// Toy for comparing rate limiting schemes
// Wokwi simulation: https://wokwi.com/projects/406476811823126529
// Slide the pot back and forth to change between schemes
// read how many times the code goes through loop() and gets
// a chance to do other things.
//
// See https://forum.arduino.cc/t/best-first-5-topics-to-read-to-reach-trust-level-1/1287592
// in particular the
// https://forum.arduino.cc/t/demonstration-code-for-several-things-at-the-same-time/217158
//
// attach a potentiometer wiper pin to A0/modePin and the potentiometer extremes to GND and +
//
const byte modePin = A0;
const unsigned long delayIntervalMs = 30; //
int choice = 0;
unsigned long currentMillis;
void setup() {
Serial.begin(115200); // Baud rate can limit loop speed too.
// Try 115200 vs 9600 vs 300 to see baud rate effects
Serial.print("rateLimitingToy -- https://wokwi.com/projects/406476811823126529\n"
"Slide the pot to change between modes:\n"
"while(..); , delay(), millis()/BWOD, unlimited\n"
);
}
void loop() {
Input(); // Read sensors // Input of IPO programming model https://en.wikipedia.org/wiki/IPO_model
Process();
// Output
report(); // count loop() cycles/second and print
}
void rateLimitedThing() {
// Check the millis() clock to see if it is time to do a Thing.
const unsigned long interval = delayIntervalMs;
static unsigned long lastMs = 0;
unsigned long now = millis();
if (now - lastMs >= interval) {
lastMs = now; // or lastMs += interval;
Serial.print("r");
}
}
void Input() { // Input of the IPO model https://en.wikipedia.org/wiki/IPO_model
// this separates the input from the other bits of the program so the rest of it is
// all working with the same data
//This rate-limits the analogRead because we don't need to respond instantly
const unsigned long interval = 50;
static unsigned long lastMs = 0;
currentMillis = millis();
if (currentMillis - lastMs >= interval) {
lastMs = currentMillis; // or lastMs += interval;
choice = analogRead(modePin) / 256; // recode range as 0-3
}
}
void Process() {
// Processing
switch (choice) { // choose a method of rate limiting to use for this cycle of loop()
case 0: // stop while(waiting for something to end)
Serial.print("while(something);");
while (analogRead(modePin) / 256 == 0) {
;
}
Serial.print("...done\n");
report();
break;
case 1: // slow down iterations with delay()
Serial.print("d");
delay(delayIntervalMs);
break;
case 2: // rate limited by testing time
rateLimitedThing();
break;
case 3: // unlimited
Serial.print("u");
break;
default:
Serial.print("unexpected choice value");
Serial.println(choice);
}
}
void report() {
// this routine cooperatively counts how many opportunities it
// was given to run in a second
static unsigned long loopcount = 0; // remember count
const unsigned long interval = 1000;
static unsigned long lastMs = 0;
unsigned long now = millis();
if (now - lastMs >= interval) { //
// choose & uncomment one of these:
//lastMs = now; // catch up
//lastMs += interval; // phase locked count each
while (now - lastMs >= interval) lastMs += interval; // phase loc with skip
Serial.println();
Serial.print(now);
Serial.print("ms LoopCount: ");
Serial.print(loopcount);
Serial.print("/sec\n");
loopcount = 0;
}
++loopcount; // count this cycle
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
pot1:VCC
pot1:SIG
pot1:GND