Multiplexing RGB-LEDs

Hi there, i just started with arduino and the only stuff i ordered with it where a couple of resistors and 3 RGB leds to tinker a little.

I found it a bit frustrating that each of these leds need 3 pwm pins, so i thought i try multiplexing them.

My question is, do i have this worked out right (code and wiring)? There still is minimal flicker - and i guess there must be some improvements, since i saw people doing it with much more leds with less flicker.

int leds[3] = {5, 6, 7};
int ledNr = 3;
int R = 4;
int B = 3;
int G = 2;

int poti = 0;
int potval = 0;

void setup() {
  pinMode(R, OUTPUT);
  pinMode(G, OUTPUT);
  pinMode(B, OUTPUT);
  for (int i = 0; i<ledNr; i++)
    pinMode(leds[i], OUTPUT);
}

void drawLed(int led, int red, int blue, int green) {
  analogWrite(R, 0);
  analogWrite(B, 0);
  analogWrite(G, 0);
  delay(2);
  for (int i = 0; i<ledNr; i++) {
    if (leds[i] == led)
      digitalWrite(leds[i], LOW);
    else
      digitalWrite(leds[i], HIGH);
  }
  analogWrite(R, red);
  analogWrite(B, blue);
  analogWrite(G, green);
  delay(3);
}

void loop() {
    drawLed(leds[0], 0, 255, 0);
    drawLed(leds[1], 255, 0, 0);
    drawLed(leds[2], 0, 0, 255);
}

Thank you for your help!
Jan

Wiring:

(sorry for that ugly painting and the second post, seems like one is not allowed to post images and links in your first post oO )

EDIT: just changed the setup to use PWM-ports for R, G and B but it still flickers…

Why the delay after analogue writing?

I don’t think you have the right idea about multiplexing as far as the software is concerned. You need to activate each row in turn and while it is activated turn on the columns. Then turn the columns off before you turn on the next row. You can swap row and column in that above.

Look at how I have done it in:- Econo Monome

Thank you for your reply!
i indeed had a lot of bloat-code there, further, using digitalWrite instead of analogWrite removed 99% of flickering :), here is my current code:

int leds[3] = {7, 8, 9};
int ledNr = 3;
int R = 6;
int B = 3;
int G = 5;

void setup() {
  pinMode(R, OUTPUT);
  pinMode(G, OUTPUT);
  pinMode(B, OUTPUT);
  for (int i = 0; i<ledNr; i++)
    pinMode(leds[i], OUTPUT);
}

void drawLed(int led, int red, int blue, int green) {
  digitalWrite(led, LOW);
  digitalWrite(R, red);
  digitalWrite(B, blue);
  digitalWrite(G, green);
  delay(1); // This is not neccecary, but increases the brightness significantly without making it flicker!
  digitalWrite(R, 0);
  digitalWrite(B, 0);
  digitalWrite(G, 0);
  digitalWrite(led, HIGH);
}

void loop() {
  drawLed(leds[0], 0, 255, 0);
  drawLed(leds[1], 255, 0, 0);  
  drawLed(leds[2], 0, 0, 255);
}

Looks like you had the PWM beating with the multiplexing rate. I would actually try and increase that delay.
Better still make it leave the write routine with the LEDs on and only turn them off when you enter the refresh routine and have to change the data.

Also if you are looking into the bright point of the LED you are inclined to perceive more flicker than if you look at the LED through some sort of diffuser.

The way I solved the beat freqency issue was to not use hardware PWM at all. For example with your 3 LEDs, insead of scanning through a loop 3 times, scan though 6 times. If the LED is supposed to be dim, only light it during its turn the 1-3 phase, if it’s supposed to be bright light it in 1-3 and 4-6. That gives you off, medium, bright. And you can extend it. The implemenation details might be a bit tricky, but overall it’s not hard to do it that way.

thanks for the advice, but as it turns out, my problem wasn’t solved by just using digitalWrite - it works in the given example, but digital write does just do HIGH or LOW (0 or >0), so i still cant mix any colors on the leds steplessly :frowning:

EDIT: @Oracle: I’ll try out your idea as well, but i would really like to mix as much colors as possible… Maybe i’ll better get some of these LED controller-thingys (TTLC5940), but i have no idea how to use them or where to get them cheap in germany…

When you PWM the LED with the hardware PWM, you are flashing it on and off very quickly and controlling the duty cycle.

When you multiplex, you are scanning through the rows of your matrix, in effect each row is flashed on and off very quickly.

What will happen is you’ll have periods of time when the off parts of the PWM match up with the off times in multiplexing a bit too much, and the LED will seem dimmer. And times when with on PWM match up with the on for the multiplexing and the LED will seem brighter.

This will make the LED appear to flicker, as you described, and the technical term for this is “beating” or “hetrodyning”

Ever notice how when you point a video camera at a CRT, you get a bright band moving up or down? It’s the same effect.

You have to either synchonize the PWM and Multiplexing or use a chip like the TLC5940 which avoids multiplexing entirely. Or for 9 LEDs, just use 9 IO lines and skip the multiplexing.

(TTLC5940), but i have no idea how to use them

see:-
http://www.thebox.myzen.co.uk/Hardware/Mini_Monome.html
for an example of how to multiplex with them.

where to get them cheap in germany.

http://www.farnell.com/
And pick the German flag.

@Oracle:
Now i got it, thank you!
One last question:
What are these chips (like the TLC5940) generally called? I can’t find a place to get these.

The TLC5940 is an “LED Driver” :wink: