Problems w/driving 16 LEDs using PORTs [Solved]

Hello! I'm having problems with digital pins 8 and 9. When I use digitalWrite(), the LEDs connected to those pins light up fine. If I command PORTB = B00000011, they light up fine. However, if I use the function flash(), that I have written (code and context given below), they do not turn on. Please read on for a bit more explanation:

I'm using a 3.3V Arduino Pro Mini, and am creating a 16-LED POV wand to mount on my bike. The 16 LEDs are connected to digital pins 2-13, and analog pins 0-3.

I have created a function flash(byte a, byte b) that accepts two bytes, each one representing 8 of the LED states. e.g. to turn on every other LED I would call flash(B10101010,B10101010);

The function flash() takes these two bytes, and distributes the bits amongst PORTD, PORTB and PORTC by masking the required bits from the two function inputs, shifting to the position each PORT expects, and writing them, as shown below.

void flash(byte firstByte, byte secondByte)
{
  // input information:
    // firstByte B11111111, secondByte B11111111, to spread amongst ports correctly
  
  // LEDs 0-7 from firstByte map to: 
    // LEDs 0-5 > digital pins 2-7: PORTD B11111100
    // LEDs 6-7 > digital pins 8-9: PORTB B00000011
  
  PORTD = (firstByte & B00111111) << 2;        // take  first 5 LEDs from firstByte 
                                               // shift two bits left to match PORTD, and write 
  PORTB = (firstByte & B11000000) >> 6;        // take last 2 LEDs from firstByte
                                               // shift 6 bits right to match PORTB, and write
    
  // LEDs 8-15 from secondByte map to:
    // LEDs 8-11 > digital pins 10-13: PORTB B00111100
    // LEDs 12-15 > analog pins 0-4:   PORTC B00001111
    
  PORTB = (secondByte & B00001111) << 2;        // take the first 4 LEDs from secondByte 
                                                // shift two bits left to match PORTD, and write
  PORTC = (secondByte & B11110000) >> 4;        // take last 4 LEDs from firstByte
                                                // shift 6 bits right to match PORTB, and write 
}

The function works fine for all the LEDs, I can create some excellent patterns using it, except that two of the LEDs won't work. Why won't this flash() function illuminate digital pins 8 and 9, when digitalWrite() will? I'm at my wits end ... does anyone have any ideas? I kneel before the mighty collected knowledge of these forums :slight_smile:

(Bonus question: to make a POV-toy, do I even need to use bit manipulation? I could write a monster piece of code for the flash() function that takes every bit individually and uses digitalWrite() 16 times. Would this effect the visibility of the shapes and letters traced?)

Maybe a dumb question but did you initialise the pin mode to output before using the flash() function

not dumb at all, all this port manipulation isn't so intuitive, initialising pins is so easy to forget. This time, however, I did remember:

  // declare all LEDs as outputs  
  DDRD = DDRD | B11111100; // digital pins 2-7 output (leaving 0 and 1 TX/RX)
  DDRB = DDRB | B00111111; // digital pins 8-13 output (two high bits unusable)
  DDRC = DDRC | B00001111; // analog pins 14-17 output, 18 input

I think I've initialised all the pins correctly

  PORTB = (firstByte & B11000000) >> 6;        // take last 2 LEDs from firstByte                                     
...
  PORTB = (secondByte & B00001111) << 2;        // take the first 4 LEDs from secondByte

You are writing out two pins from the first byte to PORTB, but then immediately overwriting them with zero in the line which writes bits from the second byte. You need to bitwise-or the two together first and just write them once.

hahaha YES! Thank you :smiley:

good lord i can't thank you enough. yay! i'll post some shiny pictures when this rig is attached to my bike.

:slight_smile: :slight_smile: :slight_smile: