Attention: This BUG affects only AVR based platforms which are using "STANDARD" Arduino Core, and not the new ARM based ones like DUE and Teensy. Also it doesn't affect Teensy 2.0 which is featuring AVR32U4 chip and is using completly different code instead of digital_wiring...
Hi,
Recently I've found out that the function from core library wiring_digital.c
void turnOffPWM(uint8_t timer);
simply doesn't switch off the associated timer properly, but only in case when it concerns TIMER0B (pwm pin 5 on UNO).
This erratic behaviour was burdened me for a while, so I focused to sort it out.
It has been out there since 2010, after the removing of previous inline functions for code optimisation, perhaps by David Mellis or Mark Sproul who did these modifications:
// - Removed inline. Save 170 bytes on atmega1280
// - changed to a switch statment; added 32 bytes but much easier to read and maintain.
// - Added more #ifdefs, now compiles for atmega645
This could be a typo mistake, or copy/paste on the wrong place, what do you think?
Now I think that I do solved it.
example:
void setup() {
analogWrite(5, 127); // 127 could be any between 1 and 254
digitalWrite(5, LOW); // LOW or HIGH doesn't matter it will not work
// and even
analogWrite(5, 0); // 0 or 255 is again will don't make any change
};
void loop(){};....
In general, once PWM operation is commenced on pin 5, you can
only change the duty cycle only from 1 to 254 ...
Solution:
I think it should be
#if defined(TCCR0A,) && defined(COM0B1)
instead of
#if defined(TIMER0B) && defined(COM0B1)
Am I correct or missing something here?
Regards
static void turnOffPWM(byte timer) {
switch (timer) {
... ... ...
#if defined(TIMER0B) && defined(COM0B1)
case TIMER0B: cbi(TCCR0A, COM0B1); break;
#endif
... ... ...
}