Skip to main content
Tweeted twitter.com/StackArduino/status/798108452824514560
Bumped by Community user
Included sentence indicated other timer settings
Source Link

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:

...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:

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:

added 4 characters in body
Source Link

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;

...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);

...the delay isthis 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?

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;

...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);

...the delay is ~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?

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;

...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?

Source Link

Help managing the fallout from timer0 mode and prescaler change on ATMega2560 without modifying wiring.c

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;

...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);

...the delay is ~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?