In this case, pulse lenght is about 8us and the jitter is +/- 2-3 clock cycles. In other situations, when the prescaler for example is 1, it is much worse. And sometimes the timer calculates a pulse lenght which differs up to 60% of pulse lenght, but this is rare (1/1000).
My question is: Am I doing something wrong? Is there a way to have the timing more precise? I cannot use the phase correct PWM mode, because I need to change the pulse lenght ( by changing OCR1A value) in the program.
I think Nick Gammon did some pretty thorough timing measurements and showed that it took about 4uS to service an interrupt.
Jitter might also occur from the micros() timer which runs all the time.
I saw this recently when I was testing sending out a bunch of bytes via SPI in response to a clock pulse. I had to disable interrupts so the bytes could go out in sync and not be interrupted by the micros() timer.
CrossRoads:
I think Nick Gammon did some pretty thorough timing measurements and showed that it took about 4uS to service an interrupt. http://www.gammon.com.au/forum/?id=11488
Jitter might also occur from the micros() timer which runs all the time.
I saw this recently when I was testing sending out a bunch of bytes via SPI in response to a clock pulse. I had to disable interrupts so the bytes could go out in sync and not be interrupted by the micros() timer.
Cool, could you post the code that disables just the timer0 interrupts? I always that it would be useful to have a function named stopTimer0(); and restartTimero(); to deal with issues like you had. I know this would just be setting or clearing a single bit in a timer0 register, but wrapping it into a user function might make it easier to remember how to do it.
The code is more complex so it is no possible to poll the timer flag for all the time. It is no important if the pulse setted to 100us will be +/- 20us, so the time for servicing an interrupt is not crucial. But it is imprortant the pulse will be always the same lenght. I thought the processor will service the interrupt always by the same cycles count.
Disabling Timer0 which uses the micros() by
TCCR0A = 0;
TCCR0B = 0;
reduced the jitter to strictly +/- 1 clock cycle. Not perfect but big improve!
The code is more complex so it is no possible to poll the timer flag for all the time. It is no important if the pulse setted to 100us will be +/- 20us, so the time for servicing an interrupt is not crucial. But it is imprortant the pulse will be always the same lenght. I thought the processor will service the interrupt always by the same cycles count.
Disabling Timer0 which uses the micros() by
TCCR0A = 0;
TCCR0B = 0;
reduced the jitter to strictly +/- 1 clock cycle. Not perfect but big improve!
Where the +/-1 clock difference is came from ??
Most likely just the inherent jitter in the 16MHz crystal clock oscillator that clocks the AVR chip?
retrolefty:
Most likely just the inherent jitter in the 16MHz crystal clock oscillator that clocks the AVR chip?
I don't mean phase shift of the sloping edge, but shift of the edge by whole cycle. It is few orders higher than the oscillator jitter.
But may I easily turn off Timer0? It breaks my serial communication ...
edit:
CrossRoads:
I think Nick Gammon did some pretty thorough timing measurements and showed that it took about 4uS to service an interrupt. http://www.gammon.com.au/forum/?id=11488
it explains well that Timer0 is needed to Serial communication. But when I stop the timer in whole code, it doesn't affect the jitter anyway. It is still +/- 4 cycles, which is terrible.
[quote]could you post the code that disables just the timer0 interrupts?
I think it was just the cli; sei; kind of thing.
Issued one to dis-able interrupts, did my SPI blasting of data, did the other to re-enable interrupts. My 43 bytes of data then took about 45uS to send out very smoothly.
From Nick's page:
Disable interrupts - If you need to disable interrupts you can "clear" the interrupt flag like this:
noInterrupts (); // or ...
cli (); // clear interrupts flag
Enable interrupts - You can enable interrupts with the function call "interrupts" or "sei" like this:
interrupts (); // or ...
sei (); // set interrupts flag
Either method has the same effect, using "interrupts" / "noInterrupts" is a bit easier to remember which way around they are.
The default in the Arduino is for interrupts to be enabled. Don't disable them for long periods or things like timers won't work properly.
[quote]could you post the code that disables just the timer0 interrupts?
I think it was just the cli; sei; kind of thing.
Issued one to dis-able interrupts, did my SPI blasting of data, did the other to re-enable interrupts. My 43 bytes of data then took about 45uS to send out very smoothly.
From Nick's page:
Disable interrupts - If you need to disable interrupts you can "clear" the interrupt flag like this:
noInterrupts (); // or ...
cli (); // clear interrupts flag
Enable interrupts - You can enable interrupts with the function call "interrupts" or "sei" like this:
interrupts (); // or ...
sei (); // set interrupts flag
Either method has the same effect, using "interrupts" / "noInterrupts" is a bit easier to remember which way around they are.
The default in the Arduino is for interrupts to be enabled. Don't disable them for long periods or things like timers won't work properly.
I'm aware of how, when, and why of enabling and disabling globally all interrupts, I was just wondering if you knew the values and register name to just enable or disable the timer0 that is put into service by the arduino init function.
"The timer is also set up to generate an interrupt, which has the sole purpose of waking the processor up from sleep, so it can draw each line with exactly the same delay after the pulse. If it wasn't asleep, there would be a variation of two to three clock cycles (since an interrupt cannot occur during a single instruction) and this gives very bad-looking "jitter" on the screen."