Pages: [1]   Go Down
Author Topic: [QUESTION] How to use millis() function?  (Read 1834 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello guys!

I'm new here, but I've done a lot of research through posts and doubts, but still I couldn't understand pretty much how to use the millis() function, instead of delay().

I would like to someone answer these questions:

    Let me give an example first:

Code:
unsigned long startTime = 0;
unsigned long endTime = 0;

void setup () {

// setup pins and stuffs

}

void loop () {

//Let's say i would like to blink a led after 2000 miliseconds, without using delay ()

digitalWrite (pin, HIGH); // I know pin does not exist, but it's just an example :)
endTime += 2000;
startTime = millis ();

   if (startTime > endTime) {
   digitalWrite (pin, LOW);
   endTime = 0;
   // reset millis() ?
   }
}


I would like to understand how it works now:

1 I must refresh 'startTime' variable everytime I go on loop?
2 How to 'reset' millis () ?
3 I must declare some 'currentTime' variable in order to keep millis () working?

I appreciate if someone could help!

Thanks in advance!
Logged

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

Quote
1 I must refresh 'startTime' variable everytime I go on loop?
That depends on what startTime represents. Maybe you need to change it. Maybe you don't.

What does startTime mean to YOU?

Quote
2 How to 'reset' millis () ?
Forget it. How often do you reset your watch? Practically never, right? And yet you get places on time, most of the time, right?

Quote
3 I must declare some 'currentTime' variable in order to keep millis () working?
No. The clock works whether you look at it, or not.

That code you posted won't do anything useful.

Code:
endTime += 2000;
startTime = millis ();

   if (startTime > endTime) {
On every pass through loop, you increment endTime by 2000, and then want to know if startTime (now) is greater than endTime. On the first pass, it won't be, and the difference will never be less than on the first pass.
Logged

Queens, New York
Online Online
Faraday Member
**
Karma: 83
Posts: 3390
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Millis() starts at the exact time the program starts. It's the internal timer for the arduino, and it can not be reset manually once started. The reason its better than delay is because, delay uses a while loop and nothing can be done until the while loop is finished. But with Millis, it runs on the arduinos clock cycles, which runs in the background, so it will allow you to do other things while its running.
« Last Edit: March 13, 2013, 08:05:19 am by HazardsMind » Logged

Created Libraries:
NPV2 (NewPasswordV2),  TFT_Extension, OneWireKeypad, SerialServo.
Will provide libraries if asked in PM or forum.

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 108
Posts: 4011
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
//Let's say i would like to blink a led after 2000 miliseconds, without using delay ()
That is a very laudable ambition, but what do you mean by blink ?
Turn the LED on ?
Turn the LED off ?
Turn the LED on then off ?
Turn the LED on/off every 2 seconds ?

If you have not already done so, have a look at the BlinkWithoutDelay program in the IDE examples.  It is well commented to explain what is going on.

Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

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

Hello guys, thanks for answering that soon!

Alright, let me try to explain better.

I have a webserver running on my arduino, and I would like to make an Ajax Call to set a pin ON or OFF.

The problem is that this pin could have a 'timer'... I need it to be ON for x ms, and then OFF. (x>=0)

The code works fine with delay (), but I don't like it (it's innificient), so I decided to use millis (). (well, tried to)

Let's have another example:

Code:
void setup () {
//set pins and stuffs;
}

void loop () {

//try to get client
//get HTTP Request from client
    if (HTTP_request.indexOf("ajax_call") > -1) {
    setPin (HTTP_request);
    } else {
    // show website
    }
}

void setPin (String action) {

//a little bit of string manipulation here, i will have that:
// PIN | ACTION | TIMER // i.e:
// 22 | 1 | 4000
// So, I must set pin 22 HIGH, for 4000 ms

}


So, this is the code I want to implement, how can I use millis ()?

The millis () starts running on ARDUINO setup, or it starts on SCOPE call?

If it starts by ARDUINO setup, so I must do something like:

Code:
unsigned long currentTime;
unsigned long startTime;
unsigned long endTime;

...

void loop () {
currentTime = millis ();

     if ((currentTime - startTime) > endTime) {
     // Turn off PIN;
     }

}

Is that right? If so, I would change the setPin function... but I need to know if my thought is right!

Thanks in advice!
Logged

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

You need to read, understand, and, most importantly, embrace the technique outlined in the blink without delay example. It shows how to perform an action, and record when that action was performed.

Knowing that the action (turn an LED on) was performed, and when it was performed, you can determine if another action (turn the LED off) is required, and when that needs to happen.

Quote
// So, I must set pin 22 HIGH, for 4000 ms
No. You must set the pin HIGH. Then, in loop(), you look to see if the pin is HIGH, and, if so, if enough time has passed to require turning it off.
Logged

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

Thanks for answering!

The point is that i don't need the led to keep 'blinking', I need to turn it off after x ms.

I came up with this code, could you tell me if it's wrong or inefficient? (I don't have arduino right now for testing).

Code:
int ledPin;
unsigned long previousMillis = 0;
unsigned long interval = 0;
int check = 1; // Could use boolean also

void setup() {
   // set pins and stuffs    
}

void loop () {
  unsigned long currentMillis = millis();
 
  if (interval > 0 && check == 1) { // This because i only need to verify time if I have a TIMER
    previousMillis = currentMillis;
  } else if (interval >0) {  
        check = 0;

        if ((currentMillis - previousMillis) > interval) {
        digitalWrite(ledPin, LOW);
        interval = 0;
        check = 1;
        }
  }
  
  // Start Ethernet Connection
  if (HTTP_request.indexOf ("ajax_call") > -1) {
  setRelay (HTTP_request); // I don't really do it on my code, it's just an example
  } else {
  // send website;
  }

}

void setRelay (int pinRelay, char status, int time) {

     if (status == "1") {
         if (time > 0) { // Here I can see if the relay must stay ON for x ms
         interval = time;
         ledPin = pinRelay; // Here i could use some array to do that for more than 1 led, maybe i should create a struct... will think about it later :)
         return;
         }
         digitalWrite (pinRelay, HIGH); // Here is just a relay that doesn't have a TIMER.
     } else if (status== "0")
     digitalWrite (pinRelay, LOW); // here i don't care about timing, the relay is just going OFF.
    
}
« Last Edit: March 13, 2013, 11:42:22 am by Nickollas Aranha » Logged

Queens, New York
Online Online
Faraday Member
**
Karma: 83
Posts: 3390
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
if ((currentMillis - previousMillis) > interval) {
No, make it this,
Code:
if ((millis() - previousMillis) > interval) {
Otherwise "currentMillis - previousMillis" will always be 0, because you declaired "previousMillis = currentMillis;"

Add: actually you dont need this line anymore, "previousMillis = currentMillis;" just replace previousMillis with currentMillis in here.
Code:
if ((millis() - previousMillis) > interval) {
« Last Edit: March 13, 2013, 11:46:18 am by HazardsMind » Logged

Created Libraries:
NPV2 (NewPasswordV2),  TFT_Extension, OneWireKeypad, SerialServo.
Will provide libraries if asked in PM or forum.

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

Hi!

I disagree with your suggestion, for those reasons:

Code:
void loop () {
  unsigned long currentMillis = millis();
 
  if (interval > 0 && check == 1) { // This because i only need to verify time if I have a TIMER
    previousMillis = currentMillis;
  } else if (interval >0) { 
        check = 0;

        if ((currentMillis - previousMillis) > interval) {
        digitalWrite(ledPin, LOW);
        interval = 0;
        check = 1;
        }
  }

It means, this line
Quote
previousMillis = currentMillis;
will happen only once, because of
Quote
if (interval > 0 && check == 1)

It's like 'the first run'. After that, i call
Quote
else if (interval >0) { 
        check = 0;

Well, i can remove the 'currentMillis' and use only millis (), but I'll focus on memory later! smiley

Do you agree with me?

Thanks in advance!
Logged

Queens, New York
Online Online
Faraday Member
**
Karma: 83
Posts: 3390
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Apologies, I over looked the else statement. You do still need this,"unsigned long currentMillis = millis();" to have something the millis() can compare to.
 
Logged

Created Libraries:
NPV2 (NewPasswordV2),  TFT_Extension, OneWireKeypad, SerialServo.
Will provide libraries if asked in PM or forum.

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3347
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So when a condition occurs, you want to light the LED for a given amount of time? Simple:

Code:
if (condition occurs)
{
  turn light on
  record lightOnTime
}

if (now minus lightOnTime is greater than our interval)
{
  turn light off
}
Logged

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

@HazardsMind
No problem mate, I appreciate your help!

@Arrch
I think my last code is doing it now, I will test it when I get home.

If someone thinks it won't work, please leave a comment!

Thanks!
Logged

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3347
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@Arrch
I think my last code is doing it now

Maybe, but it's doing it with more code than necessary.
Logged

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

Guys, hello!

Just wanted to thank you all for helping, this is working now!

I will sure have more doubts, so, keep waiting for me!

Thanks!
Logged

Pages: [1]   Go Up
Jump to: