Last active
April 28, 2020 18:01
-
-
Save ctmakro/59b0b1841b09777f13ae87255d865e7d to your computer and use it in GitHub Desktop.
Correct way to do precisely timed routine task on Arduino
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
With an Arduino, | |
If you want to: | |
1) execute a function precisely every N microseconds (or precisely 1,000,000/N times every second), | |
REGARDLESS of the running time of that function | |
2) obtain a precision of +-4 microseconds with NO ACCUMULATION OF ERROR | |
3) use no 3rd party libraries | |
Then this is for you. | |
*/ | |
// every time toggle() is called, we flip pin 13 (LED). | |
unsigned char j = 0; | |
void toggle() { | |
j = 1 - j; | |
digitalWrite(13, j ? HIGH : LOW); | |
} | |
typedef unsigned long ul; | |
class Every { | |
ul last_t; | |
public: | |
ul interval; void(*callback)(); | |
Every(ul itvl, void(*cb)()) : interval(itvl), callback(cb) {} | |
// interval(microseconds) should be an unsigned long (uint32) less than or equals 2^30. | |
void update() { | |
if ((ul)(micros() - last_t) >= interval) { | |
callback(); last_t += interval; | |
} | |
} | |
}; | |
Every e(1000, toggle); | |
// run toggle() every 1000us. (equivalent to running toggle() at 1000Hz) | |
// by running toggle() at 1000Hz one can obtain a 500Hz square wave on pin 13. | |
// actual frequency may vary by the oscillator used (crystal vs ceramic vs internal) | |
// by changing 1000 to 10000, the frequency of the square wave should drop to | |
// precisely 1/10 of the original frequency when measured with a frequency meter. | |
void setup() { | |
pinMode(13, OUTPUT); | |
} | |
void loop() { | |
e.update(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment