
simulate this circuit – Schematic created usingCircuitLab
Its a simple project. I am trying to drive 3 RGB LEDs using Arduino Nano. Since Arduino Nano does not have 9 PWM pins, the only solution I can think of by multiplexing them. I have try multiplexing 12 7-segments driven by atmega16, the results was satisfying. Is it possible to doPWM multiplexing onArduino Nano?
So far, here is what I have done:
const int R=9, G=10, B=11, M1=5, M2=6, M3=7;//I use pin 5,6,7 as selector since they are on same PORT (PORTD)void setup(){ pinMode (R,OUTPUT); pinMode (G,OUTPUT); pinMode (B,OUTPUT); pinMode (M1,OUTPUT); pinMode (M2,OUTPUT); pinMode (M3,OUTPUT);}void led(int r, int g, int b){ analogWrite(R,255-r); analogWrite(G,255-g); analogWrite(B,255-b);}void loop(){ for(int i=0; i<256; i++) { led(0,0,i); __asm__("nop\n\t"); //one clock cycle delay PORTD = B10000000; //select LED-1 led(0,i,0); __asm__("nop\n\t"); //one clock cycle delay PORTD = B01000000; //select LED-2 led(i,0,0); __asm__("nop\n\t"); //one clock cycle delay PORTD = B00100000; //select LED-3 } for(int i=256; i>0; i--) { led(0,0,i); __asm__("nop\n\t"); //one clock cycle delay PORTD = B10000000; //select LED-1 led(0,i,0); __asm__("nop\n\t"); //one clock cycle delay PORTD = B01000000; //select LED-2 led(i,0,0); __asm__("nop\n\t"); //one clock cycle delay PORTD = B00100000; //select LED-3 }}But still, this does not work. The result is all the led turned on, with 'a little bit' different color, mainly white with a little addition of another color (while it supposed to be contrast, R, G and B for each LED), and its blinking. The blink is very short, but still, its annoying. One possibility I can think of my code still not optimum.
Someone had an idea?
EDIT
I fixed the diagram, I hope the diagram does not make any misunderstandings. As the suggestion from @jwpat7, I forget to inform that the led still error even if there is just onefor-loop.
I am using__asm__("nop\n\t") as delay substitution because "theoretically", 1 clock cycle from 16mHz clock is shorter than 1 microseconds. (correct me if I am wrong, but I think its about 62.5 ns)
Thanks in advance
1 Answer1
I've copied and slightly modified your diagram, as below. Note the added connections of R1, R3 cathodes to that of R2, and similarly for green and blue LEDs.

simulate this circuit – Schematic created usingCircuitLab
I'm supposing that unlike the original diagram, this one represents what you actually wired up.
A basic problem with your program is that it spends most of its time changing PWM settings, without letting PWM cycles actually occur. To see this, do some timing analysis on the code.
The code repeatedly executes sections of code like the following:
led(0,i,0); __asm__("nop\n\t"); //one clock cycle delay PORTD = B01000000; //select LED-2The call toled() results in three calls toanalogWrite(). As seen by perusing atgarretlab the source code foranalogWrite(),digitalWrite(), andpinMode(), each of thoseanalogWrite() calls takes a few handfuls of cycles – let's say 50 at most – so the three lines of code shown above take less than a dozen microseconds to execute. Thus each of the twofor loops takes less than 10 milliseconds to complete, causing theloop() routine to run more than 50 times per second. Persistence of vision will result in observers just seeing the average level of light, rather than any ramping up or down.
To fix the ramps-not-visible problem, determine how long you want each ramp up or down to take, and add corresponding delays in thefor loops. For example, suppose you want to go up in one second and down in two. As 1000000 μs /256 passes ≈ 3906 μs per pass, you could adddelayMicroseconds(3906-36) at the end of the firstfor loop, anddelayMicroseconds(2*3906-36) at the end of the other, to achieve the specified rates. (The -36 term accounts for time used by other code in each loop. It's probably an overestimate and perhaps should be left out.)
However, the previous paragraph doesn't take multiplexing effects into account. You may, of course, want a different PWM level for each of the nine different LED chips. It probably is practical to just directly use as many PWM outputs as you have available, and emulate PWM in software for any remaining LEDs.
For more information about software PWM, seesome articles that google turns up, including:
•Arduino PWM pin vs digital pin PWM simulation on electronics.stackexchange, which presents basic ideas and some pros and cons of software-based PWM
•AnyPWM Revisited, a blog article by Nick Borko about PWMing 12 LEDs using software PWM
•PWMAllPins, an arduino.cc article apparently by Paul Badger or Seth Wolf about PWMing 11 LEDs using software PWM
Generally, software PWM hogs computing cycles and can be difficult to coordinate with other calculations. But if PWM control is the only significant task a processor is handling, software PWM can be an economical way to produce extra PWM pins.
- Thanks jwpat, I did not notice the mistake on diagram before. I edited my original question. "emulate PWM in software", sounds interesting, can you explain more?duck– duck2016-11-11 06:10:42 +00:00CommentedNov 11, 2016 at 6:10
- @dpw, I added some links that help with the software PWM concept.James Waldby - jwpat7– James Waldby - jwpat72016-11-11 08:03:02 +00:00CommentedNov 11, 2016 at 8:03
Explore related questions
See similar questions with these tags.
