Muxing 2 rgb led's in software

Hello, I'm trying to do a simple rgb led muxing, so to control 2 rgb led's with different colors I would only need 3 pwm channels, but after a lot of trials with and without delays there is always a lot of color mixing, take this example:
I set one led to full red, and another to full blue, but due to the bad muxing i get a bit of red in the "blue" led and a little of blue in the "red" led.

Here is my code, can someone help me?

void setup() {
  pinMode(2,OUTPUT);  //software mux
  pinMode(3,OUTPUT);
  digitalWrite(2,HIGH);  //start with the two leds turned off, they are common cathode, so putting a pin high turns the led's off
  digitalWrite(3,HIGH);
}

void loop() {

  led();            // simple function to turn the 2 led's off, should improve flicker, but doesn't work really well
  delay(8);
  
  digitalWrite(2,LOW);  //turns on led number 1
  digitalWrite(3,HIGH);

  analogWrite(9,0);
  analogWrite(10,255);      //full blue on one led
  analogWrite(11,0);
  
  delay(10); 
  
  led();            // simple function to turn the 2 led's off, should improve flicker, but doesn't work really well
  
  delay(8);
  
  digitalWrite(2,HIGH);  //turns on led number 2
  digitalWrite(3,LOW);

  analogWrite(9,255);      //full red on the another led
  analogWrite(10,0);
  analogWrite(11,0);
  
  delay(10);
}

void led(){
  digitalWrite(2,HIGH);
  digitalWrite(3,HIGH);   
}

Seems strange. How about if you also turn the PWM outputs off (analogWrite(pin,LOW) ) between switching LED's?

Btw, you haven't defined the PWM pins as outputs in setup, but I guess it doesn't matter?

If i just use one led, everything works fine, the pwm works perfectly because I have already used some pots and the adc to vary the pwm duty cycle and they work fine even without initializing the pwm's.

I think I could use the digital pins to drive each anode and do the pwm in the catode, is this possible?

Just take care so you don't draw too much current from the arduino pins. Absolute max is 40mA (atmega 168/328), but its not recommended for continuous operation. About half of that is better. Also total max is 200mA for the atmega (and all pins combined), so you cannot sink or source 20mA on all pins simultaneously anyway.

Since your LED's are common cathode, it wouldn't do much good PWM'ing the cathodes, unless you want all colors preset in the schematics.

Ah, I'm mistaken, it's not so strange you get artifacts when doing it like this. I just remembered, PWM uses a frequency of about 450 - 500 Hz, and I guess your multiplexing is much too fast in relation to the PWM control of the LED's. Also I'm not so sure how delay() affects PWM, my guess is it stops during the delay.
I think you should look inte the blink without delay example somewhere in the playground for an example of not using the delay() function. If you multiplex much slower than the 500 or so Hz, I think it should work, which shouldn't be a problem. You might still have to turn the PWM pins off (low) between switchin LED's though. I haven't done it exactly like this before so I'm not sure.

I will try it, can you show how have you done it by your way?

No one?

I'm not going to clam to be an expert... but I agree with raron. I think.

the PWM is already turning the pin on and off at a speed based off of 0 - 255. but when you combine that with multiplexing where you are already turning them on and off at a fast speed, might be mixing and getting strange results..

I would scratch the pwm and switch to HIGH - LOW. to see if it works that way.

then may have to figure out an algorithm to base the delay off of the pin value (0 - 255)

I'm trying to think it through, but I could be totally wrong.. (more than likely am)

why is your delays so high? I usually run mine around 1 or 2 for multiplexing.

The value of the delay is just a result of experiments, that values are the ones that offer the least amount of "flicker", but i can't in no away make it disappear :frowning:
I think that muxing this away should work just like any other led array, or am I wrong?
Could any of you post a method of a working muxing, even if it is not for rgb led's?

i think i may be wrong… with what i said but i am getting a small flicker on one led… the other two are fine. two blues work but the one green flickers ever so slightly…

this is what i coded out real fast between my last post and now.

int colpins[] = {3, 5, 6, }; // power pwm 
int rowpins[] = {12, 11, 10, }; // ground

void setup(){
 for (int pin=0; pin< 3; pin++) {
  pinMode(colpins[pin], OUTPUT);
  pinMode(rowpins[pin], OUTPUT);
 }
  
}
float ms = .2;
int ledlist[] = {1, 1, 0,};
int pwm = 0;
void loop(){
  
  delay(ms);
  
 // for (int i = 0; i < 3; i++) {
  
      //digitalWrite(colpins[i], HIGH);
      //digitalWrite(rowpins[0], HIGH);
  
   // }
   analogWrite(colpins[0], pwm);
   analogWrite(colpins[1], pwm);
   analogWrite(colpins[2], pwm);
   digitalWrite(rowpins[0], HIGH);

  delay(ms);
  for (int i = 0; i < 3; i++) {
 
      digitalWrite(colpins[i], LOW);
      digitalWrite(rowpins[0], LOW);
    }
  delay(ms);
     analogWrite(colpins[1], pwm);
   analogWrite(colpins[2], pwm);
   digitalWrite(rowpins[1], HIGH);
  pwm += 1;
  delay(ms);
  for (int i = 0; i < 3; i++) {
 
      digitalWrite(colpins[i], LOW);
      digitalWrite(rowpins[1], LOW);
    }
  delay(ms);
  
  
}

ya Idk, i think i'm going to stick with Delay is conflicting with PWM.

Tomorrow I will try to use millis() instead of delay and see the effects, and also study the code provided by you, thanks to everything :wink:

Hi guys. I did a quick test just now. It's not optimized in any way, but it kinda works for this particular situation (some flicker though)

But let me just say this is not the way to multiplex stuff. It's not perfect, but as close I came for the moment, built on OP's code. Also note I did in fact use a slight delay(1) in the middle, so it's not entirely free of the delay() function, this was just to keep it as simple as possible.

I have common anode RGB LED's, so I inverted some of the values.

long timer;
const long muxInterval = 10; // How long each LED is on, in ms

int mux = 0; // Counter to keep track of which LED is on


void setup() {
  pinMode(2,OUTPUT);  //software mux
  pinMode(3,OUTPUT);
  digitalWrite(2,HIGH);  //start with the two leds turned off, they are common cathode, so putting a pin high turns the led's off
  digitalWrite(3,HIGH);
  timer = millis();
}

void loop() {

  if (millis() - timer > muxInterval)
  {
    timer = millis(); // reset for next time
    mux++; // next LED
    if (mux > 1) mux = 0;
    led(); // turn off both leds
    analogWrite(9,255); // also turn fully off (or fully on for common anode) all the colors
    analogWrite(10,255);
    analogWrite(11,255);
    delay(1);
    if (mux)
    {
      analogWrite(9,255);
      analogWrite(10,0);  // full blue on one led
      analogWrite(11,255);
      digitalWrite(2,LOW);  // turns on led number 1
      digitalWrite(3,HIGH);
    } else {
      analogWrite(9,0);        // full red on the another led
      analogWrite(10,255);
      analogWrite(11,255);
      digitalWrite(2,HIGH); // turns on led number 2
      digitalWrite(3,LOW);
    }
  }
    

}

void led(){
  digitalWrite(2,LOW);
  digitalWrite(3,LOW);
}

EDIT: typos and stuff

I should use millis() in my code.. so millis might help.

Raron, why do you say that this isn't the way to multiplex the leds?
Maybe I should look into the projects using tlc5940's and see how people do good multiplexing?
Thanks for the help :wink:

Because the PWM is not synchronized to the multiplexing of the LED's. To do that you should really write your own PWM and multiplexing algorithm.

Thanks for the help

No problem. I just wanted to test this a bit myself. The above hackk doesn't seem to work well with cycling colors btw.
Also, delay() doesn't interfere with PWM outputs. Thats nice to know.

For an example of how I did it with an 8 by 8 RG (no blue) LED matrix you can look at this thread: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1256090448. Lots of other similar threads too. But there I used some external IC's to minimize connectiosn to the arduino, and the code isn't optimized. I've since improved it using direct port manipulation, but I'm not finished with it yet (TTT :P).

I will have some school exams this week and in the next one so, need to put the arduino aside during some days, but after that I will see if I can learn how to do software pwm and try to put this working, and I will read your post too :smiley: