Sei sulla pagina 1di 31

Make arduino do task after certain time:

 https://arduino.stackexchange.com/q/22272/25533
 https://stackoverflow.com/q/10773425/7075360
 Try out the Metro library, which lets you do recurring timed events. You can
change the frequency of the timer within the loop, if that's a desirable thing.

 You can use below sample code.Here repeating steps for every 1ms.
#include <SimpleTimer.h>

// the timer object


SimpleTimer timer;

// a function to be executed periodically


void repeatMe()
{
Serial.print("Uptime (s): ");
Serial.println(millis() / 1000);
}

void setup()
{
Serial.begin(9600);
timer.setInterval(1000, repeatMe);
}

void loop()
{
timer.run();
}
SimpleTimer Library for Arduino
Author: Marcello Romani
Contact: mromani@ottotecnica.com
License: GNU LGPL 2.1+

Navigation
 Information
o Description
o Download
o Installation
o Usage
o Theory
o Links
 Functions
o SimpleTimer()
o setInterval()
o setTimeout()
o enable()
o disable()
o toggle()
o restartTimer()
o deleteTimer()
o getNumTimers()
 Example
 Get the code
 Contributing
 About this page

Information
Description
This is (yet another) simple library to launch timed actions.

It's based on millis(), thus it has 1 ms resolution.

It uses polling, so no guarantee can be made about the exact time when a
callback is fired. For example, if you setup the library so that it calls a function
every 2ms, but this function requires 5ms to complete, then you'll have an
invocation every 5ms.

For applications where non-strict timing is enough, not using interrupts


avoids potential problems with global variables shared between the interrupt
service routine and the main program, and doesn't consume a hardware
timer.

Download
Go to the Get the code section and hit the "get the code" link at the bottom of
each code block.

There's also a fork of SimpleTimer which also supports std::function or


lambda-expressions known from C++11.
See: https://github.com/schinken/SimpleTimer

Installation
1. Create a folder named SimpleTimer in you sketchbook/libraries folder.
2. Copy-n-paste the code for SimpleTimer.h and SimpleTimer.cpp into your
favourite text editor, and save those two files under the SimpleTimer folder
you just created.
3. Launch or restart the Arduino IDE to let it detect the new library.
4. Copy-n-paste the example code (see below) to get you started with the library.
Usage
#include <SimpleTimer.h>

// the timer object


SimpleTimer timer;

// a function to be executed periodically


void repeatMe() {
Serial.print("Uptime (s): ");
Serial.println(millis() / 1000);
}

void setup() {
Serial.begin(9600);
timer.setInterval(1000, repeatMe);
}

void loop() {
timer.run();
}

Theory
The base goal is to be able to execute a particular piece of code every n
milliseconds, without using interrupts.

The algorithm looks like this:

lastMillis = 0
forever do:
if (millis() - lastMillis > n)
call the particular piece of code
lastMillis = millis()
end
end

Links
Other libraries with similar or broader goals can be found in the here

Functions
SimpleTimer()
The constructor. You usually need only one SimpleTimer object in a sketch.
SimpleTimer timer;

int setInterval(long d, timer_callback f)


Call function f every d milliseconds. The callback function must be declared
as void f().

void repeatMe() {
// do something
}

timerId = timer.setInterval(1000, repeatMe);

int setTimeout(long d, timer_callback f)


Call function f once after d milliseconds. The callback function must be
declared as void f(). After f has been called, the interval is deleted, therefore
the value timerId is no longer valid.

void callMeLater() {
// do something
}

timerId = timer.setTimeout(1000, callMeLater);

int setTimer(long d, timer_callback f, int n)


Call function f every d milliseconds for n times. The callback function must be
declared as void f(). After f has been called the specified number of times,
the interval is deleted, therefore the value timerId is no longer valid.

void repeatMeFiveTimes() {
// do something
}

timerId = timer.setTimer(1000, repeatMeFiveTimes, 5);

boolean isEnabled(int timerId)


Returns true if the specified timer is enabled

if(timer.isEnabled(timerId) {
// do domething
}

void enable(int timerId)


Enables the specified timer.

timer.enable(timerId);
void disable(int timerId)
Disables the specified timer.

timer.disable(timerId);

void toggle(int timerId)


Enables the specified timer if it's currently disabled, and vice-versa.

timer.toggle(timerId);

void restartTimer(int timerId)


Causes the specified timer to start counting from "now", i.e. the instant when
restartTimer is called. The timer callback is not fired. A use case for this
function is for example the implementation of a watchdog timer (pseudocode
follows).

void wdCallback() {
alert user or perform action to restore
program state (e.g. reset the microprocessor)
}

wd_timer_id;

void setup() {
wd_timer_id = timer.setInterval(10000, wdCallback);
}

void loop() {
timer.run();

big complex critical code

timer.restartTimer(wd_timer_id);
}

void deleteTimer(int timerId)


Free the specified timerId slot. You should need to call this only if you have
interval slots that you don't need anymore. The other timer types are
automatically deleted once the specified number of repetitions have been
executed.

void getNumTimers()
Return the number of used slots in a timer object.

n = timer.getNumTimers();
Example
1. /*
2. * SimpleTimerAlarmExample.pde
3. *
4. * Based on usage example for Time + TimeAlarm libraries
5. *
6. * A timer is called every 15 seconds
7. * Another timer is called once only after 10 seconds
8. * A third timer is called 10 times.
9. *
10. */
11.
12.#include <SimpleTimer.h>
13.
14.// There must be one global SimpleTimer object.
15.// More SimpleTimer objects can be created and run,
16.// although there is little point in doing so.
17.SimpleTimer timer;
18.
19.// function to be called repeatedly
20.void RepeatTask() {
21. Serial.println("15 second timer");
22.}
23.
24.// function to be called just once
25.void OnceOnlyTask() {
26. Serial.println("This timer only triggers once");
27.}
28.
29.// function to be called exactly 10 times
30.void TenTimesTask() {
31. static int k = 0;
32. k++;
33. Serial.print("called ");
34. Serial.print(k);
35. Serial.println(" / 10 times.");
36.}
37.
38.// print current arduino "uptime" on the serial port
39.void DigitalClockDisplay() {
40. int h,m,s;
41. s = millis() / 1000;
42. m = s / 60;
43. h = s / 3600;
44. s = s - m * 60;
45. m = m - h * 60;
46. Serial.print(h);
47. printDigits(m);
48. printDigits(s);
49. Serial.println();
50.}
51.
52.//
53.// utility function for digital clock display:
54.// prints preceding colon and leading 0
55.//
56.void printDigits(int digits) {
57. Serial.print(":");
58. if(digits < 10)
59. Serial.print('0');
60. Serial.print(digits);
61.}
62.
63.void setup() {
64. Serial.begin(9600);
65.
66. // welcome message
67. Serial.println("SimpleTimer Example");
68. Serial.println("One timer is triggered every 15 seconds");
69. Serial.println("Another timer is set to trigger only once after 10 seconds");
70. Serial.println("Another timer is set to trigger 10 times");
71. Serial.println();
72.
73. // timed actions setup
74. timer.setInterval(15000, RepeatTask);
75. timer.setTimeout(10000, OnceOnlyTask);
76. timer.setInterval(1000, DigitalClockDisplay);
77. timer.setTimer(1200, TenTimesTask, 10);
78.}
79.
80.void loop() {
81. // this is where the "polling" occurs
82. timer.run();
83.}
[Get Code]
Get the code
1. /*
2. * SimpleTimer.h
3. *
4. * SimpleTimer - A timer library for Arduino.
5. * Author: mromani@ottotecnica.com
6. * Copyright (c) 2010 OTTOTECNICA Italy
7. *
8. * This library is free software; you can redistribute it
9. * and/or modify it under the terms of the GNU Lesser
10. * General Public License as published by the Free Software
11. * Foundation; either version 2.1 of the License, or (at
12. * your option) any later version.
13. *
14. * This library is distributed in the hope that it will
15. * be useful, but WITHOUT ANY WARRANTY; without even the
16. * implied warranty of MERCHANTABILITY or FITNESS FOR A
17. * PARTICULAR PURPOSE. See the GNU Lesser General Public
18. * License for more details.
19. *
20. * You should have received a copy of the GNU Lesser
21. * General Public License along with this library; if not,
22. * write to the Free Software Foundation, Inc.,
23. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24. *
25. */
26.
27.
28.#ifndef SIMPLETIMER_H
29.#define SIMPLETIMER_H
30.
31.#if defined(ARDUINO) && ARDUINO >= 100
32.#include <Arduino.h>
33.#else
34.#include <WProgram.h>
35.#endif
36.
37.typedef void (*timer_callback)(void);
38.
39.class SimpleTimer {
40.
41.public:
42. // maximum number of timers
43. const static int MAX_TIMERS = 10;
44.
45. // setTimer() constants
46. const static int RUN_FOREVER = 0;
47. const static int RUN_ONCE = 1;
48.
49. // constructor
50. SimpleTimer();
51.
52. // this function must be called inside loop()
53. void run();
54.
55. // call function f every d milliseconds
56. int setInterval(long d, timer_callback f);
57.
58. // call function f once after d milliseconds
59. int setTimeout(long d, timer_callback f);
60.
61. // call function f every d milliseconds for n times
62. int setTimer(long d, timer_callback f, int n);
63.
64. // destroy the specified timer
65. void deleteTimer(int numTimer);
66.
67. // restart the specified timer
68. void restartTimer(int numTimer);
69.
70. // returns true if the specified timer is enabled
71. boolean isEnabled(int numTimer);
72.
73. // enables the specified timer
74. void enable(int numTimer);
75.
76. // disables the specified timer
77. void disable(int numTimer);
78.
79. // enables the specified timer if it's currently disabled,
80. // and vice-versa
81. void toggle(int numTimer);
82.
83. // returns the number of used timers
84. int getNumTimers();
85.
86. // returns the number of available timers
87. int getNumAvailableTimers() { return MAX_TIMERS - numTimers; };
88.
89.private:
90. // deferred call constants
91. const static int DEFCALL_DONTRUN = 0; // don't call the callback
function
92. const static int DEFCALL_RUNONLY = 1; // call the callback function but
don't delete the timer
93. const static int DEFCALL_RUNANDDEL = 2; // call the callback function
and delete the timer
94.
95. // find the first available slot
96. int findFirstFreeSlot();
97.
98. // value returned by the millis() function
99. // in the previous run() call
100. unsigned long prev_millis[MAX_TIMERS];
101.
102. // pointers to the callback functions
103. timer_callback callbacks[MAX_TIMERS];
104.
105. // delay values
106. long delays[MAX_TIMERS];
107.
108. // number of runs to be executed for each timer
109. int maxNumRuns[MAX_TIMERS];
110.
111. // number of executed runs for each timer
112. int numRuns[MAX_TIMERS];
113.
114. // which timers are enabled
115. boolean enabled[MAX_TIMERS];
116.
117. // deferred function call (sort of) - N.B.: this array is only used in
run()
118. int toBeCalled[MAX_TIMERS];
119.
120. // actual number of timers in use
121. int numTimers;
122. };
123.
124. #endif
[Get Code]
1. /*
2. * SimpleTimer.cpp
3. *
4. * SimpleTimer - A timer library for Arduino.
5. * Author: mromani@ottotecnica.com
6. * Copyright (c) 2010 OTTOTECNICA Italy
7. *
8. * This library is free software; you can redistribute it
9. * and/or modify it under the terms of the GNU Lesser
10. * General Public License as published by the Free Software
11. * Foundation; either version 2.1 of the License, or (at
12. * your option) any later version.
13. *
14. * This library is distributed in the hope that it will
15. * be useful, but WITHOUT ANY WARRANTY; without even the
16. * implied warranty of MERCHANTABILITY or FITNESS FOR A
17. * PARTICULAR PURPOSE. See the GNU Lesser General Public
18. * License for more details.
19. *
20. * You should have received a copy of the GNU Lesser
21. * General Public License along with this library; if not,
22. * write to the Free Software Foundation, Inc.,
23. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24. */
25.
26.
27.#include "SimpleTimer.h"
28.
29.
30.// Select time function:
31.//static inline unsigned long elapsed() { return micros(); }
32.static inline unsigned long elapsed() { return millis(); }
33.
34.
35.SimpleTimer::SimpleTimer() {
36. unsigned long current_millis = elapsed();
37.
38. for (int i = 0; i < MAX_TIMERS; i++) {
39. enabled[i] = false;
40. callbacks[i] = 0; // if the callback pointer is zero, the slot is free,
i.e. doesn't "contain" any timer
41. prev_millis[i] = current_millis;
42. numRuns[i] = 0;
43. }
44.
45. numTimers = 0;
46.}
47.
48.
49.void SimpleTimer::run() {
50. int i;
51. unsigned long current_millis;
52.
53. // get current time
54. current_millis = elapsed();
55.
56. for (i = 0; i < MAX_TIMERS; i++) {
57.
58. toBeCalled[i] = DEFCALL_DONTRUN;
59.
60. // no callback == no timer, i.e. jump over empty slots
61. if (callbacks[i]) {
62.
63. // is it time to process this timer ?
64. // see
http://arduino.cc/forum/index.php/topic,124048.msg932592.html#msg932
592
65.
66. if (current_millis - prev_millis[i] >= delays[i]) {
67.
68. // update time
69. //prev_millis[i] = current_millis;
70. prev_millis[i] += delays[i];
71.
72. // check if the timer callback has to be executed
73. if (enabled[i]) {
74.
75. // "run forever" timers must always be executed
76. if (maxNumRuns[i] == RUN_FOREVER) {
77. toBeCalled[i] = DEFCALL_RUNONLY;
78. }
79. // other timers get executed the specified number of times
80. else if (numRuns[i] < maxNumRuns[i]) {
81. toBeCalled[i] = DEFCALL_RUNONLY;
82. numRuns[i]++;
83.
84. // after the last run, delete the timer
85. if (numRuns[i] >= maxNumRuns[i]) {
86. toBeCalled[i] = DEFCALL_RUNANDDEL;
87. }
88. }
89. }
90. }
91. }
92. }
93.
94. for (i = 0; i < MAX_TIMERS; i++) {
95. switch(toBeCalled[i]) {
96. case DEFCALL_DONTRUN:
97. break;
98.
99. case DEFCALL_RUNONLY:
100. (*callbacks[i])();
101. break;
102.
103. case DEFCALL_RUNANDDEL:
104. (*callbacks[i])();
105. deleteTimer(i);
106. break;
107. }
108. }
109. }
110.
111.
112. // find the first available slot
113. // return -1 if none found
114. int SimpleTimer::findFirstFreeSlot() {
115. int i;
116.
117. // all slots are used
118. if (numTimers >= MAX_TIMERS) {
119. return -1;
120. }
121.
122. // return the first slot with no callback (i.e. free)
123. for (i = 0; i < MAX_TIMERS; i++) {
124. if (callbacks[i] == 0) {
125. return i;
126. }
127. }
128.
129. // no free slots found
130. return -1;
131. }
132.
133.
134. int SimpleTimer::setTimer(long d, timer_callback f, int n) {
135. int freeTimer;
136.
137. freeTimer = findFirstFreeSlot();
138. if (freeTimer < 0) {
139. return -1;
140. }
141.
142. if (f == NULL) {
143. return -1;
144. }
145.
146. delays[freeTimer] = d;
147. callbacks[freeTimer] = f;
148. maxNumRuns[freeTimer] = n;
149. enabled[freeTimer] = true;
150. prev_millis[freeTimer] = elapsed();
151.
152. numTimers++;
153.
154. return freeTimer;
155. }
156.
157.
158. int SimpleTimer::setInterval(long d, timer_callback f) {
159. return setTimer(d, f, RUN_FOREVER);
160. }
161.
162.
163. int SimpleTimer::setTimeout(long d, timer_callback f) {
164. return setTimer(d, f, RUN_ONCE);
165. }
166.
167.
168. void SimpleTimer::deleteTimer(int timerId) {
169. if (timerId >= MAX_TIMERS) {
170. return;
171. }
172.
173. // nothing to delete if no timers are in use
174. if (numTimers == 0) {
175. return;
176. }
177.
178. // don't decrease the number of timers if the
179. // specified slot is already empty
180. if (callbacks[timerId] != NULL) {
181. callbacks[timerId] = 0;
182. enabled[timerId] = false;
183. toBeCalled[timerId] = DEFCALL_DONTRUN;
184. delays[timerId] = 0;
185. numRuns[timerId] = 0;
186.
187. // update number of timers
188. numTimers--;
189. }
190. }
191.
192.
193. // function contributed by code@rowansimms.com
194. void SimpleTimer::restartTimer(int numTimer) {
195. if (numTimer >= MAX_TIMERS) {
196. return;
197. }
198.
199. prev_millis[numTimer] = elapsed();
200. }
201.
202.
203. boolean SimpleTimer::isEnabled(int numTimer) {
204. if (numTimer >= MAX_TIMERS) {
205. return false;
206. }
207.
208. return enabled[numTimer];
209. }
210.
211.
212. void SimpleTimer::enable(int numTimer) {
213. if (numTimer >= MAX_TIMERS) {
214. return;
215. }
216.
217. enabled[numTimer] = true;
218. }
219.
220.
221. void SimpleTimer::disable(int numTimer) {
222. if (numTimer >= MAX_TIMERS) {
223. return;
224. }
225.
226. enabled[numTimer] = false;
227. }
228.
229.
230. void SimpleTimer::toggle(int numTimer) {
231. if (numTimer >= MAX_TIMERS) {
232. return;
233. }
234.
235. enabled[numTimer] = !enabled[numTimer];
236. }
237.
238.
239. int SimpleTimer::getNumTimers() {
240. return numTimers;
241. }
[Get Code]

Arduino101-Timers.zip 8 (33689Bytes)
ArduinoTimer101.zip 7 (2802Bytes)
Update 07/24/2013 04/24/2013

 Example 3 has been updated to work with Arduino v1.x.


 Added ArduinoTimer101.zip examples source code for Arduino v1.x .

This tutorial shows the use of timers and interrupts for Arduino boards. As Arduino programmer
you will have used timers and interrupts without knowledge, bcause all the low level hardware
stuff is hidden by the Arduino API. Many Arduino functions uses timers, for example the time
functions: delay() 4, millis() 7and micros() 5 and delayMicroseconds() 3. The PWM
functions analogWrite() 2 uses timers, as thetone() 6 and the noTone() function does. Even
theServo library 6 uses timers and interrupts.

What is a timer?
A timer or to be more precise a timer / counter is a piece of hardware builtin the Arduino
controller (other controllers have timer hardware, too). It is like a clock, and can be used to
measure time events.
The timer can be programmed by some special registers. You can configure the prescaler for the
timer, or the mode of operation and many other things.
The controller of the Arduino is the Atmel AVR ATmega168 or the ATmega328. These chips are
pin compatible and only differ in the size of internal memory. Both have 3 timers, called timer0,
timer1 and timer2. Timer0 and timer2 are 8bit timer, where timer1 is a 16bit timer. The most
important difference between 8bit and 16bit timer is the timer resolution. 8bits means 256 values
where 16bit means 65536 values for higher resolution.
The controller for the Arduino Mega series is the Atmel AVR ATmega1280 or the
ATmega2560. Also identical only differs in memory size. These controllers have 6 timers. Timer
0, timer1 and timer2 are identical to the ATmega168/328. The timer3, timer4 and timer5 are all
16bit timers, similar to timer1.
All timers depends on the system clock of your Arduino system. Normally the system clock is
16MHz, but for the Arduino Pro 3,3V it is 8Mhz. So be careful when writing your own timer
functions.
The timer hardware can be configured with some special timer registers. In the Arduino firmware
all timers were configured to a 1kHz frequency and interrupts are gerally enabled.

Timer0:
Timer0 is a 8bit timer.
In the Arduino world timer0 is been used for the timer functions,
like delay() 4, millis() 7 and micros() 5. If you change timer0 registers, this may influence the
Arduino timer function. So you should know what you are doing.

Timer1:
Timer1 is a 16bit timer.
In the Arduino world the Servo library 6 uses timer1 on Arduino Uno (timer5 on Arduino Mega).

Timer2:
Timer2 is a 8bit timer like timer0.
In the Arduino work the tone() 6 function uses timer2.

Timer3, Timer4, Timer5:


Timer 3,4,5 are only available on Arduino Mega boards. These timers are all 16bit timers.

Timer Register
You can change the Timer behaviour through the timer register. The most important timer
registers are:
TCCRx - Timer/Counter Control Register. The prescaler can be configured here.

TCNTx - Timer/Counter Register. The actual timer value is stored here.

OCRx - Output Compare Register

ICRx - Input Capture Register (only for 16bit timer)

TIMSKx - Timer/Counter Interrupt Mask Register. To enable/disable timer interrupts.

TIFRx - Timer/Counter Interrupt Flag Register. Indicates a pending timer interrupt.

Clock select and timer frequency

Different clock sources can be selected for each timer independently. To calculate the timer
frequency (for example 2Hz using timer1) you will need:

1. CPU frequency 16Mhz for Arduino


2. maximum timer counter value (256 for 8bit, 65536 for 16bit timer)
3. Divide CPU frequency through the choosen prescaler (16000000 / 256 = 62500)
4. Divide result through the desired frequency (62500 / 2Hz = 31250)
5. Verify the result against the maximum timer counter value (31250 < 65536 success) if
fail, choose bigger prescaler.

Timer modes

Timers can be configured in different modes.

PWM mode. Pulth width modulation mode. the OCxy outputs are used to generate PWM signals
CTC mode. Clear timer on compare match. When the timer counter reaches the compare match
register, the timer will be cleared

What is an interrupt?
The program running on a controller is normally running sequentially instruction by instruction. An
interrupt is an external event that interrupts the running program and runs a special interrupt
service routine (ISR). After the ISR has been finished, the running program is continued with the
next instruction. Instruction means a single machine instruction, not a line of C or C++ code.
Before an pending interrupt will be able to call a ISR the following conditions must be true:

 Interrupts must be generally enabled


 the according Interrupt mask must be enabled

Interrupts can generally enabled / disabled with the function interrupts() 4 / noInterrupts() 2. By
default in the Arduino firmware interrupts are enabled. Interrupt masks are enabled / disabled by
setting / clearing bits in the Interrupt mask register (TIMSKx).
When an interrupt occurs, a flag in the interrupt flag register (TIFRx) is been set. This interrupt
will be automatically cleared when entering the ISR or by manually clearing the bit in the interrupt
flag register.

The Arduino functions attachInterrupt() 2 anddetachInterrupt() 3 can only be used for external
interrupt pins. These are different interrupt sources, not discussed here.

Timer interrupts
A timer can generate different types of interrupts. The register and bit definitions can be found in
the processor data sheet (Atmega328 or Atmega2560 3) and in the I/O definition header file
(iomx8.h for Arduino, iomxx0_1.h for Arduino Mega in the hardware/tools/avr/include/avr folder).
The suffix x stands for the timer number (0..5), the suffix y stands for the output number (A,B,C),
for example TIMSK1 (timer1 interrupt mask register) or OCR2A (timer2 output compare register
A).

Timer Overflow:
Timer overflow means the timer has reached is limit value. When a timer overflow interrupt
occurs, the timer overflow bit TOVx will be set in the interrupt flag register TIFRx. When the timer
overflow interrupt enable bit TOIEx in the interrupt mask register TIMSKx is set, the timer
overflow interrupt service routine ISR(TIMERx_OVF_vect) will be called.

Output Compare Match:


When a output compare match interrupt occurs, the OCFxy flag will be set in the interrupt flag
register TIFRx . When the output compare interrupt enable bit OCIExy in the interrupt mask
register TIMSKx is set, the output compare match interrupt service ISR(TIMERx_COMPy_vect)
routine will be called.
Timer Input Capture:
When a timer input capture interrupt occurs, the input capture flag bit ICFx will be set in the
interrupt flag register TIFRx. When the input capture interrupt enable bit ICIEx in the interrupt
mask register TIMSKx is set, the timer input capture interrupt service routine
ISR(TIMERx_CAPT_vect) will be called.

PWM and timer


There is fixed relation between the timers and the PWM capable outputs. When you look in the
data sheet or the pinout of the processor these PWM capable pins have names like OCRxA,
OCRxB or OCRxC (where x means the timer number 0..5). The PWM functionality is often
shared with other pin functionality.
The Arduino has 3Timers and 6 PWM output pins. The relation between timers and PWM
outputs is:
Pins 5 and 6: controlled by timer0
Pins 9 and 10: controlled by timer1
Pins 11 and 3: controlled by timer2

On the Arduino Mega we have 6 timers and 15 PWM outputs:


Pins 4 and 13: controlled by timer0
Pins 11 and 12: controlled by timer1
Pins 9 and10: controlled by timer2
Pin 2, 3 and 5: controlled by timer 3
Pin 6, 7 and 8: controlled by timer 4
Pin 46, 45 and 44:: controlled by timer 5

Usefull 3rd party libraries

Some 3rd party libraries exists, that uses timers:

 Ken Shirrifs IR library 3. Using timer2. Send and receive any kind of IR remote signals like RC5,
RC6, Sony

 Timer1 and Timer3 library 6. Using timer1 or tiner3. The easy way to write your own timer interupt
service routines.

I have ported these libraries to different timers for Arduino Mega. All ported libraries can be found
in the attached file.

Pitfalls
There exists some pitfalls you may encounter, when programming your Arduino and make use of
functions or libraries that uses timers.

 Servo Library uses Timer1. You can’t use PWM on Pin 9, 10 when you use the Servo Library on
an Arduino. For Arduino Mega it is a bit more difficult. The timer needed depends on the number
of servos. Each timer can handle 12 servos. For the first 12 servos timer 5 will be used (loosing
PWM on Pin 44,45,46). For 24 Servos timer 5 and 1 will be used (loosing PWM on Pin
11,12,44,45,46).. For 36 servos timer 5, 1 and 3 will be used (loosing PWM on Pin
2,3,5,11,12,44,45,46).. For 48 servos all 16bit timers 5,1,3 and 4 will be used (loosing all PWM
pins).
 Pin 11 has shared functionality PWM and MOSI. MOSI is needed for the SPI interface, You
can’t use PWM on Pin 11 and the SPI interface at the same time on Arduino. On the Arduino
Mega the SPI pins are on different pins.
 tone() function uses at least timer2. You can’t use PWM on Pin 3,11 when you use the tone()
function an Arduino and Pin 9,10 on Arduino Mega.

Examples

Time for some examples.

Blinking LED with compare match interrupt

The first example uses the timer1 in CTC mode and the compare match interrupt to toggle a
LED. The timer is configured for a frequency of 2Hz. The LED is toggled in the interrupt service
routine.

/* Arduino 101: timer and interrupts


1: Timer1 compare match interrupt example
more infos: http://www.letmakerobots.com/node/28278
created by RobotFreak
*/

#define ledPin 13

void setup()

pinMode(ledPin, OUTPUT);
// initialize timer1

noInterrupts(); // disable all interrupts

TCCR1A = 0;

TCCR1B = 0;

TCNT1 = 0;

OCR1A = 31250; // compare match register 16MHz/256/2Hz

TCCR1B |= (1 << WGM12); // CTC mode

TCCR1B |= (1 << CS12); // 256 prescaler

TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt

interrupts(); // enable all interrupts

ISR(TIMER1_COMPA_vect) // timer compare interrupt service


routine

digitalWrite(ledPin, digitalRead(ledPin) ^ 1); // toggle LED pin

void loop()

{
// your program here…

Blinking LED with timer overflow interrupt

same example like before but now we use the timer overflow interrupt.
In this case timer1 is running in normal mode.

The timer must be preloaded every time in the interrupt service


routine.

/*
* Arduino 101: timer and interrupts
* 2: Timer1 overflow interrupt example
* more infos: http://www.letmakerobots.com/node/28278
* created by RobotFreak
*/

#define ledPin 13

void setup()
{
pinMode(ledPin, OUTPUT);

// initialize timer1
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;

TCNT1 = 34286; // preload timer 65536-16MHz/256/2Hz


TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
interrupts(); // enable all interrupts
}

ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a


user defined function supplied by attachInterrupt
{
TCNT1 = 34286; // preload timer
digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
}

void loop()
{
// your program here...
}
Reading quadrature encoders with a timer

The next example is part of my Ardubot project 2. It uses timer2 and the compare match
interrupt to read the encoder inputs. Timer2 is initialized by default to a frequency of 1kHz (1ms
period). In the interrupt service routine the state of all encoder pins is read and a state machine is
used to eliminate false readings. Using the timer interrupt is much easier to handle than using 4
input change interrupts.

The signals of a quadrature encoder is a 2bit Gray code. Only 1 bit is changing from state to
state. A state machine is perfect to check the signal and count the encoder ticks. The timer must
be fast enough, to recognize each state change. For the Pololu wheel encoders used here, the
1ms timer is fast enough.

The following example has been modified to work with Arduino V1.x

/*
/*
* Arduino 101: timer and interrupts
* 3: Timer2 compare interrupt example. Quadrature Encoder
* more infos: http://www.letmakerobots.com/node/28278
* created by RobotFreak
*
* Credits:
* based on code from Peter Dannegger
* http://www.mikrocontroller.net/articles/Drehgeber
*/

#if ARDUINO >= 100

#include “Arduino.h”
#else

#include “WConstants.h”

#endif

// Encoder Pins

#define encLtA 2

#define encLtB 3

#define encRtA 11

#define encRtB 12

#define ledPin 13

#define LT_PHASE_A digitalRead(encLtA)

#define LT_PHASE_B digitalRead(encLtB)

#define RT_PHASE_A digitalRead(encRtA)

#define RT_PHASE_B digitalRead(encRtB)

static volatile int8_t encDeltaLt, encDeltaRt;

static int8_t lastLt, lastRt;

int encLt, encRt;

ISR( TIMER2_COMPA_vect )
{

int8_t val, diff;

digitalWrite(ledPin, HIGH); // toggle LED pin

val = 0;

if( LT_PHASE_A )

val = 3;

if( LT_PHASE_B )

val ^= 1; // convert gray to binary

diff = lastLt - val; // difference last -


new

if( diff & 1 ){ // bit 0 = value (1)

lastLt = val; // store new as next last

encDeltaLt += (diff & 2) - 1; // bit 1 = direction (+/-)

val = 0;

if( RT_PHASE_A )

val = 3;

if( RT_PHASE_B )
val ^= 1; // convert gray to binary

diff = lastRt - val; // difference last -


new

if( diff & 1 ){ // bit 0 = value (1)

lastRt = val; // store new as next last

encDeltaRt += (diff & 2) - 1; // bit 1 = direction (+/-)

digitalWrite(ledPin, LOW); // toggle LED pin

void QuadratureEncoderInit(void)

int8_t val;

cli();

TIMSK2 |= (1<<OCIE2A);

sei();

pinMode(encLtA, INPUT);

pinMode(encRtA, INPUT);

pinMode(encLtB, INPUT);

pinMode(encRtB, INPUT);
val=0;

if (LT_PHASE_A)

val = 3;

if (LT_PHASE_B)

val ^= 1;

lastLt = val;

encDeltaLt = 0;

val=0;

if (RT_PHASE_A)

val = 3;

if (RT_PHASE_B)

val ^= 1;

lastRt = val;

encDeltaRt = 0;

encLt = 0;

encRt = 0;

}
int8_t QuadratureEncoderReadLt( void ) // read
single step encoders

int8_t val;

cli();

val = encDeltaLt;

encDeltaLt = 0;

sei();

return val; // counts since last call

int8_t QuadratureEncoderReadRt( void ) // read


single step encoders

int8_t val;

cli();

val = encDeltaRt;

encDeltaRt = 0;

sei();

return val; // counts since last call


}

void setup()

Serial.begin(38400);

pinMode(ledPin, OUTPUT);

QuadratureEncoderInit();

void loop()

encLt += QuadratureEncoderReadLt();

encRt += QuadratureEncoderReadRt();

Serial.print("Lt: “);

Serial.print(encLt, DEC);

Serial.print(” Rt: ");

Serial.println(encRt, DEC);

delay(1000);

}
Update 02/11/2014:

Q: Why have some variables the volatile keyword, like encodeDeltaLt and encodeDeltaRt in the
examples above?

A: Read about using the volatile keyword here: http://arduino.cc/en/Reference/Volatile 3

Good link:
https://learn.adafruit.com/multi-tasking-the-arduino-part-2/timers

Potrebbero piacerti anche