Training #1: Overload + Recovery = Improvement

The first in a series of posts on cycling training. 

Humans are quite adaptable, and we take advantage of that adaptability when we work out. Or, we *try* to take advantage of it, but we often don’t do a very good job of it, because we misunderstand how things work. It’s really quite simple:

Overload + Recovery = Improvement

Overload means applying training stress that exceeds what your body is already accustomed to.

Recovery is the time after the workout when you get better.

Improvement is when you get better.

When you first start riding, this is easy to do; you aren’t used to riding at all, so pretty much anything that you do overloads your system, and you improve. Over time, your body adapts to the way that you are working out, and your improvement plateaus. If you keep training the same way you were training in the past, you won’t see the improvements that you are looking for, since you are no longer generating any training stress.

In future posts I’ll explore ways to get more overload, and how to improve recovery.


Wasting my life on riotous living

I started playing pinball before I was a teenager, and then went through high school in the heyday of the arcade. Asteroids, Defender, Centipede, Robotron 2081, Tempest – I played them all, along with every pin that came along.

One afternoon, when I was heading out to the arcade, my mother asked where I was going, and when I told her, she looked at me sternly and said, “Wasting your life on riotous living, I see”.

She was kidding, but that was the phrase I always used in the future.

Today I took a trip to the Seattle Center to the Northwest Pinball and Arcade Show.

$20 to get in, and as many games as you can play for free. Played a lot of video games, and a lot of pinball as well. It was quite a bit of fun, except for the odd pin with weak flippers. There is nothing more frustrating than not being able to shoot a ramp because of a weak flipper.


DUMBo lives!

The

Digital
Universal
Metric
Board

is completed, and has been hanging in our team area for the last week or so.

Click to go to the gallery.

My original concept was to drive it directly from a serial port – that gives enough power to drive the Arduino and displays, and all you need to do is just plug it in. That is still the preferred approach if you can put the board close enough to your main computer. In our case, however, the prime location is about 30’ away from where my desk is. Another option is to go with an old laptop, but to get the metrics I wanted, it has to be always on, connect to the domain, and then you have to deal with password changes, windows update, etc.

So, a couple of Xbee 1s come to the rescue. This one is hanging through the board with the Adafruit adapter, and at my desktop I have the second XBee hooked up using a sparkfun adapter. Then, a bit of driver code on the PC to grab the metrics and send them out the serial port, and everything works.

After a few iterations, I’ve settled on a scheme for the update. The current item in the lowest list is brighter than all the others. When the current item switches, the new item blinks off for 25mS, and then turns on. That makes the change obvious without being annoying.


Information radiator…

This afternoon I got my information radiator/team status board finished.

Here’s what the completed Arduino shield looks like:

On the front, we have four seven-segment LED digits, where the digits are 1” tall. I considered using a pre-built shield that displays digits but the ones I saw all used pretty tiny digits. I would have gone larger than this but I didn’t have the power to drive a bigger one from USB. The bigger ones also tend to use higher voltages which would have meant a separate power supply.

You will also notice the absence of any LED driver chip. The Arduino is perfectly capable of running the driver chip without any any separate hardware, and some of the Maxim chips are $10+ per item.

Across the top are the 4 transistors to drive the common cathode of each of the chips; they switch the cathode to ground to turn on the digits sequentially.

Finally, on the lower-left we have a header that is used to connect the LPD8806 LED strip to the board.

If you look closely you can see some small wires soldered on the surface of the board. They connect to the headers that hook into the Arduino

 

Here’s the bottom view. Sorry it isn’t better, but I inexplicably had my camera set to super-low resolution.

The seven-segment displays have 10 pins each; the 7 segments plus the decimal point, and then two common terminals. The 8 ones connected to the segments are all connected in parallel with the blue wire, and then connected with the dropping resistor (68 ohms) to the output pin of the microcontroller. This is the top part of the board.

The bottom section has the connections for the transistors; the collectors hook directly to the common terminals on the displays, the emitters hook to ground, and then the bases hook to the microcontroller pins through a 1K base resistor.

Finally, the header for the LPD8806 strip grabs +5V and ground from the headers, and then the data and clock lines from two more microcontroller pins.

That’s 12 pins for the display, 2 pins for the LPD8806, 2 pins for serial communication giving 16 pins used. Plus one more pin for timer interrupt debugging (more on that below). I think that leaves me 3 pins free.

All the wire is 30-gauge wire-wrap wire insulated with Kynar. It’s very thin and easy to work with but still hefty enough to carry the current we need to carry, and it’s color-coded.

Wire-wrapping can be used without soldering on square pins, but most of the components here have round pins. Soldering wire that is that thin is fairly challenging, so I use my old had wire-wrapping tool that I bought from Radio Shack in the mid-1980s (and still available for about 6 bucks) to wrap the wire around the pin/wire, and then solder it. It gives a very secure connection though it is a bit tedious; 48 connections just on the blue wire to hook the display segments together.

The LED multiplexing code worked correctly pretty much right when I wrote it. But I wasn’t sure whether it was fast enough. The easy way to figure this out is to allocate one pin (pin 4 for me) to output. At at the start of the interrupt handler, set it high. And at the end of the handler, set it back low.

Now you can hook your oscilloscope up to that pin, and it will look something like this:

       ____                         ____
      |    |                       |    |
______|    |_______________________|    |____

The high portion is the time spent in the interrupt, and you can see that it’s only spending about 20% of the time in the interrupt.

Driving the LPD8806 strip

The LPD8806 strip came from Adafruit. It uses a protocol that is SPI-like, and they provide a nice library to use it. The library has two modes – one that uses hardware SPI, and one that drives the pins directly (“bit-bang”). If I had really been planning ahead, I could have used the hardware mode, but those pins were already in use. That left the bit-bang version. So, I coded it up, added a call to update it when we switched digits, and uploaded the sketch.

It worked, but there was a slight glitch in the LEDs and on the scope whenever it updated. The write was taking long enough that it was missing the next interrupt. I dropped the number of active LEDs down, and when I got down to 4, the glitch went away. On the scope I could see that I *just barely* had enough time to do four.

I don’t really have to write out the color data for all the leds at once, but that’s the only way the library works, so I’m going to be hand-rolling some code. Use the library code as a base, I ended up with the following:

void WriteByteToStrip(byte value)

{

  for (uint8_t bit=0x80; bit; bit >>= 1)

  {

    if (value & bit)

    {

      digitalWrite(DataPin, HIGH);

    }

    else

    {

      digitalWrite(DataPin, LOW);

    }

    digitalWrite(ClockPin, HIGH);

    digitalWrite(ClockPin, LOW);

  } 
}

The if-then sets the data pin to high or low, and then toggles the clock pin. This uses the digitalWrite() support in the Arduino, which is very convenient but does a *lot* of work:

  1. It has to map the number of the pin to one of the ports on the Arduino
  2. It has to create a bit mask for the appropriate bit in that mask
  3. It either OR’s the bit mask with the port to set the bit, or ANDs the complement of the bit mask with the port to clear the bit.

Take a look at wiring_digital.c to see what work it does.

If you know what pin is going to be used, this can be done much more efficiently; you can figure out what port your are using and precompute the masks to set or clear the bit, and then just update the bit with a single operation.

The code to call WriteByteToStrip() is very simple as well:

void UpdateLedStrip(int currentItem)

{

  static int ledToUpdate = 0;

  int dimAmount = (ledToUpdate == currentItem) ? 1 : 3;

  DumboItem* pDumboItem = &dumboData.m_items[ledToUpdate];

 
  WriteByteToStrip((pDumboItem->m_green >> dimAmount) | 0x80);

  WriteByteToStrip((pDumboItem->m_red >> dimAmount) | 0x80);

  WriteByteToStrip((pDumboItem->m_blue >> dimAmount) | 0x80);

 
  ledToUpdate++;

 
  if (ledToUpdate == dumboData.m_itemCount)

  {

    WriteByteToStrip(0);

    ledToUpdate = 0;

  }

This writes one one led’s worth of data (3 bytes) each interrupt, so if there are 10 leds, they will get updated at 100Hz, which is more than quickly enough. A look at the scope shows that there is plenty of time left in the interrupt handler. I can also see the terminal byte being written; some of the updates take just a little bit longer.

 

Here’s an action picture. It’s set up with 8 values, and there is a separate LED for each of those values. It will increment through the values every second or so, making the current LED brighter and showing the associated value on the LED display.


Arduino pin current reality check

If you look at the documentation for the Arduino, you will find a section that says that the Arduino can source or sink a maximum of 40 mA on any of the digital pins. This is, at best, very misleading.

I’m working on a multiplexed 7-segment display, which requires me to use 7 pins to drive the display, and then 4 pins to switch between displays. The 7 digits will go high based on what digit they want to display, and then one of the 4 “digit select” pins will be driven to turn that digit on. Each digit will only be on 1/4 of the time, but they will switch fast enough for you not to notice.

To limit the current through each segment to 20mA, there are dropping resistors for each of the 7 segments, and I need to figure out how big they should be.

Let’s see, the Arduino runs at 5V, and my display drops 3.7 volts and I want 20mA across it, so if I plug it into an LED calculator, I get 68 ohms as my value. If I had all 8 digits on at 20mA, that would put 160mA through the digit select pin, which is way above the 40mA max that Arduino (and Atmel) say I can use, so I’ll be using a transistor to switch those low.

I wire it one digit, write some code, and it all works… (the preceding has been edited for time and content).

And then I pull out my multimeter to check how much current I’m putting through the segments. Hmm. 10.5mA, quite a bit less than what I’m expecting to see. Let’s think about it a bit (this part took me far longer than I’d like to admit).

First off, the transistor collector voltage is about 0.11 volts. Adding that to the expected 3.7 volt drop of the display should give us 3.8 volts, which is pretty close to what we measure.

So, go back to the calculator, and we’ll find that we’d expect about 18mA with a 3.8 volt drop and 68 ohms. Still not what I’d expect. Hmm.

I put my voltmeter on the digital pin driving the resistor, and measure 4.5 volts. Back to the calculator, play with the numbers, and 4.5 volts and 10.6 ohms does give us 68 ohms.

So, when is 5 volts not 5 volts, but 4.5 volts?

This is one of those areas when digital electronics stops being digital and becomes analog. To understand a bit about what’s going on, we need to go behind the scenes.

Inside the datasheet

Here’s the datasheet for the ATMega328 that powers the Arduino Uno.

If we look at section 28.1, that’s where we find the 40mA rating and the 200mA maximum rating mentioned on the Arduino site. But that’s only part of the story.

What we really want to do is head over to section 29.4.8, “Pin Driver Strength”. We’ll start with figure 29-160, which shows the relationship between the output voltage and the current on a pin when we are sinking (sending current to ground). There are different curves for different temps (-40C, 25C, and 85C) if you want the details, but if we stick with the 25C one, we see values like this:

Current Voltage
5mA 0.12V
10mA 0.24V
15mA 0.35V
20mA 0.47V

Figure 29-162 gives the curves when you are sourcing current:

Current Voltage
5mA 4.8V
10mA 4.7V
15mA 4.6V
20mA 4.5V

As curves go, these are pretty much straight lines. You’ll also notice that the source and sink is roughly symmetrical, much different from the TTL chips I used to use, which were good at sinking current and poor at sourcing it (16mA sink, only 2mA source).

Anyway, when I look at the graph and find the expected voltage drop at 11 mA, and find that it’s a little over 4.7 V. Which is about 0.2V more than I’m actually getting.

My best guess is that I’m seeing a little extra droop because I’m putting out 70mA total for all the digits.

If I want to hit a higher current, I can put the new values back into the calculator, and I’ll find that it suggests 36 ohms for 20mA. Though that is going to sag a lot more than the 10mA I’m getting, which will reduce the voltage, and therefore reduce the current, not giving me the full 20mA. My guess is that I’d be looking at around 30 ohms to get the full 20mA, but I’m tired of doing all these measurements, and I’ll leave it as an exercise for the reader.


Introduction to Arduino timer interrupts

I’ve been working on a project that involves driving a 4-digit 7-segment LED display. I could do it with a separate chip, but I want to do it with the Arduino. Each digit has a line to each segment, and a separate common connector. To drive all 7 segments would take 7 x 4 = 28 digital output lines, which is more than the Arduino has available.

The classical solution for this problem is multiplexing. We connect the 7 segment lines for all of the digits together, and then connect them to the Arduino output pin through a dropping resister. Which leads to a bit of an issue – if we turn on the segments to show a “3”, it will show on all of the digits.

So… We connect each common line to an output line of the arduino, and then work our ways through the digits. If we do it fast enough, all of the digits appear to be lit. The one downside – other than the extra complexity of the code – is that since each digit is only on for 1/4 of the time, it will only be 1/4 as bright. We work around this by increasing the amount of current we send through the LEDs. *Generally*, if you only light up an led for 1/4 of the time, you can use 4 times the current, but a) you should check the datasheet for the led you’re using to be sure, and b) you should only exceed the normal current when you’re sure everything is working, because if your code stops running with one digit on too bright, you will quickly fry the display.

Generally, you need the the refresh rate of the display to be greater than 100 Hz or the display will flicker. I’d aim for something like 250Hz.

The code that we would write looks pretty much like this:

void loop()
{
    for (int digit = 0; digit < 4; digit++)
    {
        /// turn all digits off
        /// set the values for the current digit to the 7 segments
        /// turn on the current digit
        /// delay a bit of time (say, 3 milliseconds)
    }
}

That will work fine if that is all that we want to do, but it has some disadvantages:

  1. If I need to do other things (such as read from the serial port), any code I write has to fit in the loop where the “delay” section goes. This will make the code more complex.
  2. If my code spends a variable amount of time, the digits will update at a variable rate, and they could flicker if things get too slow.

What I really need is a way to separate the functions – a way for the display to update at a constant rate and not get in the way of everything else that I want to do.

This is a perfect place to use a timer interrupt.

An interrupt is something that interrupts the code that is running to perform another task. Timer interrupts happen periodically, and are perfectly suited to running tasks repeatedly at a set interval. A timer is just a configurable counter that counts the whole time the microcontroller is running.  We make use of it by enabling a timer interrupt, which can be configured to generate an interrupt in the following conditions:

  1. When the counter overflows. Timer 0 and timer 2 are 8-bit timers, which means they overflow after the timer counts to 255. Timer 1 is a 16-bit timer, and it overflows after the timer counts to 65535.
  2. When the timer equals a specific value. This works only on the 8-bit timers, and each of them have two values that can generate the interrupt (named “A” and “B”).

Getting the proper interval

The clock on the arduino runs at 16 MHz, or 16,000,000 counts per second (note that running the AVR at 16 MHz requires an external crystal, as on the arduino board. AVR processes can run without a crystal, but they are limited to 8 MHz).  I want my update to happen at 1000 Hz (4 * 250Hz per digit). That means we need to have a timer that divides the clock rate by 16,000.

We could do this by using the timer overflow function of timer1. It overflows when it his 65,536, and I need it to do it every 16,000 counts, and I can get this to happen by setting the clock value to (65536-16000 = 49536). 16,000 counts later it will overflow, and then I can reset the counter to that value in the interrupt handler. 

In this case, I want to save timer 1 in case I need it for something else, so I’ll be using timer 2. But timer 2 is only an 8-bit timer, and I need to count to 16,000. What I need is a way to slow down the count…

Enter the prescaler…

The prescaler is a programmable divider that sits between the clock and the timer. For timer2 (it is different for different timers), it can be set to the following values, which give us the following counts to get 1,000 Hz:

Divisor Resulting rate Count to get 1000 Hz
1 16,000,000 Hz 16,000
8 2,000,000 Hz 2,000
32 1,000,000 Hz 1,000
64 250,000 Hz 250
128 125,000 Hz 125
256 31,250 Hz 31
1024 3906 Hz 39

We should pick the smallest divisor that lets us get a count that is less than 255, so we’ll use a divisor of 64.

For timer 2, we can use either method of generating the interrupt. We can set the counter to 6, so it overflows and generates an interrupt 250 counts later, or we can set “compare A” to 250, so it will generate an interrupt when the count gets to 250. Either will work.

Configuring the timer registers

To figure this out, you need to refer to table 17-9 in the datasheet for the Atmel ATMega328, the microcontroller used in the arduino. When we see that, we can figure out that we need to set the TCCR2B register to 0x04.

TCCR2B=0x04;

We will need to configuration the timer so that it will generate an interrupt when it overflows. A look at section 17.11.6 shows that we do this by setting bit 0 (value=1) in the TIMSK2 register.

TIMSK2=0x01;

And then finally, we need to set the initial count of the timer to 6 (though 250 is close enough to 256 that is really wouldn’t matter if we didn’t do this.

 

Here’s our initial sketch:

#include <pins_arduino.h>

void setup()
{
  Serial.begin(9600); 
 
  initTimer2();
}

void initTimer2()
{
  noInterrupts();
 
  ASSR=0x00;
  TCCR2A=0x00;
  TCCR2B=0x04;
  TCNT2=0x06;
  OCR2A=0x20;
  OCR2B=0x00;
  TIMSK2=0x01; 

  interrupts();
}

int count = 0;

ISR(TIMER2_OVF_vect)
{
  TCNT2=0x06;
 
  count++;
 
  if (count % 1000 == 0)
  {
    Serial.println("a");
    count = 0;
  }
}

void loop()
{
}

If this was working correctly, every second it will send an “a” out the serial port. We can check this by choosing Tools->Serial Monitor from the Arduino IDE. And it did.

So, now we can develop the rest of the timer code, and use the main() loop to handle the rest of the functions.


A new project

In my day job I write software on a team that is part of a large Redmond software company.

I’ve always been a fan of information radiators, as the information that is most apparent is the information that drives the behavior of team members. On my old team, we had an issue with failing tests, so I was going to build a display that we could put up in the hallway that would display the number of failing tests in LED letters. But I never got around to it.

Recently, I was playing around with a  bit of LPD8806 RGB strip – the part of the 32-led strip that was left after I accidentally hooked it up to 19V instead of 5V – and I was struck with an idea. Why not combine an LED display, a short bit of RGB strip, and a whiteboard to come up with a system that can display many different values. Here’s how it will work:

A computer will send data across USB to the display, consisting of:

  1. The slot number of the data
  2. The data value for the numeric display
  3. The RGB  color to display on the LED strip

The display will cycle through the slots; the active slot will show its value and the rgb color on the strip at full brightness, while all the other slots will show their colors at reduced brightness.

Hardware & Software

I’m going to build this as an Arduino shield. for the first version, I’m going to build my shield onto a piece of perfboard, but I may do a real version. The LEDs that I’ve chosen are 1” in height (one reason I’m going to build the display rather than just buy it), and I think they’re big enough that my shield is going to have to be bigger than the standard LED footprint.

The RGB strip is easy to drive from the Arduino, and I don’t need a lot of speed, so either the SPI version or the bit-bang version will be fine.

The 7 segment displays are a bit harder. The simplest thing is to buy a MAX7219 and drive it over SPI, but at $9 it’s fairly pricey and it takes up a fair bit of real estate. It’s also a bit too easy for the developer in me, so I instead decided that I’m going to drive the displays myself.

I’ll use 4 of outputs to drive the common terminals of the displays. I’m guessing I’ll put about 6mA per segment of the display, which would give 42mA total, which is just over what you can do with a single avr pin. But… I’m multiplexing, which means that instead of putting 6mA through the segment full-time, I’m going to put 24mA through each segment for 25% of the time. Which means I need to be able to drive around 300mA, which will require a transistor on the common pins of the display. I will also probably hook the commons to the PWM outputs so that I can control the brightness of the displays, though I’ll have to be careful to design the software so the PWM and the multiplexing don’t interfere in weird ways.

The display code will be fairly simple; a timer interrupt to multiplex at perhaps 1 KHz, and on each interrupt, I’ll flip to the next digit. I’ll probably hook up the rest of the updating to run off the timer interrupt.

That puts the code to read and decode the USB commands on the main loop.


Vacation cabin telephone thermostat

[Updated: I was mistaken as to how much work the two chips were doing]

I had a talking thermostat at my vacation cabin. You would call it up on the telephone, enter a code, and then you could turn the system on and off, change the temperature, etc. It was a bit pricey and the UI was needlessly complex, but it worked okay. Until a few weeks ago it stopped taking my calls, and when we arrived it was 36 degrees inside the house. The thermostat was somewhat functional but would neither answer the phone nor turn on the furnace.

I did a quick jury-rig of the furnace (shorted they yellow wire and the red together) so we had some heat besides the woodstove, and then later re-installed the original thermostat.

I then started looking for a replacement. Nobody seems to sell the model I have anymore, and there are some posts about poor quality control. There are other solutions out there, but they are overly complicated and seem to assume that you want to spend $350 on a thermostat. I spent $180 on the one that broke, so I’m not going there again.

I did a few searches and realized that there is a much easier approach that covers most scenarios. I don’t really need to be able to remotely set the exact temperature of the house; what I need to do is be able to switch from a setback temperature to an occupied temperature. You can do this by simply adding a second thermostat, and then build something to switch between the two thermostats.

Enter the QKits MXA065.

This is just the ticket – it hooks straight to the telephone and drives two relays. It also has local control for them. You can find this same board in a four-channel version if you would like to do more.

The chip on the left is the CM8870, which handles the telephone side of things, outputting DTMF codes. Next to it is the ATTiny2313, which handles the UI for the interface, PIN codes, ring number support, and local push buttons.

I don’t have an online schematic for this board, but this is a similar one, which I believe is from the same company.

The board is nicely made, and all it needs is 12V. That makes my job easy.

My ugly daughter board on the right has a 12-pin terminal strip. This will be used to connect the wires to the two thermostats and to the furnace. Furnaces use 24 VAC to run their electronics, so I built the traditional linear supply to get the 12V that I need for the board – a full-wave bridge, 7812, and a couple of filter caps. This was just wiring.

One thing that I don’t like about the board is that there is no provision for remote operation; if you want to switch off a channel or even check to see whether it’s on, you have to go to where the board is installed. I wanted to put a pushbutton and status LED next to the main thermostat, so it would be easy to see. I therefore attached to the board and send those to the 4-terminal strip in the upper right; that will connect the cable to the pushbutton and LED.

Here’s the back of the board. Ugly but functional.


Netduino and the Adafruit LPD8806 addressable RGB LED strip

(The library is on Github here. Look at program.cs – it has a few example animations that I cooked up. )

I picked up a Netduino and a couple of the Adafruit RGB LED strips – 1 meter of the non-addressable kind, and 1 meter of the addressable kind.

Ironically, the non-addressable one is harder to use, because you need some outboard transistors to source enough current to drive all the LEDs (which are connected in parallel), and you have to write code to set up the PWM to dim the red/green/blue channels separately (so you get the color you want).

The Adafruit site has a bit of code to set up the netduino to drive the LPD8806, which I used as a starting point:

using Microsoft.SPOT.Hardware;
...
        public static void LightStripSpi()
        {
            var spi = new SPI(new SPI.Configuration(Cpu.Pin.GPIO_NONE,
                false, 0, 0, false, true, 10000, SPI.SPI_module.SPI1));
            var colors = new byte[3 * 32];
            var zeros = new byte[3 * ((32 + 63) / 64)];

            while (true)
            {
                // all pixels off
                for (int i = 0; i < colors.Length; ++i) colors[i] = (byte)(0x80 | 0);
                // a progressive yellow/red blend
                for (byte i = 0; i < 32; ++i)
                {
                    colors[i * 3 + 1] = 0x80 | 32;
                    colors[i * 3 + 0] = (byte)(0x80 | (32 - i));
                    spi.Write(colors);
                    spi.Write(zeros);
                    Thread.Sleep(1000 / 32); // march at 32 pixels per second
                }
            }
        }

Not really the prettiest code around, but it works and worked as a starting point. Before I get into the details of the library I built, a few details on the LPD8806 strips.

The Support Library

I wrote a library to make it easier to use the strip. It has a Raw mode for those who want speed (though it’s not very fast), and animation support for those who want to do more complex things.

Raw mode

If you are interested in the most speed possible with this library, you should use raw mode. Here’s a sample:

    RGBStrip strip = new RGBStrip(32);
    strip.ClearAllRaw();                // turn off all leds
    strip.SetLedColorsRaw(0, 35, 0, 0);     // first led to dim red
    strip.WriteToStripRaw();            // update the strip

In a real use, you would create a loop that sets the leds the way you want them and then updates the strip.

If we use this code and do some timings, we’ll find that the following approximate costs:

SetLedColorsRaw()          0.00031 seconds

WriteToStripRaw()          0.00063 seconds

Code that set all 32 leds and then wrote out the values took about 0.0136, which translates to about 73 updates/second. You would obviously need some code to figure out what to set the led values to, and that will slow things down. If you wanted to do 5 meters of strip (160 LEDs), that would take you down to 20 updates/second, which really isn’t that fast. It’s slow not because we’re trying to do a lot, but because the IL that the C# compiler generates is being interpreted on the netduino, and that (plus the other things the managed runtime has to do) add a lot of overhead.

Dimming

After a few hours of working on the library, I got tired of spots before my eyes whenever I was running the animations; those LEDs are bright.

So, I added the DimFactor property to the RGBStrip class. This provides a brightness pre-scalaing for all of the color values; the colors are the same as before, only dimmer (this is only roughly true, but it’s true enough in most cases). The DimFactor setting maps to brightness as follows:

DimFactor Brightness
0 100%
1 50%
2 25%
3 13%
4 6%

The DimFactor defaults to 1 (50%)

I also hooked up the on-board pushbutton on the Netduino to cycle through the dim factors. That means you can do most of your testing at an eye-saving brightness, and then toggle it to full brightness when you want to test the final product.

To use DimMode, just call SetLedColorsRawWithDim() instead of SetLedColorsRaw(). I’ve kept both methods because the dimming adds one extra operation and slows things down slightly.

Animation Mode

Raw mode is fast for simple animations, but if you are doing complex ones, you’ll be writing a lot of code yourself. The library provides support for more sophisticated effects, where it will handle doing a smooth fade from one color value to another.

Here’s an example:

    RGBStrip strip = new RGBStrip(32);
    strip.ClearAll();

    Animator animator = new Animator(strip);

    Animation item = new Animation(0, 127, 127, 0, 0, 30);
    Animation item2 = new Animation(0, 0, 0, 127, 30, 30);

    animator.AddAnimation(item);
    animator.AddAnimation(item2);

    animator.DoAnimation(2);

Each animation is described by an Animation instance, which specifies the following:

  • The led to animate (0 through num-1)
  • The red, green, and blue values that are the endpoint of the animation.
  • The number of cycles to wait before starting the animation.
  • The number of cycles that the animation will take.

In this case, we add one animation to take the first pixel to full yellow, and then one that will start when that first one is done to take the pixel to full blue. The call to DoAnimation will run the animations until they are finished (which will take 60 cycles), and it will wait 2 milliseconds after each loop.

This is very convenient to use, but will be considerably slower than raw mode because of all the extra calculations required.

Handling the animation loop yourself

Using the start count to delay animations works well if you don’t mind setting up a whole group of animations at once, but it may be more convenient to just add animations along the way. If so, you can call DoAnimationCycle(), which does one cycle. If you take this approach, you will have to handled deciding when the cycle is complete yourself.


The LPD8806 protocol for Adafruit RGB LED Strips

I bought a meter of addressable RGB LED strip from Adafruit. It uses the LPD8806 driver chip to drive LEDs. I didn’t find a writeup of the protocol, so here’s a quick overview.

Each LPD8806 has 6 PWM outputs and can therefore drive two RGB LEDs. It has two lines for SPI input (data & clock), and two lines for SPI output (data & clock).

It is implemented in a very simple way:

  • When it receives a zero byte, it resets its byteCount to 0, and writes a zero byte on the output.
  • When it receives a byte with the high bit set (ie ORed with 0x80) and its byteCount < 6, it uses the lower 7 bits of the byte to set the output of one of the PWM outputs. It then increments byteCount to move to the next PWM output.
  • If byteCount == 6, it just sends the byte to the output.

When these chips are chained together, with the inputs of the second chip connected to the output of the first chip, they are quite easy to use. You just send a total of 3 bytes per LED, and bytes 1-3 go to the first one, 4-6 to the second, and so on.  The byte order is not GRB instead of RGB, which is presumably done so that the PCB layout is simpler.

The color value is 7 bits per color, for 128 * 128 * 128 = 2,097,152 colors.

That’s about it.

And just to repeat the note in the tutorial…

  • Adafruit buys the strip in 5 meter lengths, with connectors at both ends. When you buy a shorter length they cut it off the longer length, so if it has a connector on it, the connector may be the one on the end rather than the one on the start. If you try to hook up to a connector on the end, it won’t work.


  • Pages:1...19202122232425...35