Can anyone explain why var_time in the code below is changing while var_t is true? I was under the impression the variable var_time would hold the value of millis() when var_t went true?
boolean var_t;
boolean var_top;
unsigned long var_time;
void loop(){
if (var_t == true) var_time = millis();
if (millis() - var_time >= 10000) var_top = true;
}
its not actually changing...you're calling millis() a second time & thats returning a different number for millis()
here is my standard, basic timing method:
uint32_t nextUpdateTime;
uint16_t updatePeriod;
void loop()
{
if(millis() >= nextUpdateTime)
{
//do work
nextUpdateTime+= updatePeriod; //set the next time to run this
}
}
you'll have to integrate whatever your doing with the bool vars.
if by not handle the overflow, you mean that the timing is irregular at the rollover then, yes I agree. But the program doesn't break at the rollover or anything. I use this when precise timing is not needed...printing serial reports for example. For precise timing, I usually turn to internal interrupts.
I will take your changes in advisement though. Could you explain your use of "static" ? I've only just learned how & when to use static...but thats only inside the context of classes. I don't really understand its meaning in the main namespace like that.
It is actually changing, I am writing var_time to a custom variable along with var_t. When var_t is true, var_time is incrementing. I need var_time to stay constant with the millis() of when var_t went true.
assuming your most recent comment was about your original code:
this line is never run:
if (var_t == true) var_time = millis();
walk it through, var_t is initiated as 0 (false), you never modify...therefore var_time is always 0 . millis is greater than 10,000, not immediately, but very quickly. so the second if statements "always" hits, but it only changes var_top which isn't even used anywhere else
seems like you meant that second if statement to read like this:
if (millis() - var_time >= 10000) var_t = true;
now when you come back through the loop, the first statement will hit, set the current time then wait until the next time to do it all over again.
you could change the first if statment to check var_top, same effect. Point is, I think you've mixed up var_t & var_top.
Consider the scenario, where nextUpdateTime is calculated and is just short of the rollover point(4,294,967,295 ms), say 4,294,967,290ms ... so 5 ms short of the rollover.
If your other processing code takes longer than 5ms to execute in the next loop, then millis() will roll over and the next time you compare millis() >= nextUpdateTime this will be false... and remain false for the next 49 days at least.
The way @nicolajna has described is the correct way to handle millis(). It will never have a problem.
I have not mixed them up. Var_t is actually a digital input, when it goes true I need a snapshot of millis(), and if var_t is true longer than 10 seconds, then var_top is true. The issue is that var_time does not hold the snapshot of millis, it is incrementing as long as var_t is true.
Above was just a simplified version of testing code, which does the same thing as my actual code, maybe easier to under stand if you see more of it below.
if (Tank.HighATO.IsActive() || Tank.isATOTimeOut()) topoff = false;
else if (Tank.LowATO.IsActive()) topoff = true;
if (topoff == true) topoff_t = millis();
else topoff_t = 1000; //to show variable reset
if (millis() - topoff_t <= 10000) Tank.Relay.Off( Port8 ); // if topoff true < 10 sec, port off
else Tank.StandardATO( Port8 ); //else use standard top off routine
Tank.CustomVar[2]=topoff_t/1000; //for monitoring variable in seconds
Tank.CustomVar[3]=topoff; //for monitoring topoff flag where timer should start
And a full description of the arithmetic of both ways (addition vs subtraction) is available here. The addition way is perhaps more intuitive, in that it sets a target time and you keep looking at the clock to see if you got there yet, but it's not the right way to ensure the overflow is handled correctly.
Also if nextUpdateTime overflows before millis the comparison will be true until millis overflows.
A cautionary tale:
At the company I work at we had a somewhat similar bug (had to do with comparing two different data types, but the effect is the same). We were working on a device which, among other things, periodically sent some telemetry data using a mobile connection. The bug was introduced in the part of the code which triggers the telemetry routine to run, which caused the device to send data as fast as the connection allowed. The subscription we had for the device was one of those very cheap IoT subscriptions with high overusage fees. We caught this during a longer testing phase, so we were able to effectively mitigate it, but a few devices did manage to cost us around a 1000USD in just a few days.
Sure, when declaring a variable or function as static in file scope, it makes that symbol visible only to that file. It serves a couple of purposes, mainly avoiding naming conflicts and hiding internal state from other parts of the program. If you were to take a look at a larger C codebase (I'm a C developer after all) you'll see the static keyword used like that all the time, but in C++ you'll typically see it less since it has classes/namespaces and all that.
In my example it's not necessary, but old habbits die hard.
you're still not showing us anything that does anything to the variables in question. what makes var_t true? thus far, the code you've posted operates the way I narrated in my previous response. I don't doubt you're doing something with it, but you haven't shown us.
post the whole program, or at least all of main.cpp if its a big program.
since I have no idea what else your program does, I start by asking if you're doing anything to modify timer0 ? that runs micros() & millis(), changing them will cause problems.
I really dont want to play anymore guessing games, post the code. also advise what board you are compiling for.
thank you. I'm not a coder, so my knowledge is spotty. I've done deep dives in to specific topics, but am missing some of the in between.
with the code they've posted, do you see var_t being set to anything? I don't. But I think they are toggling var_t elsewhere in the loop.
I agree, the simple action of posting a complete sketch would likely lead quickly to a solution. Instead, it's just, "I did this, I did that" responses which can't be resolved outside of the full context.
myself & several others have. Read the thread before you accuse "everyone" of something. had you done that, you'd also have seen the op is more than capable of copy & paste, but thanks for the instructions
first of all you should use self-explainig names. "var_t" says nothing about the purpose of this variable
This is done by state-change-detection
This requires a flag-variable
boolean Var_t_changed = false;
if (lastVar_t == LOW && Var_t == HIGH) { // check if this is the first time that lastVar_t and Var_t are different
if (Var_t_changed == false) {
// if snapshot of time was not yet made
Var_t_changed = true; // set flag-variable "snapshot now done!"
SnapShot = millis(); // store snapshot of time
}
}
lastVar_t = Var_t; // update lastVar_t