Created
November 16, 2016 09:24
-
-
Save Koepel/4fd63069a070c74d2e928ade9bc88d67 to your computer and use it in GitHub Desktop.
Arduino sketch to calculate how much time is wasted in delays.
This file contains 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
// Wasted | |
// ------ | |
// Show the percentage of cpu time that is wasted in delay(). | |
// ---------------------------------------------------------- | |
// | |
// 8 nov 2016, by Koepel. | |
// first version. Public Domain. | |
// | |
// 16 nov 2016, by Koepel | |
// Added more comment. Added fixed delay inside yield(). | |
// Calculate the percentage more flexible, to allow any | |
// interval time, instead of the fixed 1 minute. | |
// Tested with Arduino.cc IDE 1.6.12 and Arduino Uno | |
// | |
// Just some fun with delay() and millis(). | |
// Call Wasted_init() during setup(), | |
// and add the code at the bottom. | |
// Have a serial port open, and it | |
// will print every minute how much | |
// precious cpu time is wasted in delays. | |
// | |
// The calculation of the percentage can be done | |
// in other places in your sketch. If you have something running | |
// a few times a minute or once every few minutes, | |
// then it can be done there as well. | |
// The variables can be used without restriction, | |
// and they don't have to be 'volatile', because | |
// there is no interrupt involved. | |
// If the calculation is done somewhere else, be sure to have: | |
// unsigned long wasted_currentMillis = millis(); | |
// | |
void setup() | |
{ | |
Serial.begin( 9600); | |
// while(!Serial); // for Leonardo | |
Serial.println( "Started"); | |
Wasted_init(); // <-- add this to setup() | |
pinMode( 13, OUTPUT); | |
} | |
void loop() | |
{ | |
// Test with delay() or calcPi() and see what the percentage is. | |
digitalWrite( 13, HIGH); | |
delay( 100); | |
// calcPi(); | |
digitalWrite( 13, LOW); | |
delay( 100); | |
// calcPi(); | |
} | |
void calcPi() | |
{ | |
float x = 1.0; | |
float pi = 1.0; | |
for( unsigned long t = 2UL; t < 5000UL; t++) | |
{ | |
x *= -1.0; | |
pi += x / ( (2.0 * (float) t) - 1.0); | |
} | |
pi *= 4; | |
// print pi, once in 100 times. | |
static int cnt; | |
cnt++; | |
if( cnt >= 100) | |
{ | |
cnt = 0; | |
Serial.println( pi, 8); | |
} | |
} | |
// --------------------------------------- | |
// Add the following part to your sketch. | |
// It uses the Serial port to show every minute | |
// to the serial monitor which percentage of | |
// precious cpu time was wasted in delays. | |
// | |
// It only checks delay(), not delayMicroseconds(). | |
// --------------------------------------- | |
// The preset value of 77967 is the value for | |
// an Arduino Uno (in case the init function is not called). | |
unsigned long wasted_CountsPerSecond = 77967; | |
unsigned long wasted_Count; | |
unsigned long wasted_previousMillis; | |
void Wasted_init() | |
{ | |
// Calibrate the number of counts. | |
delay( 100); // wait a little, perhaps serial data is being transmitted. | |
wasted_Count = 0UL; | |
delay( 1000); | |
wasted_CountsPerSecond = wasted_Count; | |
// Make a fresh start for the next count. | |
wasted_Count = 0UL; | |
wasted_previousMillis = millis(); | |
// Serial.print(F( "CountsPerSecond=")); | |
// Serial.println( wasted_CountsPerSecond); | |
} | |
// Override the weak function that is called from delay(). | |
// See : https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring.c | |
void yield() | |
{ | |
// ---------------------------------------------------- | |
// Begin of code to calculate the percentage | |
// ---------------------------------------------------- | |
unsigned long wasted_currentMillis = millis(); | |
if( wasted_currentMillis - wasted_previousMillis >= 60000UL) // every minute | |
{ | |
// Hopefully the calculation will be okay with unsigned long. | |
// Calculating the interval is even valid in case of a rollover of millis(). | |
// By calculating the interval in seconds, the accuracy drops for short intervals, | |
// but it makes it possible to use 32-bit unsigned long for longer intervals. | |
// The "wasted_Count" is multiplied by 100 for the percentage. | |
unsigned long interval_in_seconds = (wasted_currentMillis - wasted_previousMillis) / 1000UL; | |
unsigned long wasted_percentage = (wasted_Count * 100UL) / (wasted_CountsPerSecond * interval_in_seconds); | |
Serial.print(F( "Wasted: ")); | |
Serial.print( wasted_percentage); | |
Serial.print(F( "%")); | |
if( wasted_percentage < 2UL) // less then 2% ? | |
{ | |
// It turns out to be a very small percentage. | |
// Calculate the actual total delay in milliseconds in this interval. | |
unsigned long wasted_delay = wasted_Count / (wasted_CountsPerSecond / 1000UL); | |
Serial.print(F( " (")); | |
Serial.print( wasted_delay); | |
Serial.print(F( "ms)")); | |
} | |
Serial.println(); | |
// Serial.print(F( "Count=")); | |
// Serial.print( wasted_Count); | |
// Serial.print(F( ", interval=")); | |
// Serial.print( interval_in_seconds); | |
// Serial.print(F( "s")); | |
// Serial.println(); | |
// Set the variables for the next interval | |
wasted_previousMillis = wasted_currentMillis; // remember current time for next interval | |
wasted_Count = 0UL; // reset the counter | |
} | |
// ---------------------------------------------------- | |
// End of code to calculate the percentage | |
// ---------------------------------------------------- | |
// An extra fixed delay of 6 microseconds for fast processors. | |
// This is not needed for AVR chips, but it will do no harm. | |
// It will reduce the count for the unsigned long counter. | |
delayMicroseconds( 6); | |
wasted_Count++; // increment while being in the delay | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment