Hello everyone! I am using an Arduino Uno to drive 8 LEDs, Charplieplexed with four I/O pins, using the following schematic:
http://i.imgur.com/WTZrzFH.png (The image is far too large to post inline).
While I understand the theory behind Charlieplexing, I am running into trouble when creating my routine in code to be fast, generic, and able to turn on any combination of the eight LEDs and keep them lit using, using POV techniques obviously since it's impossible to constantly have lit any arbitrary configuration of Charlieplexed LEDs. For example, I might want to have LEDs A,C, and D lit but none of the others, or I may want to flash the sequence AB-CD-GH-EF repeatedly.
Few examples I have looked up cover code beyond the basics: putting every line of code in the main program loop to illustrate charlieplexing theory. This is not my problem. My problem is that I am having trouble finding a solution that is generic and persistent.
I think that the solution would probably contain two parts: a container that could be updated anywhere in the program to hold what LEDs are desired to be on, and a routine, perhaps in an ISR, that runs constantly to enable POV and updates the LEDs. I am getting hung up trying to wrap my head around this algorithm.
Here is the code I am working with now:
//Define the LEDs. The first nibble is the port direction register, the second is the actual port output
#define LED_A 0x31
#define LED_B 0x62
#define LED_C 0xC4
#define LED_D 0x98
#define LED_E 0x32
#define LED_F 0x64
#define LED_G 0xC8
#define LED_H 0x91
///////used by the SetOutputs function//////////////
byte leds[] = {LED_A,LED_B,LED_C,LED_D,
LED_E,LED_F,LED_G,LED_H};
byte ledsEnabled = 0x00;
////////////////////////////////////////////////////
void setup()
{
Serial.begin(9600);
ledsEnabled = 0x0F;
}
void loop()
{
SetOutputs();
}
void SetOutputs()
{
PORTB &= 0x00;
for(int i = 0; i < 8; i++)
{
// Serial.println(i);
// Serial.println((ledsEnabled & (1<<i))>>i);
// Serial.println();
//check to see if the led is enabled
if((ledsEnabled & (1<<i))>>i == 1)
{
WRITE_LED(leds[i]);
delayMicroseconds(10);
}
}
}
void WRITE_LED(byte LED)
{
DDRB &= 0x00;
DDRB = (LED & 0xF0) >> 4;
PORTB = (LED & 0x0F);
}
//void LED_ON(byte LED)
//{
// DDRB &= 0x00;
// DDRB = (LED & 0xF0) >> 4;
// PORTB |= (LED & 0x0F);
//}
//void LED_OFF(byte LED)
//{
// DDRB &= ~(LED & 0xF0) >> 4;
// PORTB &= ~(LED & 0x0F);
//}
It works nicely for what I have now: lighting the first column (A-D) of LEDs, but if I need to do anything fancier, say, alternating the first and second column of LEDs, it is not up to the task. That is what I need help with.
I am using direct port access to speed up and synchronize the outputs (especially the direction registers to enable quick tri-state switching which enables the charlieplexing technique) and to keep the program size down - I plan to implement this on an ATTiny85, but an Uno is easier to prototype with.
Any help is welcomed and appreciated I'm always able to find great answers on this forum!
Thanks!