I have tried to get two separate functions to execute independently at the same time and cant seem to get anything other than a cascaded result no matter what I try…
EG: this basic example I would like the light to toggle on/off every second whilst separately executing the “up-time” publish function.
At the moment, the led flashes on, then off, then up-time is published, then wait for up-time delay to complete before the led flash again.
Should I be using a “nested loop”? I have tried but unable to get anything happening!
Delays will… Wait for it… Delay. Who would’ve guessed?
A delay will halt the microcontroller, having it do absolutely nothing until the day is over. Rather than doing your timing like that, try implementing ‘soft-delays’, like you have for the publish functionality by using the millis timer.
Or use software timers to set a flag which you check for in the loop, or…
Thanks @ScruffR for taking the time to help with this and providing example.
Using your example I was able to come up with the following which I will share for future reference with fellow Particle / C# enthusiasts having same query!
Many thanks
void loop()
{
unsigned long LoopTimeAcc01 = millis();
unsigned long LoopTimeAcc02 = millis();
// First looping routine:
if (LoopTimeAcc01 - LoopTimer01 > 3000)
{
LoopTimer01 = LoopTimeAcc01;
digitalWrite(Led01_EN, !digitalRead(Led01_EN));
}
// Second looping routine:
if (LoopTimeAcc02 - LoopTimer02 > 500)
{
LoopTimer02 = LoopTimeAcc02;
digitalWrite(Led02_EN, !digitalRead(Led02_EN));
}
}
I would have thought…
after 3 seconds, turn on Led01_EN
after 1 additional second, turn off Led01_EN
(essentially acting like a delay to hold the LED on for one second, without halting the controller?) whilst still allowing the second loop routine to run, undisturbed?
\void loop()
{
unsigned long LoopTimeAcc = millis();
// First looping routine:
if (LoopTimeAcc - LoopTimer01 > 3000)
{
LoopTimer01 = LoopTimeAcc;
digitalWrite(Led01_EN, HIGH);
}
if (LoopTimeAcc - LoopTimer03 > 4000)
{
LoopTimer03 = LoopTimeAcc;
digitalWrite(Led01_EN, LOW);
}
// Second looping routine:
if (LoopTimeAcc - LoopTimer02 > 500)
{
LoopTimer02 = LoopTimeAcc;
digitalWrite(Led02_EN, !digitalRead(Led02_EN));
}
}
I’d rather stick with the conventional aproach first - once you got the hang of that, you can move on to software timers as they are slightly more involved when it comes to what goes and what not inside a timer callback.
With conventional, there are several options, but one would look like this
void loop()
{
unsigned long LoopTimeAcc = millis();
// treat the less frequent action first, since it might impact the more frequent one
if (LoopTimeAcc - LoopTimer03 > 4000) // use the same timer variable for both linked actions
{
LoopTimer01 = LoopTimeAcc; // only after the full task is completed, reset the timer
digitalWrite(Led01_EN, LOW);
}
if (LoopTimeAcc - LoopTimer03 > 3000 && digitalRead(LED01_EN) == LOW)
{ // only do it when the time's up AND the LED isn't already on
// don't reset the timer, to have it carry on through to the second part of the action
digitalWrite(Led01_EN, HIGH);
}
// Second looping routine:
if (LoopTimeAcc - LoopTimer02 > 500)
{
LoopTimer02 = LoopTimeAcc;
digitalWrite(Led02_EN, !digitalRead(Led02_EN));
}
}
This is not the most elegant way of doing it, but should be very easy to understand.
For software timers for your 3+1 blink I’d go with one that fires every second and increment a counter a switch the light on when the counter is 3 (and off when it’s four just for clarity).
For the 500ms counter just do the same, or you could incorporate that in the same timer, half its periode to 500ms and double the check values to 6 (on) and 8 (off).
BTW, the above is not backyard but has its use for tasks that can’t go into timer callbacks for various reasons.
Although in my own code I’d write it a lot more streamlined
To clarify, backyard being the difference between by noob / leaning and perception as to what’s most appropriate and that of the professional coders like you guys.
On that note, this post alone has taught me so much. Your examples using my examples mean I can take the code “to the bench” and play / learn and grow my understanding, under the terms in the way that I learn best.
Grateful there are valued people such as yourself committed to helping others get through.
Cheers
Could you provide an example of your abouve comment of how one would go about coding the same Timer using half the value.
Example:
Timer mstTimer(1000, secCallback);
mstTimer(500, halfSecCallback);
The original intent of my code above is to choose the common factor for the desired periods (e.g. 500ms) in the constructor and increment a counter in the timer to distinguish the respective multiples of that common periode.