how to hold pin state for two hours in microcontroller

Thread Starter

mah

Joined Mar 15, 2010
393
the problem is i want to set and reset it every 2 hours and every state hold its value for 2 hours
for example

Code:
if( hour=1&minute=59)/// this will set it every 2 hours but it will reset after 1 minute when the condition is false.
{
set
}
else 
{ 
reset /// for two hours
}
 

djsfantasi

Joined Apr 11, 2010
9,163
Use the millis() function.

C:
const unsigned long twoHours = 720000;
unsigned long endTime = 0;
endTime = millis()+twoHours;
...
if (millis()>endTime) 
{
// set
endTime = millis()+twoHours;
}
else
{
// reset
}
How long will the sketch run? Is this a 24 hour application? The millisecond timer “rolls over” once a day and the code will have to adjust for that. I’ll leave that as an exercise. Make sure you understand this first.
 

mvas

Joined Jun 19, 2017
539
I think, the TS wants to Toggle the Output Pin, once every two hours ...

C:
const unsigned long TwoHours = 7200000;
unsigned long StartTime = 0;
...
// SETUP section
// Capture the Start Time, needed for the next Toggle Event
StartTime = millis();
...
// LOOP section
// Time for the next Toggle Event ?
if ( millis() - StartTime > TwoHours ) 
{
// Capture the Start Time, needed for the next Toggle Event
StartTime = millis();

< Add code here to Toggle the State of the Output Pin >

}
The above code does not have any issue when the millis() function "rolls over".
The millis() function, will roll-over once every ~49.7 days, not once per day.
The Delay should be 7,200,000 = 2 hours x 60 minutes x 60 seconds x 1,000 milliseconds, not 720,000
 
Last edited:

djsfantasi

Joined Apr 11, 2010
9,163
I think, the TS wants to Toggle the Output Pin, once every two hours ...

C:
const unsigned long TwoHours = 7200000;
unsigned long StartTime = 0;
...
// SETUP section
// Capture the Start Time, needed for the next Toggle Event
StartTime = millis();
...
// LOOP section
// Time for the next Toggle Event ?
if ( millis() - StartTime > TwoHours )
{
// Capture the Start Time, needed for the next Toggle Event
StartTime = millis();

< Add code here to Toggle the State of the Output Pin >

}
The above code does not have any issue when the millis() rolls over.

And I think, millis() will roll-over once every ~49.7 days, not once per day.
@mvas

Deleted this post because I was just d*** wrong. I must have been tired, because I misread almost everything.

Thanks for your replies!
 
Last edited:

mvas

Joined Jun 19, 2017
539
Logically that’s the exact same code as mine. And you’re probably right about the rollover. It’s probably more like days, not hours.

First, my code DOES toggle the pin every two hours.

And your code still suffers from rollover. Let’s assume roll over occurs at 49.7 days. And currently, millis() returns a value within 2 hours of the rollover time.
  • You set StartTime to that value (a big unsigned long value).
  • Rollover occurs
  • You check the value of (millis()-StartTime). Note that value is a signed long integer and is a negative number. The test will not be satisfied
  • Any negative number will be less than TwoHours. And the test will not go positive until millis() is within two hours of rollover.

The test will never again be satisfied, because less than two hours will elapse before rollover occurs (again) and the entire sequence will repeat.
The developers at Arduino say you are wrong.
Per Arduino ... the millis() function returns an unsigned long value, not a signed long value ( read your Arduino Language Reference Guide )
Per Arduino ... My code will not fail during a roll-over, like your code does ( I used the code recommended by the Arduino Developers )
Per Arduino ... My code will delay for 2 hours even during a "roll-over", your code will not.

Logically, my code is not the same as your code

Actually, your code appears to ...
a) Continuously RESET the Output Bit for the next 12 Minutes
b) Then SET the I/O Bit for just one Pass ( microseconds? )
c) Then Continuously RESET the Output Bit for the next 12 Minutes
d) Then SET the I/O Bit for just one Pass ( microseconds? )
repeat steps a - d ...
You code uses the wrong delay of 12 minutes
Your code does not turn the Output Bit ON for 2 Hours and then OFF for 2 Hours ( ie Toggle once every 2 Hours )
Your code uses delay logic that is "not recommended" because it has the roll-over issue
Your code is very inefficient - it wastes a huge amount of CPU time executing redundant I/O

My code actually "Toggles" the Output Pin once every 2 Hours
My code uses the correct delay of 2 Hours ON and 2 Hours OFF
My code uses the "Arduino Developer Approved" delay logic that avoids the "roll-over" issue
My code is very efficient & highly optimized code because it executes the slow I/O code only once every 2 Hours

The Arduino I/O routines are very slow.
There is no reason to waste CPU Cycles by continuously SETTING an Output Bit for 2 hours
There is no reason to waste CPU Cycles by continuously RESETTING an Output Bit for 2 hours
It is best to Toggle the Output Bit only once every 2 Hours
 

turboscrew

Joined Dec 7, 2018
16
Are you looking for something like this?
This is for clock that wraps around every hour, but the idea works for other periods too.

Code:
uint32_t time_diff(uint32_t now, uint32_t earlier)
{
    int tmp = now - earlier;
    if (tmp < 0)
    {
        tmp = MS_PER_HOUR - (earlier - now); /* modulo hour */
    }
    return (uint32_t) tmp;
}
If your clock is just a 32-bit counter then:
Code:
uint32_t time_diff(uint32_t now, uint32_t before)
{
        /* 0x100000000 is split to 0xFFFFFFFF + 1 */
        if (before > now) return (0xFFFFFFFF - before) + now + 1;
        else return now - before;
}
 
Last edited:
Top