Go Down

Topic: Blinking without delay (Read 2165 times) previous topic - next topic

psppb

Hello all,

I am having  trouble with a timer. I need to energize a Mosfet for a time period (Interval * 1000) milliseconds. I have the interval stored in memory. I am looking at the "Blink without delay" example but I need something where I can push a button, it will count to a specified number while the controller is running in the background and when the timer is up switch off. The problem I had with the "Blink W/O delay" code is that it runs on an even count where   depending on a count of 1 thousand it is either on or off. my timer is activated by an if then statement.

I need to set millis() to zero and subtract current millis() from the (interval * 1000) and once it equals zero ta-dah! I do not know how to set millis() to zero however

Thank you

Bill

AWOL

The key thing to take away from the blink without delay is that it works on time differences; there is never any need to reset millis().
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

James C4S

The problem I had with the "Blink W/O delay" code is that it runs on an even count where depending on a count of 1 thousand it is either on or off. my timer is activated by an if then statement.

That's how you use millis(), it isn't a "problem."

I do not know how to set millis() to zero however

You don't.  Instead you track how much millis() has changed since the last time you check it.  That's how you use it.
Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

psppb

Here is what I have so far.  "interval" integer from 1 to 12. If the time is right it needs to bring a certain pin high for a give amount of time. I am taking a snapshot of millis() giving it a number, adding it to the interval and comparing it to the current millis. It's not working. Any suggestions? Thanks!


Code: [Select]
if(((now.hour() == Breakfast) && (now.minute() == 0) && (now.second() == 0)) || ((now.hour() == Dinner) && (now.minute() == 0)  && (now.second() == 0))) { 
   
   unsigned long AutoMillis = millis();
 
   while(AutoMillis + (interval * OzMenu) < millis ) {
     if(automatic == true){ // Need t o add feedback
     digitalWrite(motorpin, HIGH);
     }
   }
     previousMillis = currentMillis;   
  //Feed the dog by rotating motor
}




AWOL

Code: [Select]
while(AutoMillis + (interval * OzMenu) < millis ) {
millis is a function pointer, and hence a constant.
It doesn't make sense to compare it against an arithmetic expression.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

PaulS

Quote
It's not working. Any suggestions?

Yes. Explain what "it's not working" means. What does that snippet do that you don't want? What does it not do that you do want?

Where are Breakfast and Dinner defined? Where are they valued? Where are previousMillis and currentMillis defined? How are they defined? Where are they valued?

When posting code, it's much better to post all of your code than to post the section where you think the error is.

psppb

Breakfast and dinner are integers. They are from 1 to 23 in terms of hours.

Basically the think never turns off. Even past it's time.  Hypothetically lets say that millis() was 10,000. My interval was 8, multiplied by 1000 that gives 8000. So when millis() = 10,000 the output pin is high I add 10,000 to 8,000 (The duration) and then try to compare it the absolute up to date value of millis(). When the absolute value of millis() does in fact equal to 18,000 the output pin goes low.

I cannot figure out how to capture the current value of millis() to compare it to the value at which it should shout off.

Thanks for the replies I really appreciate it :)

Bill

AWOL

Quote
I cannot figure out how to capture the current value of millis() to compare it to the value at which it should shout off.

Try calling it.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

psppb

How would I go about calling it and not resetting the previous bookmark I took for millis()?
I'm really confused.

AWOL

You need to call it here:
Code: [Select]
while(AutoMillis + (interval * OzMenu) < millis ) {

thus
Code: [Select]
while(AutoMillis + (interval * OzMenu) < millis () ) {
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

floresta

Quote
to compare it to the value at which it should shout off.
You don't want to turn something off 'at' any value because if you happen to miss that value it will never turn off.  You want to turn off when 'equal to or greater' than the value (or perhaps 'equal to or less' than the value, depending on your logic).

Don

psppb

Here is the latest. The code compiles, the integers are all declared. If I comment out all the timing elements it works. I just cannot shut it off. however when I re-insert the code dealing with the timing aspect. Poof! it does not work.
Code: [Select]
else if((MiscMenu == 5) &&(buttonstate == LOW) && (TopMenuSelect == 0) ){
        if(automatic == false){
          unsigned long AutoMillis = millis();
          while(AutoMillis + (1 * OzMenu) < millis()) {
             if(automatic == false){ // Need t o add feedback
             digitalWrite(motorpin, HIGH);
             }//close actual feed
          }//close while
        }//close if automatic = true
        }//Close Else if statement


AWOL

Posting code snippets is just wasting time.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

markB

psppb

I think the responders are suggesting the following.
Use a long variable.
When you energise the Mosfet, make this variable = millis()
check that the variable is greater or equal (>=) to millis() + delay *1000
Either move on, or turn off the mosfet.

I have snipped some of mine that does basically the same, although in mine the heat gets turned off, and the pump runs for 5 secs.
I also set another variable as to what state the pump and heater are in.
You could also set your mosfet state (or read the pin) to know if you should be turning it off.

Code: [Select]


void HeatOff()
{
    // Heat is OFF without delay, BUT we set the ControlChangeTimer.
   
    digitalWrite(HeatOut, LOW);              // Turn Off the HeatOut pin
    HeatState = false;
    ControlChangeTime = millis();
    Serial.print(millis(),DEC);
    Serial.print("   Heat is Off\n");
}

void PumpOff()
{
  // Pump is not OFF until after the delay period, which allows water to circulate.

    if (millis() >= (ControlChangeTime + (PumpDelay *1000)))  // PumpDelay stored as secs
    { 
      digitalWrite(PumpOut, LOW);              // Turn Off the PumpOut pin
      PumpState = false;
      ControlChangeTime = millis();
      Serial.print(millis(),DEC);
      Serial.print("   Pump is Off\n");
    }
}


Coding Badly

Use an unsigned long variable.


Quote
check that the variable is greater or equal (>=) to millis() + delay *1000


Fails when millis wraps.  The trick to doing it correctly is to use subtraction.

Quote
void PumpOff()
{
  // Pump is not OFF until after the delay period, which allows water to circulate.

    if ( (ControlChangeTime - millis()) >= (PumpDelay *1000) )  // PumpDelay stored as secs

Go Up