Hello
I am just wanting help to understand a piece of code I have 'borrowed' from another arduino.cc member (http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1274834441)
Basically what the code does is count pulses coming into a digital pin using an interrupt, and adjusts the counts based on Timer0 to get 4us accuracy, and then outputs the number of pulses it 'estimates' would occur in 60 seconds. It basically looks at the time between interrupt pulses + timer0 @ 4us, and estimates the pulses in 60 seconds.
I have a few questions, which are listed after the code.
Code in question is here (very nicely done):
extern volatile unsigned long timer0_overflow_count; // Record the most recent timer ticks
volatile boolean ticks_valid; // Indicates a valid reading
volatile unsigned long ticks_per_rev; // Number of ticks counted in the current revolution
volatile unsigned long ticks_now;
float lastRPM; // Most recent RPM reading
const float TICKS_TO_RPMS = 15e6; // Convert clock ticks to RPM by dividng ticks into this number
// 16000000Mhz / 64 Prescaler = 4uS (Timer0 resolution)
// 1000*1000*60/4us = 15e6
void setup()
{
Serial.begin(115200); // Initialise serial comms.
attachInterrupt(0, RPM_ISR, RISING); // RPM sense will cause an interrupt on pin2
lastRPM = 0;
}
void RPM_ISR()
{
static unsigned long pre_count; // Last timer0_overflow_count value
ticks_now = timer0_overflow_count; // Read the timer over count (number of times timer0 has overflowed since startup)
byte t = TCNT0; // Copy the current value of Timer0
if ((TIFR0 & _BV(TOV0)) && (t<255)) // If the Timer has overflowed
ticks_now++; // Increment the number of Ticks (Timer0 counting to 255 takes 1024uS, therefore this is 1024uS resoluation)
ticks_now = (ticks_now << 8) + t; // Bit shift Ticks by 8 bits and add Timer0 current value, to make ticks_now 4uS resolution now
if (pre_count == 0) // If this was the first time around the loop
{
pre_count = ticks_now; // Set the precount to the current count, don't use this number.
}
else
{
ticks_per_rev = ticks_now - pre_count; // Calculate the difference to get the actual number of ticks...
pre_count = ticks_now; // reset the counter with the current count value
ticks_valid = true; // and flag the change up
}
}
void loop()
{
unsigned long thisMillis = millis(); // Read the time once
// Calculate RPM
if (ticks_valid) // Only come here if we have a valid RPM reading
{
unsigned long thisTicks;
noInterrupts(); // Disable interrupts so the next calculation isnt changed half way through
thisTicks = ticks_per_rev;
ticks_valid = false;
interrupts(); // Enable interrupts again
lastRPM = TICKS_TO_RPMS / thisTicks; // Convert ticks to RPMs
ticks_valid = false; // Reset the flag.
}
}
My question is around this piece of code specifically:
byte t = TCNT0; // Copy the current value of Timer0
if ((TIFR0 & _BV(TOV0)) && (t<255)) // If the Timer has overflowed
ticks_now++; // Increment the number of Ticks (1024uS resolution)
ticks_now = (ticks_now << 8) + t; // Bit shift Ticks by 8 bits and add Timer0 current value, to make ticks_now 4uS resolution now
From what I have pieced together, it takes a copy of the Timer0 count, and then checks to see if Timer0 has overflowed using (TIFR0 & _BV(TOV0). What I am wondering is, how does it know if the timer hasnt elapsed twice since this was run, and how does the TIFR0 etc get reset to say it hasnt overflowed anymore.
Basically what I am getting at is if TIFR0 & _BV(TOV0) is saying that Timer0 has overflowed, if its never reset then the next time this code is executed it will be true again.
Does that make sense? Or am I talking total rubbish...
I know TIFR0 is a register, and TOV0 is a bit in that register... from the reading I have done.. but I dont know anything further about them.
Some of the comments above are my own, to remember what I found - so hopefully they are correct and not misleading anyone.
If someone can help me understand I would very much appriciate it.
I am raising this as the code does work very well, however the number of pulses it estimates does fluctuate a little. Not by much, but it does fluctuate. I have a 555 timer going into it for testing. I am just wondering if the piece of code mentioned above may be contributing to this?
It may be perfect, but I thought I would ask
Hats of to the creators, it has been very valuable to me and saved me alot of time and head scratching. Now I just need to get 100% comfortable with it so I am not just using another persons code without fully understanding it.
Thanks
J