Set pin HIGH for x millis

Hello. I am trying to have a digital pin set to HIGH for a set amount of milliseconds using the millis function.

if(vanntid > 0)
{
digitalWrite(waterPump, HIGH);
}

if(vanntid <= 0)
{
digitalWrite(waterPump, LOW);
}

I have a variable named “vanntid”, I set that variable over serial. So I need a function like.

unsigned long currentMillis = millis();
vanntid = vanntid - currentMillis;

So if I set the “vanntid” to 20 000 ms, it starts to count down til it reaches 0, and then set the waterPump to LOW…

Any suggestions?

What do you think would work?

Let’s say the chip has been running for 30 seconds (30000 mS).

So every time you check and do this:

vanntid = vanntid - currentMillis;

Then vantid is going to be 20000 - 30000 … except it is unsigned so it can’t go negative. Do you see any flaws here?

Hello and thanks for answering. Yes.. I see the problem. But cant the millis start counting while the pin is set high? And keep counting while its high?

Absolutely it can. And you are on the right track. :)

Maybe post your whole code rather than snippets. You learn more by attempting than just having someone post a result. You learn even by getting it wrong. Because then you learn what doesn't work. ;)

I completly agree… :slight_smile:

Here is my code:

#include <DateTime.h>
#include <math.h>
double Thermister(int RawADC) {
double Temp;
Temp = log(((10240000/RawADC) - 10000));
Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
Temp = Temp - 273.15;            // Convert Kelvin to Celcius
return Temp;
}

int tempSensor = 2;
int moistureSensor = 1;


int tempLed = 3;
int waterPump = 7;



int temp_val;
int moisture_val;

int lowtemp;
int lowtemp_tens;
int lowtemp_ones;

int hightemp;
int hightemp_tens;
int hightemp_ones;

long vanntid;


int vanntid_tens;
int vanntid_ones;

void setup() {

Serial.begin(9600);

pinMode (waterPump, OUTPUT);
pinMode (tempLed, OUTPUT);
digitalWrite (waterPump, LOW);
digitalWrite (tempLed, LOW);


}
void loop() {

 if(Serial.available() >2 ){  // wait for 3 characters to come in
    switch (byte(Serial.read())){

    case 'l':
      lowtemp_tens = Serial.read() - 0x30;  // convert from ascii to decimal, see asciitable.com
      lowtemp_ones = Serial.read() - 0x30;

lowtemp = lowtemp_tens *10 + lowtemp_ones;

      break;
      
    case 'h':
      hightemp_tens = Serial.read() - 0x30;
      hightemp_ones = Serial.read() - 0x30;

hightemp = hightemp_tens*10 + hightemp_ones;
      break;
      
    case 'v':
      vanntid_tens = Serial.read() - 0x30;
      vanntid_ones = Serial.read() - 0x30;
   

vanntid = (vanntid_tens*10 + vanntid_ones)*1000;
    }
  }

moisture_val = analogRead(moistureSensor);

Serial.print( moisture_val );
Serial.print(":");
Serial.print( int(Thermister(analogRead(2))) );
Serial.print(":");
Serial.print( lowtemp, DEC );
Serial.print(":");
Serial.print( hightemp, DEC );
Serial.print(":");
Serial.print( vanntid, DEC );
Serial.println("|");


if(vanntid > 0)
{
digitalWrite(waterPump, HIGH);
unsigned long currentMillis = millis();
vanntid = vanntid - currentMillis;
}

if(vanntid <= 0)
{
digitalWrite(waterPump, LOW);
}

if (int(Thermister(analogRead(2))) <= lowtemp)
{
digitalWrite(tempLed, HIGH);
}

if (int(Thermister(analogRead(2))) >= hightemp)
{
digitalWrite(tempLed, LOW);
}

}

But when I run this, and set the vanntid to 22 000 . it just returns to -2508 strait away…

millis tells you how long the arduino has been running. It's increasing all the time, so while you're entering low temp and high temp and vanntid, the clock is ticking. In your example, it looks like it took you ~24 seconds to get to the point where vanntid was set. A way to help think about this that's used here often: if you were doing this yourself using a watch, how would you do it?

if currentMillis >= vanntid......

I haven't futzed with timers and interrupts yet but there should be a way to 'set the alarm clock' so to speak.

No need for interrupts or timers - just store millis in an unsigned long variable when you set vanntid. When millis - TimeISaved > vanntid, time's up.

With timer and interrupt I think that you can shut the CPU down for those 15 seconds or do something else besides sit and watch.

I don't understand what you are doing here:

if(vanntid > 0)
{
digitalWrite(waterPump, HIGH);
unsigned long currentMillis = millis();
vanntid = vanntid - currentMillis;
}

For a start, this is the same as:

if(vanntid > 0)
{
digitalWrite(waterPump, HIGH);
vanntid = vanntid - millis();
}

Can you just explain why you are doing that?

Let's try to describe it, as if you are using a clock.

Say you are told to turn the heater on for two hours. So vantid is 2.

Now what this code is doing is saying, "I wonder what the time is? Ah, it's 10 am". Right, I'll subtract 10 from 2.

2 - 10 = -8

Right, so I need to turn the heater on for -8 hours! Why? Why subtract the current time from the time you want? And if it is 6 am you get:

2 - 6 = -4

The numbers are meaningless. There is no point to doing that.

Short of resetting the board, is there any way to zero millis/micros?

Why do you want to?

That like saying you can’t cook a 3 minute-egg unless you can reset the time to midnight. It isn’t necessary.

It would just be a way to use leaner, faster code in some or many cases is all. Nobody would -have- to do it!

millis() only rolls over about every 50 days. Let's check for that maybe 1000+ times a second, it's better that way.

Ok. I get it. I thought millis was like a stopwatch… that it didnt start before I called on it.

I got it now, by doing…

    case 'v':
      vanntid_tens = Serial.read() - 0x30;
      vanntid_ones = Serial.read() - 0x30;
   

vanntid = ((vanntid_tens*10 + vanntid_ones)*1000) + millis();

and then I …

if(vanntid > millis())
{
digitalWrite(waterPump, HIGH);
}
else
{
digitalWrite(waterPump, LOW);
}

Thanks for all the replys and help.

GoForSmoke: millis() only rolls over about every 50 days. Let's check for that maybe 1000+ times a second, it's better that way.

It doesn't matter that it rolls over. You don't have to check for it, ever.

Right. I could save millis and call that L8R then add 15000 to that. Then in a loop check if millis = L8R. But if I missed the 1 millisecond window to check when they actually are equal it will turn into a long, long wait.

You just save the current time, and check for >= the interval, like this:

unsigned long start_time = millis ();  // when we start 

...

// later we check if time is up
if (millis () - start_time >= 15000)
  {

  // time is up
  }

This code always works. It works if millis () wraps around, and it doesn’t matter if you miss the exact moment.

      vanntid_tens = Serial.read() - 0x30;

would be a lot easier to understand as

      vanntid_tens = Serial.read() - '0';

So that's because of unsigned numbers then Nick? I knew I missed something.

Yes it is. It's like magic. :)

Try it with some example numbers and you'll see.