"multithreading" timer sometimes works, sometimes skips

Hey everyone,

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:

void setup() {
...
}

unsigned int lastTime = 0;
bool handle = false;

void loop() {
    unsigned int currentTime = millis();
    if (currentTime - lastTime >= 3000) {
        Serial.println("3 seconds passed");
        lastTime = currentTime;
    }
}

My real code, is 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?

Thanks in advance :ok_hand:

...is the wrong answer.

Oops

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 tried also unsigned long, same result.
Anyways, I updated the main post and added my code, maybe now you will understand me better

Thank you for your comment!

You're right about the if statements levels, however it doesn't matter in my case - the result is the same.

I update the main post, maybe now it will be more clear what I mean

From your real code. I am unfamiliar with the ellipsis operator.

a7

After three seconds, this becomes true:

  if (myTimer - lastTimer >= 3000)

That means the moveBack() has to be inside that if-statement, so it will be executed after three seconds.

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)

Thanks again for helping!

You didn't posted your complete sketch.

Are you using global defined variables of type String?
Are you using arrays?

It happens very often that the bug sits somewhere else than the coder thought of.
So if you want a deep analysis what it might be

You should post your complete sketch by using code-tags
There is an automatic function for doing this in the Arduino-IDE
just three steps

  1. press Ctrl-T for autoformatting your code
  2. do a rightclick with the mouse and choose "copy for forum"
  3. paste clipboard into write-window of a posting

best regards Stefan

1 Like

From the code you posted it makes no sense. However, there is code you haven't posted that may be causing issues.

1 Like