96. Paul Conneally

“Paul Conneally” 5: Software

The software for this one is quite simple. Five patterns (lighting effects) are predefined. The software displays a pattern for a few seconds (the exact time is randomised) and then selects a different random pattern and fades to that one. This just repeats indefinitely.

For example, to create the effect of light coming from above, the six pairs of LEDs are set up as shown below. LED [1] is at the bottom of the painting, which should be in shadow (it looks wrong if it is completely off, so it’s set to 10 (i.e. 10/255 of maximum). [2] points up at the second diagonal, so is off. [3] points down at the first diagonal, so is on full. The same with [4] and [5]. Finally, [6] is at the top, so is on full.

 BrightTarget[1] = {10};
 BrightTarget[2] = {0};
 BrightTarget[3] = {255};
 BrightTarget[4] = {0};
 BrightTarget[5] = {255};
 BrightTarget[6] = {255};

The only additional code is a voltage check on startup to make sure the correct, working adapter is being used. (As with the previous project, it’s a potential divider from the power supply, connected to one of the Analogue inputs (with a 5 Volt zener diode to protect the input)). The LEDs are only turned on if the supply voltage is correct.

PWM problem
There was a problem with the fades. Sometimes there would be a slow fading effect on top of the actual fades, as though someone were fading the brightness up and down about once a second. The effect was very noticeable. I tested all the voltages, and everything seemed correct. I checked and double-checked the code. Again, it seemed fine. I ever replaced the Arduino. Nothing seemed to fix the problem. Eventually I came across a similar problem on one of the discussion forums. It’s a problem how the PWM system works. Fortunately, there’s a software fix. Bear with me on this, because it’s a bit complicated.

There are three timers on the Arduino nano. Each one controls the PWM effect on two of the digital I/O pins. I needed to use all six PWM outputs because there are six pairs of LEDs that I wanted to control separately. The problem is that, by default, these three timers do not work in the same way. Timer 0 counts from zero to 255 and then counts back down to zero (“PWM mode”), whereas timers 1 and 2 count from zero to 255 and then jump straight to zero (“Phase-correct mode”).

Timer 0: PWM on pins 5 and 6, PWM mode
Timer 1: PWM on pins 9 and 10, Phase-correct mode
Timer 2: PWM on pins 11 and 3, Phase-correct mode

Now, on their own, the difference doesn’t matter, but using both types at once creates a problem. You see, counting 0-255 takes 256 counts,  or 512 if you do it twice. On the other hand, counting 0-255-0 takes 511 counts. So you have two timers repeating every 511 counts and one every 512 counts.

It’s a bit like the Moiré effect, where moving lines interact with static lines to produce a very noticeable third image, except in this case there’s the appearance of a slow strobing/fading effect.

To prevent this, all three timers need to operate in the same way. Now, timer 0 is used to update the time and to calculate delays, so it’s not a good idea to change that one. Therefore,  the answer is to set timers 1 and 2 to PWM mode. It would be nice if there were some easy command like “timerset(1, PWM)”, but there’s not. You need the following scary-looking low level code in setup():

TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM11) | _BV(WGM10);
TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);

And, as if by magic, the problem goes away!




Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s