Hey i wrote this code with some help, to measure the time between events and it seems to run pretty well in first tests.
I would like to measure more precise, as right now its seems to count in 4micros steps when using micros().
I got a hint to use timer1 in a previous post, does someone know how to or can swap micros() in my code to be counted with timer1 ?
Or is this not possible ?
Thanks upfront !
Benni
Yes, you can use the hardware timers to get greater resolution than the 4 microsecond increment of micros().
It's not clear to me that given your timing code based on polling the state of pins with digitalRead() that a higher resolution is actually valuable. How are you using your time interval measurements?
One of the best tutorials on the avr hardware timers is by Nick Gammon.
Timer1 is a 16 bit timer, and and normal mode it will count up from 0 to 65535 before it rolls over and starts counting up again.
If you set the prescaler of the timer to 8, each count is .5 microsecond. Measuring a period of up to 32762 microsecond is then very easy and does not involve accounting for the number of roll overs. Simple subtraction of the unsigned integers will give the elapsed period.
You can set up the timer in normal mode with a prescaler =8 like this
TCCR1A = 0; //clear all ide timer presets used to enable analogWrite()
TCCR1B = 0; //clear all ide timer presets used to enable analogWrite()
TCCR1B = 1<< CS11; //set prescaler 8 for .5 microsecond tick
Then everywhere in your code everywhere you use micros() substitute TCNT1 which is the timer count value. Subtract the start values from the stop values and you will have .5 microsecond tick counts.
There are far more accurate techniques which use the input capture features of the timers. They are covered in the Gammon tutorial.
Hey thanks for the reply @cattledog.
It’s for checking the shutter of old cameras with a focal plane shutter.
It has two curtains the first curtain runs from one side to the other opening the window the second closes the window with some delay.
So im measuring the time where each of the three Diode gets light =shutter times at 3 points.
As well as the time the first curtain needs from one side to the other(diode1 gets light -diode3 gets light) and the time the second curtain needs from one side to the other(diode1 turns off - diode 3 turns off)
Im gonna check out the video.
The longest time will be normally around 1000milliseconds, never more then 2000milliseconds.
The shortest time will be around 0,490 milliseconds
That’s for the shuttertimes.
The curtain runtime is around 10-12 milliseconds.
Im using micros as I want 3 numbers behind the comma.
How precise can I get this code with this setup ?
Does the timer work with this times ?
Thanks
Benjamin
The longest time will be normally around 1000milliseconds, never more then 2000milliseconds.
The shortest time will be around 0,490 milliseconds
That's for the shuttertimes.
The curtain runtime is around 10-12 milliseconds.
Im using micros as I want 3 numbers behind the comma.
How precise can I get this code with this setup ?
Does the timer work with this times ?
If the shutter times are longer than approximately 32 milliseconds you will need to count timer overflows, and that complicates the code. Doable, but more complex.
There are examples in the Gammon tutorial of counting the timer overflows and adding the value into the counts.
The prescaler of 8 sets the precision to .5 microsecond. That's what limits the timer run without overflow to the 32 millisecond period. If you slow the timer down with a prescaler of 64 you get the same 4 microsecond resolution of the micros() function.
Even with very short shutter times of 490 microseconds, are you certain that the 4 microsecond resolution of micros() i.e. approximately 1% is a problem for what you are trying to check?
Alright, the 1% at 1/2000 is actually precise enough.
I just thought if it’s easy to do it would be worth it, but this way it seems it’s not worth the hustle.
Thank you for the help
It should be simple for the shorter shutter times. Why not give it a try? You will feel good about the half microsecond resolution even if it doesn't mean anything
// Fast Timer
// Returns the current time in 16th of a microsecond.
// Overflows every 268.435456 seconds.
// Note: Since this uses Timer1, Pin 9 and Pin 10 can't be used for
// analogWrite().
void setup()
{
Serial.begin(300);
while (!Serial);
StartFastTimer();
}
void StartFastTimer()
{
noInterrupts (); // protected code
// Reset Timer 1 to WGM 0, no PWM, and no clock
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0; // Reset the counter
TIMSK1 = 0; // Turn off all Timer1 interrupts
// Clear the Timer1 Overflow Flag (yes, by writing 1 to it)
// so we don't get an immediate interrupt when we enable it.
TIFR1 = _BV(TOV1);
TCCR1B = _BV(CS10); // start Timer 1, no prescale
// Note: For longer intervals you could use a prescale of 8
// to get 8 times the duration at 1/8th the resolution (1/2
// microsecond intervals). Set '_BV(CS11)' instead.
TIMSK1 = _BV(TOIE1); // Timer 1 Overflow Interrupt Enable
interrupts ();
}
volatile uint16_t Overflows = 0;
ISR(TIMER1_OVF_vect)
{
Overflows++;
}
unsigned long FastTimer()
{
unsigned long currentTime;
uint16_t overflows;
noInterrupts();
overflows = Overflows; // Make a local copy
// If an overflow happened but has not been handled yet
// and the timer count was close to zero, count the
// overflow as part of this time.
if ((TIFR1 & _BV(TOV1)) && (TCNT1 < 1024))
overflows++;
currentTime = overflows; // Upper 16 bits
currentTime = (currentTime << 16) | TCNT1;
interrupts();
return currentTime;
}
void loop()
{
static unsigned long previousTime = 0;
static unsigned long currentTime = FastTimer();
Serial.println(currentTime - previousTime);
previousTime = currentTime;
}