HOW TO IMPLEMENT PRECISE TIMED EVENT WITH ARDUINO
Let us assume a situation where you want to blink an event at a precise moment with a trigger, while the Arduino doing other tasks and you want to prioritize the blink as important event.
Well in order to do that you
need timers help to time it precisely hence you need to use timer as interrupt to
do that.
The Arduino IDE default has a
time function called “delay (microseconds)” it is pretty good and we can use it
almost in many things, but it’s not precise and tends to shift some mill-seconds
after sometime hence not reliable.
That being said let’s see how
we can implement a timer of Arduino to create a triggered event. The Arduino comes
with two 8-bit timers, one 16-bit timer hence we can use the 16-bit timer to
implement and triggered event.
We are gonna use the TCCR1A
and TCCR1B timer registers to implement. In the datasheet it is given clearly
about how to implant it.
The Timer/Counter (TCNT1), output compare registers
(OCR1A/B), and input capture register (ICR1) are all 16-bit registers.
Special procedures must be followed when accessing the 16-bit
registers. We need to use the mode called “NORMAL MODE” of 16-bit timer which
is mentioned in the TCCR1A and TCCR1B registers. First we need to set the
TCCR1A register.
The following makes sense like this:
16*1000000/65535 = 1/X
//16 MHz crystal that uses to count 1 sec
Hence X = 65536/16*1000000
//x gives
the default event of time i.e.
X = 4096 ms
//we need exactly 1000 ms for our event so we use prescaler
The TIMSK1 is responsible for
i-flag in it the “0-bit”, “TOIE1”.
• Bit 0 – TOIE1: Timer/Counter1, Overflow
Interrupt Enable:
When
this bit is written to one, and the I-flag in the status register is set
(interrupts globally enabled), the Timer/Counter1overflow interrupt is enabled.
The corresponding interrupt vector is executed when
the TOV1 flag, located in TIFR1, is set.
Next we set TCCR1B register to implement and set it to 0. We only need the CS10, 11, 12 bits to implement the prescaler.
Here we have different choices
to set prescaler I need 1 sec time event so choose 256 prescaler
X = 65536/ (16*1000000/256)
//x gives the default event of time i.e.
X = 1048 ms
//we still need exactly 1000 ms for our event
So we should count from
different value to get 1 sec here is the math for it:
1/1000 Hz
//the
frequency we need 1 KHz i.e.
X = 1000 ms = 1 sec
//we need exactly 1000 ms for our event so we use prescaler
The formula calculate the
desired value to start from is:
TCNT1 (desired Value) = 65536 –
F_clk / (prescaler*F_Target)
Here is a simple code to execute
the use of it:
void setup () {
Serial.begin(9600);
TCCR1A = 0; // writes 0 to all 8-bits in TCCR1A register
TCCR1B = 0; // writes 0 to all 8-bits in TCCR1B register
TNCT1 = 3036; //desired value for counter to start from
//TCCR1B |= (1<<CS10); //prescaler 1
TCCR1B |= (1<<CS10); //prescaler 256
TIMSK1 |= (1<<T0IE1); //overflow register
}
ISR (TIMER1_OVF_vect) //interrupt service routine implementation
{
// Serial.println( millis() ); // this line only checks the output and displays the // time of event
if (button == 1)
{
digitalWrite(3, !digitalWrite(3) ); // our event
}
}
void loop()
{
if (digitalWrite(3) == LOW)
{
button = 0;
digitalWrite(3,LOW);
}
}
good blog........
ReplyDelete