Pages: 1 [2] 3   Go Down
Author Topic: Millis() Timing goes way off over time.  (Read 1389 times)
0 Members and 1 Guest are viewing this topic.
Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49092
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What if i need to delay for longer than 1-5 minutes at a time? doesn't delay stops my code, for the certain amount of time? within that 1-5 minutes of delay(), i could be turning on a bunch of relays.

unless I am confused about the delay().
Yes, delay() stops your code for the specified duration. But, so does your code.

The thing you need to do it to get rid of the while loop(s). I'd recommend getting rid of the Zone function, too. Move the code into loop(). On each pass through loop, you check to see if it is time to turn a pin on, or not. You check to see if it is time to turn a pin off, or not. If it is time, turn the pin on, or off, and note the time that you did that. This becomes the basis for deciding exactly when to do the next thing.

If you were running around the yard turning sprinklers on and off, you wouldn't stand next to a valve for the whole time it is not, staring at your watch to see if it had been on long enough,. You'd turn on the ones that needed to be on (you should have an array of them), and then go sit in the sun and drink beer until it is time to turn them off (at least, that's what I'd do). Not all of them need to be turned on or off at the same time, so you have to check your watch periodically, so that you turn them off at about the right time. But, while the sprinklers are running, you can sit back and drink beer and enjoy the sun, or watch TV, or work on the honey-do list.

With just 4 sprinklers, you wouldn't need a piece of paper to write down the times, but, if you were managing a golf course with 1000 zones, you probably would.

Millis is the function that replaces your watch. The variables, or arrays, replace the paper. Nothing replaces the thinking that needs to occur, but the Arduino can easily decide if enough time has passed to turn a zone on or off, AND it won't drink all your beer while you are playing with the sprinklers.
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

SimpleTimer is not a function, but a class.

Variable intervals... interesting question. I tried a solution with this example.

Code:
#include <SimpleTimer.h>

const short ledPin = 13;

// the timer object
SimpleTimer timer;

void printUptime() {
    Serial.print("Uptime (s): ");
    Serial.println(millis() / 1000);
}

void blinkLed() {
    static boolean ledOn = true;

    if (ledOn) {
        digitalWrite(ledPin, HIGH);
        timer.setTimeout(50, blinkLed);
        //Serial.println(millis());
    }
    else {
        digitalWrite(ledPin, LOW);
        timer.setTimeout(1500, blinkLed);
        //Serial.println(millis());
    }
   
    ledOn = !ledOn;
}

void setup() {
    Serial.begin(9600);
    timer.setInterval(5000, printUptime);
    timer.setTimeout(500, blinkLed);
}

void loop() {
    timer.run();
}
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4803
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've been away from serious C++ for too long, what happens when you pass an unsigned long to unsigned long []?

Code:
void loop(){
  Zone(5000UL,3600000UL,0,previousMillis);
}

void Zone(unsigned long on, unsigned long off, int i, unsigned long previousMilis[]){
  currentMillis[i] = millis();
  if (currentMillis[i] - previousMillis[i]> off){
    previousMillis[i]=currentMillis[i];
    while(millis()-previousMillis[i]<=on){
      digitalWrite(relayPin[i],HIGH);
    }
    digitalWrite(relayPin[i],LOW);
  }
}

and does it matter if you don't actually use it in the function?


Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49092
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I've been away from serious C++ for too long, what happens when you pass an unsigned long to unsigned long []?
The previousMillis variable is an array. The call is correct.

Quote
and does it matter if you don't actually use it in the function?
It's referenced twice in the function.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4803
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Okay so he did pass an address to something that expects an address, like I wrote; it has been too long.
Still nowhere in the function is previousMilis[] used.

Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49092
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Still nowhere in the function is previousMilis[] used.
void Zone(unsigned long on, unsigned long off, int i, unsigned long previousMilis[]){
  currentMillis[ i ] = millis();
  if (currentMillis[ i ] - previousMillis[ i ]> off){
    previousMillis[ i ]=currentMillis[ i ];
    while(millis()-previousMillis[ i ]<=on){
      digitalWrite(relayPin[ i ],HIGH);
    }
    digitalWrite(relayPin[ i ],LOW);
  }
}
Looks like it's used to me...

No code box because you can't highlight in a code box, like you used to be able to do.
« Last Edit: March 02, 2012, 08:28:24 pm by PaulS » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 481
Posts: 18737
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Interesting though all this is ...

If I may suggest to the OP:

http://gammon.com.au/blink

I don't think turning on timers to water plants is rocket science. You should be able to make it work quite easily.

Looking at the code above:

Quote
Code:
while(millis()-previousMillis[ i ]<=on){
      digitalWrite(relayPin[ i ],HIGH);
    }

You don't need to keep turning the pin on. Once it's on, it's on. You could make it:

Code:
digitalWrite(relayPin[ i ],HIGH);  // turn on pin
while(millis()-previousMillis[ i ]<=on)  // my delay technique
 {   }

or just:

Code:
digitalWrite(relayPin[ i ],HIGH);  // turn on pin
delay (on);

However this, fairly obviously, only lets you water one lot of plants at once. Does it matter? I doubt the plants will care.
Logged


Gosport, UK
Offline Offline
Faraday Member
**
Karma: 21
Posts: 3113
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Might also be worth looking at the recent blink series of threads by Morris Dovey.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4803
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Paul;

previousMilis

is not

previousMillis

How many times have you seen just 1 character make all the difference? If I had a dollar for every time.....
« Last Edit: March 03, 2012, 05:53:27 am by GoForSmoke » Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49092
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
previousMilis

is not

previousMillis
Until you mentioned that, I was reading this thread with the font size at a reasonable level. With old(er) eyes, the two l's looked just like 1. I had to increase the font size significantly to see that there were indeed two l's in the name used, versus one in the argument.

Sorry about that...
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4803
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have View Zoomed to 120% and still it's not always apparent at first glance.
The first PC's I programmed for money on had 9" blazing white on black screens, my 19" flat panel is soooo nice!
 
In any any case, it doesn't matter because the call and args do match even if most of it is bull teats.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Okay guys!!!

I have listened to everyone who has replied, and removed the while loop  and i've rewritten it to this:
I hope it will be understandable.

Code:
/* Cosinepi
aeroTimer
*/

unsigned char relayPin[4] = {13,5,6,7}; // Define the led's pin

void Zone(unsigned long on, unsigned long off, int i);

int mode[4]={LOW,LOW,LOW,LOW};
unsigned long previousMillis[4]={0,0,0,0};
unsigned long Sec = 1000L;
unsigned long Min= 60*1000L;
unsigned long Hour=60*Min;
unsigned long currentMillis[4]={0,0,0,0};

void setup()
{
  int i;
  for(i = 0; i < 4; i++)
  {
    pinMode(relayPin[i],OUTPUT);
    digitalWrite(relayPin[i],mode[i]);
  }
}

void loop(){
  Zone(3000UL,8000UL,0);
  Zone(5000UL,1800000UL,1);
  Zone(10000UL,3600000UL,2);
}

void Zone(unsigned long on, unsigned long off, int i){
  currentMillis[i] = millis();
  if (currentMillis[i] - previousMillis[i]>= off && mode[i]==LOW){
    previousMillis[i]=currentMillis[i];
    mode[i]=HIGH;
      digitalWrite(relayPin[i],mode[i]);
  }
  if (currentMillis[i]-previousMillis[i]>= on && mode[i] == HIGH){
    previousMillis[i]=currentMillis[i];
    mode[i]=LOW;
      digitalWrite(relayPin[i],mode[i]);
  }
}

What do you guys think? it is better and more efficient? are there things I should improve?

I am going to make another module to monitor my PH, EC, humidity and TEMP of the rooms and water nutrients. I will need your help soon, so thank you guys in advance!
Logged

New Jersey
Offline Offline
Faraday Member
**
Karma: 67
Posts: 3679
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks good. One minor thing - there is no need to have a CurrentMillis array, you can have a single local variable in Zone or indeed, just use millis directly.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just something to look out for ... What will happen when Millis() overflows --- won't you be waiting another 36 hours or so for previousmillis to catch-up ????

Maybe I am wrong ... has happened before ;-)

Logged

New Jersey
Offline Offline
Faraday Member
**
Karma: 67
Posts: 3679
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Maybe I am wrong ... has happened before ;-)

I'm afraid it's happened again  smiley-wink

That subtractive pattern works fine even when millis overflows.

For more detail check johnwasser's analysis in this thread: http://arduino.cc/forum/index.php/topic,60215.0.html.
« Last Edit: March 04, 2012, 08:16:00 am by wildbill » Logged

Pages: 1 [2] 3   Go Up
Jump to: