1

I am seeing a "blip" in LED brightness when trying to fade a red LED on an Arduino UNO.

This code demonstrates the "blip" seen in brightness right after a 254, 255, 0 sequence. When the brightness is then set to 1, the actual brightness is much higher for a short period of time. The blip is not seen during the entire delay interval, just at the beginning.

I see the blip every time except for the very first cycle, before the 255 to 0 transition has ever happened.

My best guess is that there is a PWM "accumulation" that is not seen when the brightness is set to zero, but it is used when the brightness is set to a non-zero value.

/*
 FadeBlip
 Derived from Fade.ino.
 */

int led = 9;
int brightness = 0;
int fadeAmount = 1;
int skipBegin = 5;
int skipEnd = 254;

// If you try a shorter delay, you must make the skip range smaller
// to pick out the blip.  If you try a longer delay, the blip is not
// as bright.
int delayms = 1000;

void setup()  {
  pinMode(led, OUTPUT);
  Serial.begin(9600);
  delay(1000);  // give us time to bring up serial monitor
}

void loop()  {
  Serial.println(brightness);
  analogWrite(led, brightness);

  brightness = brightness + fadeAmount;

  // skip the boring middle values
  if (skipBegin < brightness && brightness < skipEnd)
    brightness = skipEnd;

  if (brightness > 255)
    brightness = 0;

  delay(delayms);
}
1

1 Answer 1

1

The Why does an LED sometimes flash when increasing brightness? question does exactly describe my problem (except for the substitution of pin 11 for pin 9). That question refers to this post at forum.arduino.cc which gives the beginnings of an answer.

The problem is caused by the fact that analogWrite(led, 0) does not use PWM, it just sets the pin to LOW. So when you call analogWrite(led, 0), the value in the Output Compare Register (OCR) is left at 255. When you call analogWrite(led, 1), the OCR value is changed to 1, but due to double-buffering this doesn't take effect until the next timer cycle begins. So for a fraction of the current timer cycle the output pin is left at HIGH.

The solution is to either avoid calling analogWrite(led, 0) or to explicitly set the OCR value to 0 when analogWrite(led, 0) is called. This will only work if another call to analogWrite() is not made in the current timer cycle. Given that the default timer cycle takes 32 microseconds, this is unlikely to happen. 32 microseconds = 256 (ticks per timer cycle) / 16MHz (clock ticks per second) * 2 (default timer prescale factor).

For pin 9, the solution was to add these lines immediately after the analogWrite() call:

if (brightness == 0) {
    OCR1A = 0;
}

For other pins, use the correct Output Compare Register. For the Arduino UNO they are:

+-------------+----------+-------+
| Arduino Pin | Chip Pin | OCR   |
+-------------+----------+-------+
|           3 |        5 | OCR2B |
|           5 |       11 | OCR0B |
|           6 |       12 | OCR0A |
|           9 |       15 | OCR1A |
|          10 |       16 | OCR1B |
|          11 |       17 | OCR2A |
+-------------+----------+-------+

Of course this solution will need to be modified if you have changed anything related to timers such as the PWM mode.

The solution given by the forum.arduino.cc post indicated that the Timer/Counter Control Register (TCCR) needed to be modified in addition to setting the OCR value. This modification was to configure the PWM mode, but the PWM mode would have already been correctly configured by any previous call to analogWrite() for that pin.

Others have suggested that calling analogWrite(led, 1) before analogWrite(led, 0) would be a simpler solution, but that still results in a flash, albeit shorter.

Resources:

  • LED fade malfunction (random flash) (forum.arduino.cc/index.php?topic=360468.msg2486781)
  • hardware/arduino/cores/avr/arduino/wiring_analog.c
  • Secrets of Arduino PWM (www.righto.com/2009/07/secrets-of-arduino-pwm.html). There is a more recent copy of this article at arduino.cc (www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM), but that copy has the useful graphics stripped out.
  • Arduino Timers and Interrupts (arduino-info.wikispaces.com/Timers-Arduino)

Not the answer you're looking for? Browse other questions tagged or ask your own question.