For a driving application I need the PWM mode to be phase correct and the prescaler to be 1. The issue is that the board I am working with has the load hooked up to a PWM pin reliant on timer0. The firmware running on this board makes use of the delay()
, delayMicroseconds()
, and millis()
functions from wiring.c. The goal is to make the timer0 change, shown below, and then make small modifications where the firmware calls the wiring.c timing functions. My approach was to find a scaling factor to be applied to the call of these functions. The scaling factor I came to was 32.12549, calculated by taking the wiring.c expected timer0 behavior: prescaler=64 and TOV0 flag every 256 counts, and comparing it to the actual values after my change: prescaler=1 and TOV0 flag every 510 counts
Calculation: 64*256/510=32.12549
Timer0 change:
// Set timer0 to phase correct PWM
TCCR0A = TCCR0A & 0b11111100 | 0x01;
// Set prescaler for timer0 to 1
TCCR0B = TCCR0B & 0b11111000 | 0x01;
The other timers are all configured in phase correct PWM mode, with a prescaler of 1.
...When I apply this scaling factor to a value returned from millis() to keep time it works well. For example the two pieces of code below proved to be equivalent through the timer0 change:
Use of millis()
before timer0 change:
//current time
long unsigned now = millis();
//delay for 1 second
while(millis() - now < 1000){}
Use of millis()
after timer0 change:
//current time
long unsigned now = millis();
//delay for 1 second, with x32.125 scaling coefficient
while(millis() - now < 32125){}
The two snippets of code above both delayed for 1 second
Now comes the problem: when I try to apply that same scaling factor to delay()
or delayMicroseconds()
it seems to give unreasonable delays...
Use of delayMicroseconds()
before timer0 change:
// wait 1.5ms for mux to switch
delayMicroseconds(1500);
...this delays for 1.5ms
Use of delayMicroseconds()
after timer0 change:
// wait 1.5ms for mux to switch, with x32.125 scaling coefficient
delayMicroseconds(48188);
...this delays for ~20ms.
Assuming this is still linearly scalable: if 48188 -> 20ms, therefore 1.5ms -> 3614
But when the following code is used...
// wait 1.5ms for mux to switch, scaled
delayMicroseconds(3614);
...this delays for ~4.5ms
Why is it that delayMicroseconds()
and delay()
cannot be linearly scaled to account for a timer0 change? Furthermore, is there any simple modification to how these functions are called or utilized that can account for the effect of changing timer0?
delayMicroseconds()
doesn't utilizemicros()
, which blocks interrupts; I assumed it did sincedelay()
does) - although I am using a scope to measure the output (toggling a pin on either side of the delay) and the delay is repeatable, where-as our interrupts may happen at any time during the code. If it is an interrupt causing the issue I would expect the delay to vary as the loop runs, which it does not. I'll do my best to read through the source code fordelayMicroseconds()