Flickering problem with RGB leds and a simple solution

  • I've noticed with some of the RGB nodes around the house an annoying flickering problem. It occurs when none of the R G B channels is driven at full brightness. This is especially disturbing when a lower light level is desired.

    Tried to find out a reason for this. It was not related to the Arduino used, whether it being a Nano, Uno, official or not. Also not related to using gw.wait or delay in the main loop. Or adding resistors to the fet data pins.

    Turns out it is related to the Arduino PWM not being very optimal. Tried to solve the problem by using a different approach, softPWM [e.g. https://github.com/Palatis/arduino-softpwm] but they conflicted with servo library (that uses various timers also, as soft pwms do).

    Jeelabs brought a solution; tweaking the frequency of some timers. Just tested it, and seems that the flickering is totally gone AND still the servos AND the MySensor communication works. Very happy with the result.

    This is the blog post describing the issue, the solution I used is in the comments http://jeelabs.org/wp-content/uploads/2011/11/8/fixing-the-arduinos-pwm/index.html.

    So, flickering fixed by adding TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20) to the setup. Will need to update a few nodes now!

  • I can confirm this fixing the flickering problem. The only problem it introduces - some high pitch whine from arduino.

  • Some background, why the solution works without changing the timer prescale:
    The default prescale of all timers are 64, so they should work the same, but the default mode is different:
    Timer 0: Fast PWM mode = 0..255,0..255,... (timer is used for internal calculations millis() / delay() /..., so this setting is required)
    Timer 2: Phase-correct mode = 0..255..0..255...
    Timer 1 is 16 bit and the pins are blocked by the radio, so I'll leave them out here.
    The frequency of the timer is comparable to a timer round trip (values are calculated with a 16 MHz IO-frequency like with ATmega168 or ATmega328 used in nano):
    Timer 0: 16 MHz / 64 / 256 = 976.5625 Hz
    Timer 2: 16 MHz / 64 / 510 = 490.1961 Hz
    Fast PWM uses 0..255 = 256 for a round trip.
    Phase-corrected mode uses 0..255,254..1 = 256 + 254 = 510 (all numbers are double except 0 and 255!)

    NOW the command:
    TCCR2A |= _BV(WGM21);
    Switches timer 2 to fast PWM mode (mode from 1 to 3).

    In addition to the links above, here I found the default settings: http://playground.arduino.cc/Main/TimerPWMCheatsheet