Hi,
I am using a UNO to read the voltage output of several sensors ( solar panels );
4 in total. I believe I can code for that, but I'm having trouble with the delay function.
I want to read all 4 values, record them, then do it again at intervals over an entire day.
I reckon a reading every 5 minutes would be good enough. How do you code for a 5 minute delay?
I'm assuming you write :delay (1000) or somesuch, over and over in a loop. This seems messy,
and I understand the chip cant do anything else while a delay is on. For this trivial application
this isnt important, but I'm guessing there's a better way when you want to do other stuff simultaneously.
Or do you simply use an ATTINY dedicated just to that one job?
You're quite right, you could do this with a delay, which takes a value in milliseconds, therefore 5mins would be 1000 * 60 * 5 = 300,000.
Another/better method is to use the way outlined in the BlinkWithoutDelay example ( under Digital, the 2nd group in the examples folder in the IDE). Have a read of that, it's pretty well commented.
Essentially the loop keeps going, which allows you to do other things and periodically your sketch checks to see whether the interval has passed, at which point actions are taken (for you, readings, or for the example, toggling an LED).
As you say there's probably no downside to using the delay(300,000); to get you your interval...however a blinking activity LED in between as some hint of life probably isn't a bad thing.
The compiler would accept the comma, but it wouldn't work the way you expect.
[/quote]Good catch Nick. The comma was just my auto-punctuationTM...it shouldn't be there of course.
OK guys.
First: the reason I didnt look at the millis() function is a syntax error
and I dont mean code syntax; I mean the syntax of English!
The title is 'Blink without delay'. This actually means blink without using "delay()",
but I took it to mean there wasnt going to be any delay, so wasnt any use to me! Ho, ho!
Second: Nick, what is the UL in delay(300000UL)?
Third: I certainly didnt find the 'Blink without delay' explanation easy to follow; au contraire,
it baffled me and still does! I dont doubt it works fine; it's my head that doesnt work OK.
For the moment it doesnt matter since I can get along OK by using 'delay()'.
poriet:
OK guys.
First: The title is 'Blink without delay'. This actually means blink without using "delay()",
but I took it to mean there wasnt going to be any delay, so wasnt any use to me! Ho, ho!
Or, blink right now?
poriet:
Second: Nick, what is the UL in delay(300000UL)?
This is shorthand for the compiler to interpret the number as a value of type Unsigned Long, a type large enough to accommodate that value.
poriet:
Third: I certainly didnt find the 'Blink without delay' explanation easy to follow; au contraire,
it baffled me and still does! I dont doubt it works fine; it's my head that doesnt work OK.
Have a bit of a play with the interval, maybe add some Serial.prints to see what it's doing with the different values and you may find that helps further. The millis() function returns the number of milliseconds since the Arduino was last reset, and essentially you're using that to see if an interval has passed yet since the last time you did something. When it has, you do the thing, and store the present value of millis() so the next loops through you're now comparing the current millis() value versus the last time you (in this case, changed the state of an LED) did something.
Anyway, if you're good with delay for now it's always something you can update your sketch to use later on when you're more comfortable with it.
Thanks Geoff,
I understand the idea of the millis() function. What I couldnt grasp was
the loop later on which was 2 'if' statements.
As you say, I'm OK for now and I'll deal with Mr. Millis later.
Basically what you would do using millis() would be something like this -
unsigned long NextVoltCheck;
Startup(){
...
NextVoltCheck = mmillis(); // just gets thing primed...
...
}
loop() {
unsigned long CurrentTime;
...
CurrentTime= millis();
if (CurrentTime > NextVoltCheck) { // first time through the voltages will all be read, after that ...
NextVoltCheck = millis() + 300000UL; // by adding 300000UL to millis() you get a 5 min. delay.
... // whatever other code you want to run, or call a function to make your readings
}
}
I code a little different than Blinkwitoutdelay, but achieve the same result.
loop() {
unsigned long CurrentTime;
...
CurrentTime= millis();
if (CurrentTime > NextVoltCheck) { // first time through the voltages will all be read, after that ...
NextVoltCheck = millis() + 300000UL; // by adding 300000UL to millis() you get a 5 min. delay.
... // whatever other code you want to run, or call a function to make your readings
}
}
I code a little different than Blinkwitoutdelay, but achieve the same result.
The reason the example is different is because your code won't work when millis rolls over (after 50 days). That's an even bigger problem if you use micros with the same technique, since it'll take 34 minutesish. The example will accommodate rollovers.
if (CurrentTime > NextVoltCheck) { // first time through the voltages will all be read, after that ...
NextVoltCheck = millis() + 300000UL;
This works well unless you happen to hit the biggest possible number with NextVoltCheck, or your loop takes longer than a millisecond.
Agreed, a very very rare case, and it's critical once every couple of weeks only.
Rather use the preferred method:
const unsigned long INTERVAL = 5 * 60 * 1000L; // 5 minutes, notice the L indicator, required when all numbers fit into default int arithmetics
unsigned long LastVoltCheck = (unsigned long) -INTERVAL; // first time through the voltages will all be read, after that ...
...
if ( (CurrentTime - LastVoltCheck) >= INTERVAL) {
LastVoltCheck = CurrentTime;
This will work forever, eh.. until a power outage.
millis() will simply rollover some day, restarting at 0. The difference between a LastVoltCheck near the end and the rolled over CurrentTime is still correct, automatically !