|
33 | 33 | * [3. Timer2](#3-timer2) |
34 | 34 | * [4. Timer3, Timer4, Timer5](#4-timer3-timer4-timer5) |
35 | 35 | * [5. Important Notes](#5-important-notes) |
36 | | -* [How to use](#how-to-use) |
| 36 | +* [Usage](#usage) |
| 37 | + * [1. Using only Hardware Timer directly](#1-using-only-hardware-timer-directly) |
| 38 | + * [1.1 Init Hardware Timer](#11-init-hardware-timer) |
| 39 | + * [1.2 Set Hardware Timer Interval and attach Timer Interrupt Handler function](#12-set-hardware-timer-interval-and-attach-timer-interrupt-handler-function) |
| 40 | + * [1.3 Set Hardware Timer Frequency and attach Timer Interrupt Handler function](#13-set-hardware-timer-frequency-and-attach-timer-interrupt-handler-function) |
| 41 | + * [2. Using 16 ISR_based Timers from 1 Hardware Timer](#2-using-16-isr_based-timers-from-1-hardware-timer) |
| 42 | + * [2.1 Important Note](#21-important-note) |
| 43 | + * [2.2 Init Hardware Timer and ISR-based Timer](#22-init-hardware-timer-and-isr-based-timer) |
| 44 | + * [2.3 Set Hardware Timer Interval and attach Timer Interrupt Handler functions](#23-set-hardware-timer-interval-and-attach-timer-interrupt-handler-functions) |
37 | 45 | * [Examples](#examples) |
38 | 46 | * [ 1. Argument_Complex](examples/Argument_Complex) |
39 | 47 | * [ 2. Argument_None](examples/Argument_None) |
@@ -251,98 +259,186 @@ Timer3, Timer4 and Timer5 are only available for Arduino Mega boards. |
251 | 259 | --- |
252 | 260 | --- |
253 | 261 |
|
254 | | -## How to use |
| 262 | +## Usage |
255 | 263 |
|
256 | | -``` |
257 | | -// These define's must be placed at the beginning before #include "TimerInterrupt.h" |
258 | | -// Don't define TIMER_INTERRUPT_DEBUG > 0. Only for special ISR debugging only. Can hang the system. |
259 | | -#define TIMER_INTERRUPT_DEBUG 0 |
| 264 | +Before using any Timer, you have to make sure the Timer has not been used by any other purpose. |
| 265 | + |
| 266 | +### 1. Using only Hardware Timer directly |
| 267 | + |
| 268 | +#### 1.1 Init Hardware Timer |
260 | 269 |
|
| 270 | +``` |
| 271 | +// Select the timers you're using, here ITimer1 |
261 | 272 | #define USE_TIMER_1 true |
262 | | -#define USE_TIMER_2 true |
| 273 | +#define USE_TIMER_2 false |
263 | 274 | #define USE_TIMER_3 false |
264 | 275 | #define USE_TIMER_4 false |
265 | 276 | #define USE_TIMER_5 false |
266 | 277 |
|
267 | | -#include "TimerInterrupt.h" |
| 278 | +// Init timer ITimer1 |
| 279 | +ITimer1.init(); |
| 280 | +``` |
268 | 281 |
|
269 | | -void TimerHandler1(void) |
270 | | -{ |
271 | | - static bool toggle1 = false; |
272 | | - static bool started = false; |
| 282 | +#### 1.2 Set Hardware Timer Interval and attach Timer Interrupt Handler function |
273 | 283 |
|
274 | | - if (!started) |
275 | | - { |
276 | | - started = true; |
277 | | - pinMode(LED_BUILTIN, OUTPUT); |
278 | | - } |
| 284 | +Use one of these functions with **interval in unsigned long milliseconds** |
| 285 | + |
| 286 | +``` |
| 287 | +// interval (in ms) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely |
| 288 | +template<typename TArg> bool setInterval(unsigned long interval, void (*callback)(TArg), TArg params, unsigned long duration = 0); |
279 | 289 |
|
280 | | - //timer interrupt toggles pin LED_BUILTIN |
281 | | - digitalWrite(LED_BUILTIN, toggle1); |
282 | | - toggle1 = !toggle1; |
| 290 | +// interval (in ms) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely |
| 291 | +bool setInterval(unsigned long interval, timer_callback callback, unsigned long duration = 0); |
| 292 | +
|
| 293 | +// Interval (in ms) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely |
| 294 | +template<typename TArg> bool attachInterruptInterval(unsigned long interval, void (*callback)(TArg), TArg params, unsigned long duration = 0); |
| 295 | +
|
| 296 | +// Interval (in ms) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely |
| 297 | +bool attachInterruptInterval(unsigned long interval, timer_callback callback, unsigned long duration = 0) |
| 298 | +``` |
| 299 | + |
| 300 | +as follows |
| 301 | + |
| 302 | +``` |
| 303 | +void TimerHandler0() |
| 304 | +{ |
| 305 | + // Doing something here inside ISR |
283 | 306 | } |
284 | 307 |
|
285 | | -void TimerHandler2(void) |
| 308 | +#define TIMER0_INTERVAL_MS 50L |
| 309 | +
|
| 310 | +void setup() |
286 | 311 | { |
287 | | - static bool toggle2 = false; |
288 | | - static bool started = false; |
| 312 | + .... |
| 313 | + |
| 314 | + // Interval in unsigned long millisecs |
| 315 | + if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS, TimerHandler0)) |
| 316 | + Serial.println("Starting ITimer0 OK, millis() = " + String(millis())); |
| 317 | + else |
| 318 | + Serial.println("Can't set ITimer0. Select another freq. or timer"); |
| 319 | +} |
| 320 | +``` |
289 | 321 |
|
290 | | - if (!started) |
291 | | - { |
292 | | - started = true; |
293 | | - pinMode(A0, OUTPUT); |
294 | | - } |
| 322 | +#### 1.3 Set Hardware Timer Frequency and attach Timer Interrupt Handler function |
295 | 323 |
|
296 | | - //timer interrupt toggles outputPin |
297 | | - digitalWrite(A0, toggle2); |
298 | | - toggle2 = !toggle2; |
299 | | -} |
| 324 | +Use one of these functions with **frequency in float Hz** |
| 325 | + |
| 326 | +``` |
| 327 | +// frequency (in hertz) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely |
| 328 | +bool setFrequency(float frequency, timer_callback_p callback, /* void* */ uint32_t params, unsigned long duration = 0); |
300 | 329 |
|
301 | | -#define TIMER1_INTERVAL_MS 1000 |
| 330 | +// frequency (in hertz) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely |
| 331 | +bool setFrequency(float frequency, timer_callback callback, unsigned long duration = 0); |
| 332 | +
|
| 333 | +// frequency (in hertz) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely |
| 334 | +template<typename TArg> bool attachInterrupt(float frequency, void (*callback)(TArg), TArg params, unsigned long duration = 0); |
| 335 | +
|
| 336 | +// frequency (in hertz) and duration (in milliseconds). Duration = 0 or not specified => run indefinitely |
| 337 | +bool attachInterrupt(float frequency, timer_callback callback, unsigned long duration = 0); |
| 338 | +``` |
302 | 339 |
|
303 | | -#define TIMER2_INTERVAL_MS 2000 |
| 340 | +as follows |
| 341 | + |
| 342 | +``` |
| 343 | +void TimerHandler0() |
| 344 | +{ |
| 345 | + // Doing something here inside ISR |
| 346 | +} |
| 347 | +
|
| 348 | +#define TIMER0_FREQ_HZ 5555.555 |
304 | 349 |
|
305 | 350 | void setup() |
306 | 351 | { |
307 | | - Serial.begin(115200); |
308 | | - while (!Serial); |
| 352 | + .... |
| 353 | + |
| 354 | + // Frequency in float Hz |
| 355 | + if (ITimer0.attachInterrupt(TIMER0_FREQ_HZ, TimerHandler0)) |
| 356 | + Serial.println("Starting ITimer0 OK, millis() = " + String(millis())); |
| 357 | + else |
| 358 | + Serial.println("Can't set ITimer0. Select another freq. or timer"); |
| 359 | +} |
| 360 | +``` |
309 | 361 |
|
310 | | - Serial.println(F("\nStarting Argument_None")); |
311 | | - Serial.println(TIMER_INTERRUPT_VERSION); |
312 | | - Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); |
313 | 362 |
|
314 | | - // Select Timer 1-2 for UNO, 0-5 for MEGA |
315 | | - // Timer 2 is 8-bit timer, only for higher frequency |
316 | | - ITimer1.init(); |
| 363 | +### 2. Using 16 ISR_based Timers from 1 Hardware Timer |
317 | 364 |
|
318 | | - // Using ATmega328 used in UNO => 16MHz CPU clock , |
319 | | - // For 16-bit timer 1, 3, 4 and 5, set frequency from 0.2385 to some KHz |
320 | | - // For 8-bit timer 2 (prescaler up to 1024, set frequency from 61.5Hz to some KHz |
| 365 | +### 2.1 Important Note |
321 | 366 |
|
322 | | - if (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS, TimerHandler1)) |
323 | | - { |
324 | | - Serial.print(F("Starting ITimer1 OK, millis() = ")); Serial.println(millis()); |
325 | | - } |
326 | | - else |
327 | | - Serial.println(F("Can't set ITimer1. Select another freq. or timer")); |
| 367 | +The 16 ISR_based Timers, designed for long timer intervals, only support using **unsigned long millisec intervals**. If you have to use much higher frequency or sub-millisecond interval, you have to use the Hardware Timers directly as in [1.3 Set Hardware Timer Frequency and attach Timer Interrupt Handler function](#13-set-hardware-timer-frequency-and-attach-timer-interrupt-handler-function) |
328 | 368 |
|
329 | | - // Select Timer 1-2 for UNO, 0-5 for MEGA |
330 | | - // Timer 2 is 8-bit timer, only for higher frequency |
331 | | - ITimer2.init(); |
| 369 | +### 2.2 Init Hardware Timer and ISR-based Timer |
332 | 370 |
|
333 | | - if (ITimer2.attachInterruptInterval(TIMER2_INTERVAL_MS, TimerHandler2)) |
334 | | - { |
335 | | - Serial.print(F("Starting ITimer2 OK, millis() = ")); Serial.println(millis()); |
336 | | - } |
337 | | - else |
338 | | - Serial.println(F("Can't set ITimer2. Select another freq. or timer")); |
| 371 | +``` |
| 372 | +// Select the timers you're using, here ITimer2 |
| 373 | +#define USE_TIMER_1 false |
| 374 | +#define USE_TIMER_2 true |
| 375 | +#define USE_TIMER_3 false |
| 376 | +#define USE_TIMER_4 false |
| 377 | +#define USE_TIMER_5 false |
| 378 | +
|
| 379 | +// Init ISR_Timer |
| 380 | +// Each ISR_Timer can service 16 different ISR-based timers |
| 381 | +ISR_Timer ISR_Timer2; |
| 382 | +``` |
| 383 | + |
| 384 | +#### 2.3 Set Hardware Timer Interval and attach Timer Interrupt Handler functions |
| 385 | + |
| 386 | +``` |
| 387 | +void TimerHandler() |
| 388 | +{ |
| 389 | + ISR_Timer2.run(); |
339 | 390 | } |
340 | 391 |
|
341 | | -void loop() |
| 392 | +#define HW_TIMER_INTERVAL_MS 50L |
| 393 | +
|
| 394 | +#define TIMER_INTERVAL_2S 2000L |
| 395 | +#define TIMER_INTERVAL_5S 5000L |
| 396 | +#define TIMER_INTERVAL_11S 11000L |
| 397 | +#define TIMER_INTERVAL_101S 101000L |
| 398 | +
|
| 399 | +// In AVR, avoid doing something fancy in ISR, for example complex Serial.print with String() argument |
| 400 | +// The pure simple Serial.prints here are just for demonstration and testing. Must be eliminate in working environment |
| 401 | +// Or you can get this run-time error / crash |
| 402 | +void doingSomething2s() |
| 403 | +{ |
| 404 | + // Doing something here inside ISR every 2 seconds |
| 405 | +} |
| 406 | + |
| 407 | +void doingSomething5s() |
| 408 | +{ |
| 409 | + // Doing something here inside ISR every 5 seconds |
| 410 | +} |
| 411 | +
|
| 412 | +void doingSomething11s() |
342 | 413 | { |
| 414 | + // Doing something here inside ISR every 11 seconds |
| 415 | +} |
343 | 416 |
|
| 417 | +void doingSomething101s() |
| 418 | +{ |
| 419 | + // Doing something here inside ISR every 101 seconds |
344 | 420 | } |
345 | 421 |
|
| 422 | +void setup() |
| 423 | +{ |
| 424 | + .... |
| 425 | + |
| 426 | + // Interval in microsecs |
| 427 | + if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_MS * 1000, TimerHandler)) |
| 428 | + { |
| 429 | + lastMillis = millis(); |
| 430 | + Serial.println("Starting ITimer OK, millis() = " + String(lastMillis)); |
| 431 | + } |
| 432 | + else |
| 433 | + Serial.println("Can't set ITimer correctly. Select another freq. or interval"); |
| 434 | +
|
| 435 | + // Just to demonstrate, don't use too many ISR Timers if not absolutely necessary |
| 436 | + // You can use up to 16 timer for each ISR_Timer |
| 437 | + ISR_Timer2.setInterval(TIMER_INTERVAL_2S, doingSomething2s); |
| 438 | + ISR_Timer2.setInterval(TIMER_INTERVAL_5S, doingSomething5s); |
| 439 | + ISR_Timer2.setInterval(TIMER_INTERVAL_11S, doingSomething11s); |
| 440 | + ISR_Timer2.setInterval(TIMER_INTERVAL_101S, doingSomething101s); |
| 441 | +} |
346 | 442 | ``` |
347 | 443 |
|
348 | 444 | --- |
|
0 commit comments