I'll start with saying that I know multithreading isn't really available in Arduino, and what I mean when I say it, is when you do something like this:
bool handle = false;
void setup() {...}
unsigned long lastTimer = 0;
void loop() {
unsigned long myTimer = millis();
if (distance >= 500) { // trigger
if (handle) { // already in action
Serial.print("already handling");
} else {
handle = true; // flag to indicate an action is needed
lastTimer = myTimer; // saving current time
}
}
if (handle) { // if an action is needed
moveBack(); // action - e.g. moving motors backwards
if (myTimer - lastTimer >= 3000) { // Just after 3 seconds, stopping the action
handle = false;
lastTimer = myTimer;
}
}
}
The thing is, it sometimes jumps straight inside the
if (myTimer - lastTimer >= 3000) {...}
with no "delay" - I couldn't find any "pattern" for when it does and when it doesn't.
Sometimes it happens after 10 seconds, sometimes 2 minutes, no fixed timing.
It makes absolutely no sense to me, how can it sometimes work, and sometimes not..
Does anyone have any idea why can it happen?
A millis-timer is started somewhere and the millis-timer itself should run in the main level of the loop().
So you start it, and then let the millis-timer run on its own. If you want to be able to stop a millis-timer, then you can put it behind one if-statement. But that's all, don't hide it at a deeper level.
When you do something with millis(), use 'unsigned long'.
It is 100% reliable and it always works, unless the sketch is wrong.
bool run_blink_led;
bool run_buzzer;
void loop()
{
if button pressed
start a millis timer
if temperature too low and it is not night
start a millis timer
millis-timer to turn something off after some time
millis-timer to read sensors
millis-timer to update a display
if(run_blink_led)
millis-timer to blink a led
if(run_buzzer)
millis-timer to sound a buzzer
}
Multithreading is available. There are a few good options, such as the simple scheduler for SAMD boards, or the full FreeRTOS on a ESP32 (which is not an Arduino board, but it is made Arduino-compatible) or the TaskSchedular which even runs on a Arduino Uno.
The problem is not the multithreading, but the problem is that each task requires its own stack and the Arduino Uno has very little SRAM.
I had a lot of fun with the simple schedular. But even on a Arduino Zero with 32kbyte of SRAM, I still have to be careful with the stack usage. The number of tasks seems to grow every time I think of adding something extra.
I want moveBack(); to happen for 3 seconds, not after 3 seconds.
After 3 seconds (when the if is true) the flag variable will be changed, which will make the if (handle) be false, and won't call moveBack(); anymore.
And as I said, it works, but not always - it randomly stops working, and jumps straight into the if (the timer) as if it was always true.
Is there something I missing about the logic, that might explain why it sometimes work, and then stops working? (And once it stops working and jumps straight into the if, it doesn't work again, and will always jump into the if)