
このページは私がよく使っているSimpleTimerライブラリのリファレンスです。
公式が消えているのでアーカイブからのコピペです。
インストール方法などはいらないと判断して省いています。
似たようなライブラリが何個もあるためどれが本家なのかは分かりません...
昔からあるライブラリで更新もないので、使っている人も少数かもしれませんが個人的には使い慣れていますしシンプルで好きです。
スポンサーリンク
目次
- Description
- Download
- Usage
- Theory
- Functions
- SimpleTimer()
- int setInterval(long d, timer_callback f)
- int setTimeout(long d, timer_callback f)
- int setTimer(long d, timer_callback f, int n)
- boolean isEnabled(int timerId)
- void enable(int timerId)
- void disable(int timerId)
- void toggle(int timerId)
- void restartTimer(int timerId)
- void deleteTimer(int timerId)
- void getNumTimers()
- Example
- Get the code
- Contributing
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
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
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 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 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 getNumTimers()
Return the number of used slots in a timer object.
n = timer.getNumTimers();
Example
/* * SimpleTimerAlarmExample.pde * * Based on usage example for Time + TimeAlarm libraries * * A timer is called every 15 seconds * Another timer is called once only after 10 seconds * A third timer is called 10 times. * */ #include <SimpleTimer.h> // There must be one global SimpleTimer object. // More SimpleTimer objects can be created and run, // although there is little point in doing so. SimpleTimer timer; // function to be called repeatedly void RepeatTask() { Serial.println("15 second timer"); } // function to be called just once void OnceOnlyTask() { Serial.println("This timer only triggers once"); } // function to be called exactly 10 times void TenTimesTask() { static int k = 0; k++; Serial.print("called "); Serial.print(k); Serial.println(" / 10 times."); } // print current arduino "uptime" on the serial port void DigitalClockDisplay() { int h,m,s; s = millis() / 1000; m = s / 60; h = s / 3600; s = s - m * 60; m = m - h * 60; Serial.print(h); printDigits(m); printDigits(s); Serial.println(); } // // utility function for digital clock display: // prints preceding colon and leading 0 // void printDigits(int digits) { Serial.print(":"); if(digits < 10) Serial.print('0'); Serial.print(digits); } void setup() { Serial.begin(9600); // welcome message Serial.println("SimpleTimer Example"); Serial.println("One timer is triggered every 15 seconds"); Serial.println("Another timer is set to trigger only once after 10 seconds"); Serial.println("Another timer is set to trigger 10 times"); Serial.println(); // timed actions setup timer.setInterval(15000, RepeatTask); timer.setTimeout(10000, OnceOnlyTask); timer.setInterval(1000, DigitalClockDisplay); timer.setTimer(1200, TenTimesTask, 10); } void loop() { // this is where the "polling" occurs timer.run(); }
Get the code
/* * SimpleTimer.h * * SimpleTimer - A timer library for Arduino. * Author: mromani@ottotecnica.com * Copyright (c) 2010 OTTOTECNICA Italy * * This library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will * be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser * General Public License along with this library; if not, * write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef SIMPLETIMER_H #define SIMPLETIMER_H #if defined(ARDUINO) && ARDUINO >= 100 #include <Arduino.h> #else #include <WProgram.h> #endif typedef void (*timer_callback)(void); class SimpleTimer { public: // maximum number of timers const static int MAX_TIMERS = 10; // setTimer() constants const static int RUN_FOREVER = 0; const static int RUN_ONCE = 1; // constructor SimpleTimer(); // this function must be called inside loop() void run(); // call function f every d milliseconds int setInterval(long d, timer_callback f); // call function f once after d milliseconds int setTimeout(long d, timer_callback f); // call function f every d milliseconds for n times int setTimer(long d, timer_callback f, int n); // destroy the specified timer void deleteTimer(int numTimer); // restart the specified timer void restartTimer(int numTimer); // returns true if the specified timer is enabled boolean isEnabled(int numTimer); // enables the specified timer void enable(int numTimer); // disables the specified timer void disable(int numTimer); // enables the specified timer if it's currently disabled, // and vice-versa void toggle(int numTimer); // returns the number of used timers int getNumTimers(); // returns the number of available timers int getNumAvailableTimers() { return MAX_TIMERS - numTimers; }; private: // deferred call constants const static int DEFCALL_DONTRUN = 0; // don't call the callback function const static int DEFCALL_RUNONLY = 1; // call the callback function but don't delete the timer const static int DEFCALL_RUNANDDEL = 2; // call the callback function and delete the timer // find the first available slot int findFirstFreeSlot(); // value returned by the millis() function // in the previous run() call unsigned long prev_millis[MAX_TIMERS]; // pointers to the callback functions timer_callback callbacks[MAX_TIMERS]; // delay values long delays[MAX_TIMERS]; // number of runs to be executed for each timer int maxNumRuns[MAX_TIMERS]; // number of executed runs for each timer int numRuns[MAX_TIMERS]; // which timers are enabled boolean enabled[MAX_TIMERS]; // deferred function call (sort of) - N.B.: this array is only used in run() int toBeCalled[MAX_TIMERS]; // actual number of timers in use int numTimers; }; #endif
/* * SimpleTimer.cpp * * SimpleTimer - A timer library for Arduino. * Author: mromani@ottotecnica.com * Copyright (c) 2010 OTTOTECNICA Italy * * This library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will * be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser * General Public License along with this library; if not, * write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "SimpleTimer.h" // Select time function: //static inline unsigned long elapsed() { return micros(); } static inline unsigned long elapsed() { return millis(); } SimpleTimer::SimpleTimer() { unsigned long current_millis = elapsed(); for (int i = 0; i < MAX_TIMERS; i++) { enabled[i] = false; callbacks[i] = 0; // if the callback pointer is zero, the slot is free, i.e. doesn't "contain" any timer prev_millis[i] = current_millis; numRuns[i] = 0; } numTimers = 0; } void SimpleTimer::run() { int i; unsigned long current_millis; // get current time current_millis = elapsed(); for (i = 0; i < MAX_TIMERS; i++) { toBeCalled[i] = DEFCALL_DONTRUN; // no callback == no timer, i.e. jump over empty slots if (callbacks[i]) { // is it time to process this timer ? // see https://arduino.cc/forum/index.php/topic,124048.msg932592.html#msg932592 if (current_millis - prev_millis[i] >= delays[i]) { // update time //prev_millis[i] = current_millis; prev_millis[i] += delays[i]; // check if the timer callback has to be executed if (enabled[i]) { // "run forever" timers must always be executed if (maxNumRuns[i] == RUN_FOREVER) { toBeCalled[i] = DEFCALL_RUNONLY; } // other timers get executed the specified number of times else if (numRuns[i] < maxNumRuns[i]) { toBeCalled[i] = DEFCALL_RUNONLY; numRuns[i]++; // after the last run, delete the timer if (numRuns[i] >= maxNumRuns[i]) { toBeCalled[i] = DEFCALL_RUNANDDEL; } } } } } } for (i = 0; i < MAX_TIMERS; i++) { switch(toBeCalled[i]) { case DEFCALL_DONTRUN: break; case DEFCALL_RUNONLY: (*callbacks[i])(); break; case DEFCALL_RUNANDDEL: (*callbacks[i])(); deleteTimer(i); break; } } } // find the first available slot // return -1 if none found int SimpleTimer::findFirstFreeSlot() { int i; // all slots are used if (numTimers >= MAX_TIMERS) { return -1; } // return the first slot with no callback (i.e. free) for (i = 0; i < MAX_TIMERS; i++) { if (callbacks[i] == 0) { return i; } } // no free slots found return -1; } int SimpleTimer::setTimer(long d, timer_callback f, int n) { int freeTimer; freeTimer = findFirstFreeSlot(); if (freeTimer < 0) { return -1; } if (f == NULL) { return -1; } delays[freeTimer] = d; callbacks[freeTimer] = f; maxNumRuns[freeTimer] = n; enabled[freeTimer] = true; prev_millis[freeTimer] = elapsed(); numTimers++; return freeTimer; } int SimpleTimer::setInterval(long d, timer_callback f) { return setTimer(d, f, RUN_FOREVER); } int SimpleTimer::setTimeout(long d, timer_callback f) { return setTimer(d, f, RUN_ONCE); } void SimpleTimer::deleteTimer(int timerId) { if (timerId >= MAX_TIMERS) { return; } // nothing to delete if no timers are in use if (numTimers == 0) { return; } // don't decrease the number of timers if the // specified slot is already empty if (callbacks[timerId] != NULL) { callbacks[timerId] = 0; enabled[timerId] = false; toBeCalled[timerId] = DEFCALL_DONTRUN; delays[timerId] = 0; numRuns[timerId] = 0; // update number of timers numTimers--; } } // function contributed by code@rowansimms.com void SimpleTimer::restartTimer(int numTimer) { if (numTimer >= MAX_TIMERS) { return; } prev_millis[numTimer] = elapsed(); } boolean SimpleTimer::isEnabled(int numTimer) { if (numTimer >= MAX_TIMERS) { return false; } return enabled[numTimer]; } void SimpleTimer::enable(int numTimer) { if (numTimer >= MAX_TIMERS) { return; } enabled[numTimer] = true; } void SimpleTimer::disable(int numTimer) { if (numTimer >= MAX_TIMERS) { return; } enabled[numTimer] = false; } void SimpleTimer::toggle(int numTimer) { if (numTimer >= MAX_TIMERS) { return; } enabled[numTimer] = !enabled[numTimer]; } int SimpleTimer::getNumTimers() { return numTimers; }
Contributing
Contributions to the code are more than welcome. If you would like to suggest a code change, please head over to github:
https://github.com/marcelloromani/arduino/tree/master/SimpleTimer
スポンサーリンク
Leave a Comment