Go Down

Topic: How to use Timer to exit LoopA,then run LoopB? (Read 698 times) previous topic - next topic

Hi, I am very new to Arduino, my question is:
How to use Timer to do this:  Run LoopA 10sec. then Run LoopB 2sec., then LoopA 10sec. LoopB 2sec., repeatly. Could somebody write some code for me? Thanks in advance.

????
void LoopA()
????
void LoopB()

Cybernetician

#1
Nov 28, 2012, 05:09 am Last Edit: Nov 28, 2012, 12:59 pm by Cybernetician Reason: 1
EDIT: Wrong Answer tomorrow i post right one now i am late

Code: [Select]

void loop(){
while (millis() < 10000) {
LoopA();
}
while (millis() < 2000) {
LoopB();
}
}


Are you looking for this
From Idea To Invention

Nick Gammon

Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

PaulS

@Cybernetician
What is going to happen after the Arduino has been running for 10 seconds in your code?

Aqualize

Yes that one only works the first iteration. I haven't compiled this code to test (to the Arduino C++ variant have do...while... loops?).
Code: [Select]

long quitTime;
void loop () {
   quitTime = millis () + 10000;
   do {
       // Do stuff
   } while (millis () < quitTime);

   quitTime = millis () + 2000;
   do {
       // Do other stuff
   } while (millis() < quitTime);
}


Remember that it won't interrupt the execution and jump out of a loop, so to make it work you can't have too much code (execution time wise "much") in there.
Say that in the second step you have code which takes 1.5 second to run. Then it will exit the loop 3 seconds after it started.
But if you have code that only takes 10 ms to run, well you may overshoot with a few ms but that is probably okay.

Cybernetician

Quote
@Cybernetician
What is going to happen after the Arduino has been running for 10 seconds in your code?


Code: [Select]

void loop(){
while (millis() < 10000) {
LoopA();
}
while (millis() < 2000) {
LoopB();
}
}


Ooops. what a big mistake

tomorrow i post right one now i am late

From Idea To Invention

PaulS

Code: [Select]
    quitTime = millis () + 10000;
Adding unsigned longs is not a good idea in robust code.

Code: [Select]
    do {
        // Do stuff
    } while (millis () - startTime < diddleTime);

is guaranteed to work. Though I suspect that a do/while is NOT the construct you want to use. While probably is. Look up the differences.

Jimmy60

I'd go with something like this. I put it in a loop() function for clarity.

Code: [Select]

constant unsigned long firstLoopLength = 10000;
constant unsigned long secondLoopLength = 5000;

void loop(){
        // loop A
unsigned long loopStartTime = millis();
while (millis() - firstLoopLength > loopStartTime){
// do loop A stuff
}

        // loop B
loopStartTime = millis();
while (millis() - secondLoopLength > loopStartTime){
// do loop B stuff
}
}

PaulS

Code: [Select]
while (millis() - firstLoopLength > loopStartTime){
would, in my humble opinion, be better as
Code: [Select]
while (millis() - loopStartTime < firstLoopLength)
        {

Since that more naturally reflects how one would describe the while clause in English.


Jimmy60

I value your opinion and I can see what you are saying. It makes sense.

Thanks.

Cybernetician

PaulS says:
Quote

@Cybernetician
What is going to happen after the Arduino has been running for 10 seconds in your code?

Aqualize Says:
Quote

Yes that one only works the first iteration. I haven't compiled this code to test (to the Arduino C++ variant have do...while... loops?).

Code: [Select]
long quitTime;
void loop () {
    quitTime = millis () + 10000;
    do {
        // Do stuff
    } while (millis () < quitTime);

    quitTime = millis () + 2000;
    do {
        // Do other stuff
    } while (millis() < quitTime);
}

Remember that it won't interrupt the execution and jump out of a loop, so to make it work you can't have too much code (execution time wise "much") in there.
Say that in the second step you have code which takes 1.5 second to run. Then it will exit the loop 3 seconds after it started.
But if you have code that only takes 10 ms to run, well you may overshoot with a few ms but that is probably okay.


Quote


Quote
@Cybernetician
What is going to happen after the Arduino has been running for 10 seconds in your code?

Code: [Select]
void loop(){
while (millis() < 10000) {
LoopA();
}
while (millis() < 2000) {
LoopB();
}
}


Ooops. what a big mistake

tomorrow i post right one now i am late



thanks PaulS.

Need to minus time of loopA, loopB, and other statements execution time for near to perfect result.

Code: [Select]

#include "Timer.h"

Timer t;

bool lpA = true;
bool lpB = false;
int loopAEvent;
int loopBEvent;

void setup()
{
  Serial.begin(9600);
  loopAEvent = t.every(10000, loopBFlag);
}

void loop()
{
  t.update();
  if(lpA==true)
  {
    Serial.println("LOOPA");
  }
  if(lpB==true)
  {
    Serial.println("LOOPB");
  }
}

void loopBFlag()
{
  t.stop(loopAEvent);
  lpA=false;
  lpB=true;
  loopBEvent = t.every(2000, loopAFlag);
}
void loopAFlag()
{
  t.stop(loopBEvent);
  lpA=true;
  lpB=false;
  loopAEvent = t.every(10000, loopBFlag);
}
From Idea To Invention

Aqualize


Code: [Select]
    quitTime = millis () + 10000;
Adding unsigned longs is not a good idea in robust code.

Code: [Select]
    do {
        // Do stuff
    } while (millis () - startTime < diddleTime);

is guaranteed to work. Though I suspect that a do/while is NOT the construct you want to use. While probably is. Look up the differences.

I had to think about it but I understand the part about adding unsigned longs. In the corrected version millis() - startTime will never result in a wrap around because startTime can not be larger than millis() result. Except after those 50 days when result of millis() wraps around. But that is more esoteric, if the machine isn't expected to stay on for such long time.

But the part about while instead of do/while?
The difference I know is that do/while will execute at least once. My thinking was that it will save one loop condition check in this particular application, if setting the startTime (or as I had written, the quitTime) just before the loop and we want to interrupt after several seconds it till definitely don't have time to become false for that first iteration (using interrupts and having a lot of heavy code in the interrupt could cause this if the interrupts occurs exactly after the variable assignment). Also the code could be / probably would be written that the second loop expects to run after the first one, not that one time the first loop will be skipped.
Because of this reasons I thought that having the loop condition check after the first run was the most economical and effective one.
Am I wrong in my intention why to use do/while or is it some other side effect that I'm unaware of?

PaulS

Quote
Am I wrong in my intention why to use do/while or is it some other side effect that I'm unaware of?

As long as you understand the distinction, use the one that is appropriate for your situation. Personally, I've never used do/while. The time required to check the condition, even when you KNOW that the condition will be true, one extra time is only a couple hundred nanoseconds.

Nick Gammon

There are times when using do...while is highly appropriate. For example, if the thing you are testing is set up inside the loop.

On the other hand, if the thing being tested can happen zero times (eg. while (we_have_apples) eat_an_apple(); ) then you should use while on its own.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Go Up