Tis quite well works.. But.... If i enable the RPM reading with interrupt with 1ms interval it works quite well, but if i enable the RPM reading for example every 200ms the RPM is floating around and is not accurate. for some reason the micros() is not accurate if i run this interrupt code less often. Just cannot understand why.
The first thing Arduino does in entering an ISR is to disable global interrupts until it exits the ISR. What this means is that anything that relies on an interrupt (millis, micros, Serial.print for example) will simply not work. The reality is that a single interrupt will be queued for execution upon re-establishing globals, but this is not something that should be taken into consideration, just be aware.
Yes, if interrupts are disabled the rollover/overflow of the 8 bit timer register will not be handled. This means that micros() will only have a reliable range of 0..(256*X)-1 where X is 4 on 16MHz and 8 on 8Mhz. Because micros() may register a single rollover, the timer register can extend to 9 bits giving an unreliable range of up to twice the reliable range.
EDIT: The following untested code should deadlock an arduino:
void setup()
{
Serial.begin(9600);
unsigned long MAX = 256 * ((F_CPU == 16000000UL) ? 4 : 8) * 2;
noInterrupts();
unsigned long us = micros();
while (micros() - us < MAX) ;
interrupts();
}
void loop()
{
Serial.println("You will never see this!");
delay(1000);
}
EDIT: Code has been updated after UKHeliBob tested it.
PaulS:
Why are you detaching the interrupt handler in the interrupt handler?
Because in that point I have got enough pulses to calculate RPM. There is no need to let it run anymore before i want to have new RPM value. The I will again enable the interrupt pin.
As i understand that should not interfere micros because i'm not disabling all interrupts. Just the RPM interruptPIN
Because in that point I have got enough pulses to calculate RPM. There is no need to let it run anymore before i want to have new RPM value. The I will again enable the interrupt pin.
That's like removing your doorbell because you are going on vacation.
Let the mailman ring the doorbell while you are not there, or don't care.
When you are ready to measure RPM again, just disable interrupts, set the count to 0, and enable interrupts. Meanwhile, let the interrupt happen uselessly.
PaulS:
That's like removing your doorbell because you are going on vacation.
Let the mailman ring the doorbell while you are not there, or don't care.
When you are ready to measure RPM again, just disable interrupts, set the count to 0, and enable interrupts. Meanwhile, let the interrupt happen uselessly.
Damn, You are good...
Now delta time changes max of 4micros in every measurement..
UKHeliBob:
Just tested it on a Nano and got the following
You will never see this!
You will never see this!
You will never see this!
You will never see this!
You will never see this!
and so on
Change "MAX" to "1600" or "256 * ( (F_CPU == 16000000UL) ? 4 : 8 ) * 2" - this will deadlock my nano. Actually I dunno why it counts out of bounds, but I'd sure like to know
In case anyone should be interrested, I figured out that micros() may in fact register a single rollover of the timer register even if interrupts are disabled or if used in an interrupt handler. This will - unreliably - extend the range that micros() will cover by up to a multiple of 2 I've edited my previous post with the deadlock example for clarification.