I put together a quick test of an idea I had to keep tracks of things like timers without blocking the loop. My code is as follows, but I don't understand why the LED only blinks 16 times, and then stops (off).
#include <loopTimer.h>
int led13setup = 0;
int led13last_time = 0;
int led13next_time = 0;
int led13status = 0;
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
blinkLed13();
}
void blinkLed13() {
if (led13setup == 0) {
pinMode(13, OUTPUT);
led13setup = 1;
}
if (led13last_time == 0) {
led13last_time = millis();
led13next_time = millis() + 1000;
digitalWrite(13, HIGH);
} else {
if (millis() > led13next_time) {
led13last_time = led13next_time;
led13next_time = millis() + 1000;
if (led13status == 1) {
led13status=0;
digitalWrite(13, LOW);
} else {
led13status=1;
digitalWrite(13, HIGH);
}
}
}
}
The maximum values if the signed int variables are causing the problem and you have made it worse by using addition instead of subtraction in the calculations
I was struggling to wrap my head around why this doesn't break on rollover.
Assumptions / understanding:
Unsigned long variables have a range from 0 to 4,294,967,295.
When an unsigned long reaches this limit, it rolls over to zero.
IF statement checks to see if currentMillis - previousMillis >= interval
Example:
If interval is 1000
and previousMillis = 4,294,967,200
and currentMillis = 805
805 - 4,294,967,200 = -4,294,966,395.
But the result is cast as an unsigned long!
if ((unsigned long)(currentMillis - previousMillis) >= interval)
Since an unsigned long cannot hold a negative value, I believe it would store the absolute value instead. This would be greater than or equal to the interval. However, it would reach this status as soon as the millis rolled over to zero. This would result in an incorrect interval pulse every 49ish days.
I am still left with an anomaly at rollover, but I think it can be a non-issue if handled properly. Blinking an LED is just a simple task to illustrate the concept of non-blocking wait.
The current task is to utilize various counters (scaled in minutes) and act once they reach a target threshold. The counters initialize and reset based on a switch position. In this case, it would be the ignition switch position.
Arduino wakes and enables power to different areas if switch is turned "on", and begins timers to disable power to areas at intervals after switch is turned "off". For example, the power windows might retain power for 5 minutes after the vehicle has been powered off, but interior lights are powered for 30 mintes.
If I set an interval of 1000, and a timer process uses that interval to count up 5 minutes, then a rollover anomaly would have almost zero impact as it would only truncate a single 1000ms interval out of 300,000.
It is simple.
Lets a clock for example.
If your interval start at 58 minutes of an hour, but end at 12 minutes of next hour, so the difference between times wion't (- 46) minutes (12 - 58) and even not a 46 minutes (absolute value of 12 -58), but 14 minutes.