Multiplexing leds and some coding

A project log for W-Ring

An RGB led Clock-Ring

One of the most important things in this project is the display, 3 rgb leds, but 3 rgb leds means 3 * 3 colors = 9 pins. One solution is a charlieplexed arrangement, which allows me to use only 4 pins

so in theory, playing with different pin digital outputs and inputs is possible to turn an specific color.

So let's code a bit:

first I need a function that turns all off:

```// turn all pins off by putting them in a high impedance state
void turnOff(){
pinMode(PIN0, INPUT);
pinMode(PIN1, INPUT);
pinMode(PIN2, INPUT);
pinMode(PIN3, INPUT);
}```

The pinMode function allows to set a pin as a 0/1 (OUTPUT) or as a high impedance state (INPUT). Setting it as an input is like turning that pin off, no digital data coming out that pin.

So now I need a function for control which color of which led turn on, so there is:

```// turns on one led one color at time, 3 available leds and 3 available colors (0 = BLACK, 1 = RED, 2 = GREEN, 3 = BLUE)
void turnOn(byte led, byte color){

//turn all pins off
turnOff();

switch(led){
case 0:
// set the common cathode on
pinMode(PIN0, OUTPUT);
digitalWrite(PIN0, HIGH);

// set the mapped pin to off
if(color == 1){
pinMode(PIN1, OUTPUT);
digitalWrite(PIN1, LOW);
}

if(color == 2){
pinMode(PIN2, OUTPUT);
digitalWrite(PIN2, LOW);
}

if(color == 3){
pinMode(PIN3, OUTPUT);
digitalWrite(PIN3, LOW);
}
break;

case 1:
// set the common cathode on
pinMode(PIN1, OUTPUT);
digitalWrite(PIN1, HIGH);

// set the mapped pin to off
if(color == 1){
pinMode(PIN2, OUTPUT);
digitalWrite(PIN2, LOW);
}

if(color == 2){
pinMode(PIN3, OUTPUT);
digitalWrite(PIN3, LOW);
}

if(color == 3){
pinMode(PIN0, OUTPUT);
digitalWrite(PIN0, LOW);
}
break;

case 2:
// set the common cathode on
pinMode(PIN2, OUTPUT);
digitalWrite(PIN2, HIGH);

// set the mapped pin to off
if(color == 1){
pinMode(PIN3, OUTPUT);
digitalWrite(PIN3, LOW);
}

if(color == 2){
pinMode(PIN0, OUTPUT);
digitalWrite(PIN0, LOW);
}

if(color == 3){
pinMode(PIN1, OUTPUT);
digitalWrite(PIN1, LOW);
}
break;
}
}```

What this function does is to turn on one led one color (R/G/B) at time turning off the rest, so lets test it:

Now we want to represent decimal numbers as an octal color coded ones:

```void drawNumber(int number, int milliseconds){

float startedMilliseconds = millis();

// run the while for the time set
while(startedMilliseconds + milliseconds > millis()){

// loop for each led
for(int i = 0; i < 3; i++){

// n is the octal number corresponding to ith digit, this is the main decimal to octal conversion
int n = (number/round(pow(8, i)))%8;

// loop for each binary digit on n
for(int j = 0; j < 3; j++){
// we get the jth binary digit and check if is a 0 or a 1, turning on or off the corresponding color, for example 5 = 101 which would turn red and blue = magenta
if((n/round(pow(2, j)))%2 == 1){
turnOn(i, j+1);
}else{
turnOn(i, 0);
}

}
}
}
turnOff();
}```

We run the function in a while loop for the time that we want the leds turned on, after that, we convert the digital number ("number" variable) into 3 octal digits, each one corresponding to one led, this digit is called "n". Now we get the n and we decompose it into binary digits in the second loop. How the n is a number between 0-7, we only need 3 binary digits. Each binary digit is represents a RGB color on a led so for example the 5 = 101 would turn on the red led, would turn off the green led and turn on the blue, so we would get magenta. Let's see it in action:

And that's, sorry for the terrible quality, I had to compress the gif

So now, we can get any number between 0 - 511 and show it with 3 RGB leds and 4 microcontroller pins!

Stay tuned for the next log

Discussions 