.NET Gadgeteer + Lady Ada(fruit) = blinky goodness!

I took last Friday off and, since I didn’t really feel like working on any of the 97 side-projects I should be working on, I messed around with one I felt like working on. In particular, a digital-addressable RGB LED strip I picked up a few months ago at adafruit.com, driven by a FEZ Spider .NET Gadgeteer board (I’ve got their starter kit, which includes a ton of stuff) by GHI Electronics.

Controlling RGB LED strips isn’t anything new – you can find a ton of websites on how to do this with an Arduino-type boards – but I haven’t seen much for doing this type of thing with a Gadgeteer board, so I figured I’d write it up.

Here’s the end result, a shaky washed-out video of it running through some test sequences. Pretty happy with the way it (the project, not the video) came out, especially with the fading stuff seen towards the end..

Digression about .NET Gadgeteer

.NET Gadgeteer is some pretty cool stuff. If you’d like to get a bit into playing with Arduino-type boards but are intimidated by electronics and the development environments make you want to scream, it’s worth checking out .NET Gadgeteer. The libraries & framework are all open source. The basic IDE is free and totally spanks everything else out there – it’s really quite nice and is the same environment I use to write code for our big machines (hardware duplexed, 64-core, 1/4TB of RAM, etc) at work. Threads, timers, live debugging with breakpoints and looking at variables and all that stuff, on a little microcontroller.

Not having an electronics background, one of my favorite features is that .NET Gadgeteer and its IDE let you just drag components into your project then say “connect modules” and it lays out all the connections for you. If you try to do something it doesn’t like (such as using 5 COM ports when your board only supports 3) it will yell at you and let you make changes.

Here’s a picture of something I just whipped up by creating a new project for a FEZ Spider and dragging in an accelerometer, SD card, camera, OLED display, compass, joystick, gyro, 4 daisy-chained RGB LEDs and a button. Then I did the “connect” option and get…

Image

Showing a MSDEV .NET Gadgeteer project that has nothing to do with LEDs (click for bigger version)

…all the modules connected. The IDE even adds all the right libraries and variables for these modules so, once you hook up your hardware just like the picutre, you just get to start using it all, right away. Nice!

Back to the blinky lights: Hardware

So, you may be asking yourself, if this Gadgeteer stuff is soooo easy and there’s lots of stuff online about RGB LED strips, why aren’t there many things about RGB LED strips with Gadgeteer?

The answer’s pretty easy: if you look online at Gadgeteer boards, they all only have Gadgeteer sockets on them. These standardized sockets make it really easy to connect up Gadgeteer modules – the wires I use to hook up a color touchscreen are the same that I’d use for a GPS module – but LED strips just have some solder pads on them. No fancy sockets. This isn’t really a big deal but it means a few extra steps. An hour of head scratching and some googling was all it took to get me going.

The first step was reading through the tutorial at adafruit.com, which explains how to solder the LED strip up and even provides a little .NET MicroFramework (which is similar to .NET Gadgeteer) sample code.  The important bit there, aside from knowing what to solder, was finding that you talk to the LED strip using some protocol called SPI.

Not knowing anything about SPI, I googled some more and found the Gadgeteer Socket Types page and, from there, the page on SPI sockets and how they should be wired up. Comparing this SPI layout and the Adafruit guide, I see enough to match up the 4 solder pads on the LED strip with the socket: 5V, GND, MOSI and SCK. MOSI is basically SPI output – from the Gadgeteer mainboard to the device (LED strip) – and SCK is a clock signal, which keeps things in sync.

Part of the Spider starter kit I got included some ‘extender’ modules that are designed for exactly what I need to do at this point: connect something that needs soldering to a Gadgeteer socket. You can see one here – two sockets and space for a .1 header. The 5V and GND spots are nicely labled and from the SPI page, I can see that P7 is MOSI and P9 is the clock.

The headers I’m using are these but you can find them almost anywhere, cheap. You just count off the number of pins you need (10 in my case) and snap off a strip that length with some pliars. Push the short ends into the holes, secure with a bit of tape (or helping hands or whatever) and solder them in. I could have snapped off 4 individual pins and soldered just those in but these things are so cheap I figure I’ll do all 10 and have an extender I can use for anything, later.

Also needed is some wiring to go from the strip to the extender module. I’m using some female jumpers wires, which you can also find just about anywhere. I’ve taken 4 different colored wires and snipped them in half . The cut end gets soldered to the LED strip per the Adafruit guide and the end with the female jumper still on it gets plugged into the extender:

Last on the hardware front is power. The Adafruit page makes it very clear that a little microcontroller isn’t going to have enough juice to drive these LED strips and that you’re going to need some sort of external power supply.

On the Gadgeteer end, I’ve got a USB Client DP module, which came with my kit. This is a nice little module that lets you use just USB for projects that don’t need a lot of power (and also using USB for deploying and debugging) and you can also hook up external power supply, for when you need a bit more. The web page for this module says you can use anything from 7V to 30V so I’m going to use a 12V supply I have lying around.

The software

With all the hardware done, which took an hour or so but would now take me about 10 minutes, now that I’ve done it once and have the links to the Gadgeteer socket specs, I get to write code, which (for me) is much more fun..

I’m not going to post it all here. GHI (makers of the Gadgeteer board I’m using) has a place for such things but they’re doing some renovations and it’s read-only right now. It should be up in a few days – I’ll post it there and update this blog with the link, once they’re back up. (edit: driver code now at the tinyclr.com site)

I will post some of the interesting bits of the test program, though. Here’s the startup portion, slighly edited to just have the relevent parts:

private LedStripLPD8806 mLedStrip;

void ProgramStarted()
{
    GT.Socket socket;
    socket = GT.Socket.GetSocket(mExtender.ExtenderSocketNumber, true, mExtender, null);

    mLedStrip = new LedStripLPD8806(socket, 32);

    FlashTest(null);
}

First, I declare a member variable for my LED strip driver class called mLedStrip. Any time I want to mess with the LEDs, I’ll reference this object. The constructor of this class takes a generic Gadgeteer “socket” instance so I call GetSocket on the mExtender object (which the IDE created for me in a drag/drop scenario like the picture back up at the top of this post) to get the underlying socket. Once I’ve got that, I create the mLedStrip instance, passing it the socket and the number of LEDs. That’s all that’s really needed – the rest of the code just uses methods on mLedStrip.

Back to the video, the test program does the follow things:

  1. flash all LEDs to red then green then blue
  2. ‘scale’ all the LEDs (light one at a time, from first to last then turn them off in reverse order) on red then green the blue
  3. change each LED in the strip to a random color (100 times)
  4. fade from whatever the random test left on the strip to solid red. Then fade to green then blue
  5. fade to random colors
  6. all LEDs off

Here’s the video again, along with some of the code that does the steps above:

Here’s the flash test. Note that mLedStrip is called with just color values – there’s nothing saying which LED I want to light. This tells the driver to set all the LEDs in the strip at the same time.

private void FlashTest(object o)
{
    for (int test = 0; test < 3; test++)
    {
        int r = test == 0 ? 32 : 0;
        int g = test == 1 ? 32 : 0;
        int b = test == 2 ? 32 : 0;

        mLedStrip.Set(r, g, b);
        Thread.Sleep(250);
    }

    mLedStrip.TurnOff();
    ScalesTest();
}

The scales test is similar but this time I set each LED individually. First to set the color up the strip then back down the strip to turn each one off. The driver code pushes colors to the strip right away unless you tell it otherwise so you can update any particular LED, just calling mLedStrip.Set.

private void ScalesTest()
{
    for (int test = 0; test < 3; test++)
    {
        int r = test == 0 ? 32 : 0;
        int g = test == 1 ? 32 : 0;
        int b = test == 2 ? 32 : 0;

        for (int i = 0; i < NUM_LEDS; i++)
        {
            mLedStrip.Set(i, r, g, b);
            Thread.Sleep(5);
        }

        for (int i = NUM_LEDS - 1; i >= 0; i--)
        {
            mLedStrip.TurnOff(i);
            Thread.Sleep(10);
        }
    }

    RandomTest();
}

For flashing random colors, each LED gets a different color and I want to the whole strip to flash at once so I needed a way to tell the driver to update a bunch of LEDs, without it pushing the data to the strip. BeginUpdate and EndUpdate do just this. BeginUpdate tells the driver not to push anything out – it just updates the color values in memory. EndUpdate tells it that you’re done and want to push the color data in memory to the strip.

The driver also can take a integer with red, green and blue encoded into it – I’m using that here with the output of the RandomColor method, which returns a semi-random set of colors in an int.

I’m also testing the indexer method of the driver. Indexers are a great feature of the C# language that let you define a method for what to do when a caller treats you like an array. The mLedStrip variable isn’t an array but I’ve written the code so that if somebody calls it like an array, like “mLedStrip[led]” below, it acts like Set (used above to set one LED) on the LED being indexed. Hard to explain but a really nice language feature, once you get it..

private void RandomTest()
{
    for (int i = 0; i < 100; i++)
    {
        mLedStrip.BeginUpdate();

        for (int led = 0; led < NUM_LEDS; led++)
        {
            mLedStrip[led] = RandomColor();
        }

        mLedStrip.EndUpdate();
        Thread.Sleep(10);
    }

    StartFadeTest();
}

After this are the fade tests, which is split into 2 pieces. Since the driver needs to push out a bunch of updates during the fade – one for each change in the colors – it uses a timer that fires at some specified interval. I don’t really want the test program to block while this happens so I’m using a C# event to tell the driver how to let me know when the fade completes:

private void StartFadeTest()
{
    mFadeTestNumber = 0;
    mLedStrip.OnFadeComplete += NextFadeTest;
    NextFadeTest(null);
}

The 2nd line above probably looks funny if you’re a C/C++ person. Underneath, a C# event is sortofa list of function pointers. You add callbacks to the list with += and remove them with -=. On the driver side, I just call OnFadeComplete like a method and the framework invokes any methods that opted in with a +=. So, basically, that line tells the driver to call NextFadeTest() whenever a fade completes.

The 3rd line manually calls NextFadeTest to prime the loop.

private void NextFadeTest(object ignored)
{
    if (mFadeTestNumber < 3)
    {
        // first few times through, fade to solid r, g or b
        int r = mFadeTestNumber == 0 ? 63 : 0;
        int g = mFadeTestNumber == 1 ? 63 : 0;
        int b = mFadeTestNumber == 2 ? 63 : 0;

        mLedStrip.InitFade(2500);
        mLedStrip.FadeTo(r, g, b);
        mLedStrip.StartFade();
    }
    else if (mFadeTestNumber < 20)
    {
        // fade to random colors; one second fade with 40 steps (25ms) each
        mLedStrip.InitFade(1000, 40);
        for (int i = 0; i < NUM_LEDS; i++)
        {
            mLedStrip.FadeTo(i, RandomColor());
        }

        mLedStrip.StartFade();
    }
    else
    {
        // all done - turn the strip off
        mLedStrip.TurnOff();
    }

    mFadeTestNumber++;
}

Two versions of InitFade, which sets up the fade in the driver, are used above: InitFade(2500) tells the driver that I want to do a fade sequence which will take 2.5 seconds. The other, InitFade(1000, 40), tells the driver that I want a fade that will last 1 second and have 40 steps in it. The version without the number of steps parameter will do the math so that 50ms (1/20th of a second) steps are used, which looks fine to me.

After InitFade, the FadeTo method is called for each LED that you want to participate in the sequence. If you don’t call FadeTo on a particular LED, it just stays the same color. Like the Set method used above, FadeTo has 2 versions, one to do the whole strip at once and one to do a particular LED.

Once all the LEDs are set to fade where I want, I just call StartFade and return. The driver will call this method again, once the current fade is complete..

That’s pretty much it.. Fun stuff to play with!

About these ads
This entry was posted in .NET Gadgeteer. Bookmark the permalink.

6 Responses to .NET Gadgeteer + Lady Ada(fruit) = blinky goodness!

  1. Pingback: .NET Gadgeteer + Lady Ada(fruit) = blinky goodness! « adafruit industries blog

  2. devhammer says:

    Awesome, Dave. This is great stuff…can’t wait to get my hands on some LED strips so I can try my hand at this. Thanks for sharing!

  3. Dave Durant says:

    Let me know how it works!

  4. Gary says:

    I like it! Nice job Dave.

  5. Agustin says:

    Pretty nice post. I just stumbled upon your blog and wished to
    say that I’ve truly enjoyed surfing around your blog posts. In any case I will be subscribing to your rss feed and I hope you write again soon!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s