lolshield hacking

My friend Jimmie Rodgers, maker extraordinaire has come up with a great new shield for the Arduino which he is calling the LoLshield for “lots of leds”. It’s a charliplexed array of 126 LEDs in a 9×14 grid that pops right onto an arduino. Neat!

A problem with charliplexing is brightness. Since you have to turn each led on and off only one at a time, you must cycle them very quickly and rely on persistance of vision to make it look like many are on at once. The faster you can cycle, the brighter they will seem.

Arduino libraries can be very convenient, but some are slow. Using the original routine which called PinMode() and DigitalWrite() twice for each LED, only limited brightness could be achieved. I worked out a way to use direct port manipulation instead, a process which allows you to directly set the output mode and state of the pins of the ATMega very quickly – and set multiple pins at once to boot! Check out the Arduino Port Manipulation page for more.

Here’s how it works. At the heart, we have a 2D lookup array which contains 4 values for each of the 126 LEDs on the board. The values are what needs to be shoved into the corresponding DDR and PORT registers to turn each LED on. (I used a quick processing sketch to generate this) As an example, let’s walk through the 4 values stored for LED 0, the upper-left LED. It uses pin 13 as its positive pin, and pin 5 as its ground. The values stored are:  {32, 34, 32, 0}

- first byte is the value to enable pin 13 in the DDRB register (00100000) ORed with the value to enable pin 5 in the DDRB register(00000000) (it’s in the DDRD reg so it’s just zeros) = 32
- second byte is value for pin 13 in the DDRB (00000000) ORed with the value for pin 5 in the DDRD reg(00100010) (includes keeping pin 1 enabled for serial) = 34
(These two values are ORed between the pins so that they can be set simultaneously in one assignment of each DDR register)
- third byte is the value needed to turn on pin 13 (the positive pin) in PORTB = 32
- fourth byte is the value needed to turn on pin 13 in PORTD (either the 3rd or 4th byte will always be zero since we only turn on 1 pin) = 0
(Notice there’s no ORing with these last two – we only want pin 13 high, pin 5 should stay low to sink current and provide the ground. Luckily low is the default state for a pin set as an output so we don’t have to do anything with pin 5 here)
Since the enable bit for both pins is now set in value 1 and 2, we just have to shove byte1 into DDRB and byte 2 into DDRD to enable the pins as outputs
Since the output bit for the correct pin is set in either value 3 or 4, we just have to shove byte 3 into PORTB and byte 4 into PORTD to turn the proper pin high
Now, with these values, we just have to put them where they belong, so we have been able to turn this:
void turnon(int led) {
int pospin = ledMap[led][0];
int negpin = ledMap[led][1];
pinMode (pospin, OUTPUT);
pinMode (negpin, OUTPUT);
digitalWrite (pospin, HIGH);
digitalWrite (negpin, LOW);
}
into this:
void turnonbin(int led){
DDRB = ledMapBin[led][0];
DDRD = ledMapBin[led][1];
PORTB = ledMapBin[led][2];
PORTD = ledMapBin[led][3];
}
Which seems to run faster, updating the LEDs faster, and resulting in better brightness and LED stability. Just what I was going for!
You can find my version of Jimmie’s demo code attached, along with the messy processing sketch I used to translate the original LED map into the new version.
Now, go buy a kit from Jimmie and get loling!
Arduino demo code
Processing sketch
Posted on December 29, 2009 at 5:46 pm by W. Aaron Waychoff · Permalink
In: projects · Tagged with: 

Leave a Reply