Pages: 1 [2]   Go Down
Author Topic: Very confused about timing.  (Read 3305 times)
0 Members and 1 Guest are viewing this topic.
Fort Lauderdale, FL
Offline Offline
Faraday Member
**
Karma: 71
Posts: 6144
Baldengineer
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Aimed at how to simulate multitasking with millis(), but provides an extended explanation on how it works:

http://www.cmiyc.com/blog/2011/01/06/millis-tutorial/

millis() will work in this application, but you would be able to write much simpler code if you wired up a RTC (such as the ds1307).
Logged

Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.c

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 208
Posts: 12939
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Aimed at how to simulate multitasking with millis(), but provides an extended explanation on how it works:
http://www.cmiyc.com/blog/2011/01/06/millis-tutorial/
The code does not work correctly as millis approaches the wrap-around.
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 538
Posts: 27144
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Something basic like this would work, flesh out the definitions, pin assignments, other stuff.
Basically, you push the start button at 8:30.
It reads the current value of millis, then sits in a loop reading millis and comparing to the initial read until 8.5 hrs have gone by for interval1.
It then sets some flags and sits in the loop again until 15.5 hrs have gone by for interval2.
Then it repeats.

Code:
unsigned long  currentmillis = 0; // value from 0 to 4294967295 (hex FFFF FFFF, a 32 bit number)
unsigned long  elapsedmillis = 0;
unsigned long previousmillis = 0;
//unsigned long interval1 = 3060000; // = 8.5hrs x 60 min/hr * 60 sec/min * 1000ms/sec
//unsigned long interval2 = 55800000; // = (24-8.5)hrs x 60 min/hr * 60 sec/min * 1000ms/sec
unsigned long interval1 = 5000;  // for testing, replace with above
unsigned long interval2 = 5000; // for testing, replace with above

byte interval1_active = 0; // flag =1 to show interval1 in process
byte interval2_active = 0; // flag =1 to show interval2 in process
byte start_button = 2; // pin2 for start button
byte start_button_state = 1; // state of the active low (connect to ground) button

void setup(){
  Serial.begin (9600);
  pinMode (start_button, INPUT);
  digitalWrite (start_button, HIGH);  // internal pullup turned on
}
void loop()
{
  start_button_state = digitalRead (start_button);  // read the active low (internal pullup) start button
  if (start_button_state == 0 && interval1_active == 0) // uses interval1 to ignore switch bounce once pushed
  {  // once pressed,
    Serial.println ("Started!"); // let the user know
    interval1_active = 1; // and set a flag for interval1
    currentmillis = millis();  // take a snapshot of current time
    previousmillis = currentmillis; // sets difference to 0
  }
  if (interval1_active == 0 && interval2_active == 0)  // nothing going on yet
  {
    Serial.println ("Waiting for 8:30"); //  let user know waiting for start time
    delay (1000);  // but not too often
  }

  if (interval1_active == 1 && interval2_active == 0){
    currentmillis = millis();  // read the time.
    elapsedmillis = currentmillis - previousmillis; // compute how much has gone by

    if (elapsedmillis >= interval1) // 8.5 hrs have gone by
    {
      Serial.println ("8.5 hrs elapsed");
      interval1_active = 0;  // turn off 1st flag
      interval2_active = 1; // turn on 2nd
      previousmillis = currentmillis; // reset the difference to 0
      elapsedmillis = 0;
    }
  }


  if (interval1_active == 0 & interval2_active == 1){
    currentmillis = millis();  // read the time.
    elapsedmillis = currentmillis - previousmillis; // compute how much has gone by

    if (elapsedmillis >= interval2) // (24-8.5) hrs have gone by
    {
      Serial.println ("15.5 hrs elapsed");
      interval1_active = 1;
      interval2_active = 0;
      previousmillis = currentmillis;
      elapsedmillis = 0;
    }
  }

} // end void looop

Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Colorado
Offline Offline
Full Member
***
Karma: 2
Posts: 220
Arduino 0022 and Ubuntu 11.10 64bit.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Take a look at the Time library.  I am looking at a led display matrix. it syncs the time once a week via a ntp server.  Seems to keep to good time with or without the sync.
Logged

Right Here!
Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well here's another fairly clean cut example. Might help.
Code:
#define ONEMINUTE 60000

unsigned long lastminute;
int minutes = 0; // either set these to starting values
int hours = 0; // or switch on at midnight!
bool running = false;

void setup(){
  // whatever else you want here
  lastminute = millis(); // should be last command in setup
}

void loop{
  if (millis() - lastminute >= ONEMINUTE){
    lastminute += ONEMINUTE;
    minutes += 1;
    if (minutes == 60){
      minutes = 0;
      hours += 1;
      if (hours == 24){
        hours == 0;
      }
    }
  }
  if (not running and hours == 8 and minutes == 30){ // just examples
    running = true;
  }
  else if (running and hours == 17 and minutes == 0){
    running = false;
  }
  if (running){
  // some function here
  }
// some other code here too
}

This will correctly handle millis()  wrap around zero and also step over any other code functions provided the overall loop time is less than 1 minute!
« Last Edit: January 18, 2011, 07:54:58 pm by zaphil » Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 538
Posts: 27144
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

As long as the variables dealing with millis() are unsiged long, there is no wraparound problem.
Try some examples, convince yourself.
FFFF FFE0 - 0000 0010 correct yields 0000 0030



Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Right Here!
Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Only if you do a subtractive comparison. Do a direct foo > bar and the wraparound gives a false result.
Logged

Pages: 1 [2]   Go Up
Jump to: