I have several elapsed time millis calculations in my sketch.
One monitors a run status input and calculates the average run time
per number of ON/OFF cycles.
Whenever I load the UNO with a new code version the value initially displayed
for this average runtime calculation is always "4294967295."
As soon as the input registers a change of state the correct elapsed time values will display.
I have tried to clear this nuisance with "if value is greater than X make value = 0."
But for some reason that interferes with a getting a subsequent correct calculation.
This is not a big deal and the code works fine as soon as the digital input gets its first change of state.
Any suggestions on a clean way to make sure at startup your millis calculations are zeroed out?
No code posted so hard to be specific. Have you initialized the variable to zero in the declaration?
Another source of error could be overwriting the memory for the variable (eg, move a string that is too long into the variable declared just before it).
It seems to be a bug in your code. The millis() counter is initialized with 0 at startup.
The value 4294967295 that you got is 0xFFFFFFFF in HEX = the maximum possible value of the millis(). The reason for this answer is most likely due to incorrect use of unsigned arithmetic
The division by zero (undefined behaviour) could also produce a zero. The outcome is compiler / platform / weather / solar flare / etcetera dependent. In other words, it would be handy for @edthewino to also indicate which board(s) they are using.
Ok, I took your suggestion and made a new sketch with just the code related to the
runtime average calculation.
I was not able to reproduce the same "4294967295" being placed in the Hrs. data field
when the processor first initialized.
But what I did discover is two particular lines of code if left in would cause the processor to halt/hangup. Commenting them out allowed the UNO to keep looping.
They are:
The line initializing 'blr_cycles_counter' to '0' is the culprit. As soon as I made it a '1'
the processor would continue running. So I think this is what's causing the bogus
number on initialization: divide by zero; not good I am thinking. As soon as the boiler goes through a cycle the phantom number goes away.
I need to have it start out with a zero but not sure what a workaround would be.
I did change all the unsigned long declarations to 'int' as I was troubleshooting the code.
Is it ok in this application to leave them as int's or stay with unsigned integer?
int blr_cycles_counter = 0;
```cpp
#include <math.h>
unsigned long blr_ON_mismatch_Millis = 0;
unsigned long blr_run_cmd_Millis = 0;
unsigned long blr_ON_Millis = 0;
int latest_on_cycle = 0;
unsigned long blr_daily_run_Millis = 0;
unsigned long total_daily_run_Millis = 0;
unsigned long blr_OFF_Millis = 0;
int blr_OFF_interval = 0;
int blr_OFF_min = 0;
int blr_OFF_hr = 0;
int blr_OFF_mins = 0;
int daily_hours_elapsed = 0;
int blr_cycles_counter = 0;
int last_blr_state = 0;
int current_on_cycle = 0;
int current_cycle_seconds = 0;
int current_cycle_minutes = 0;
int current_cycle_hours = 0;
int current_cycle_run_minutes = 0;
int current_cycle_run_seconds = 0;
int last_cycle_seconds = 0;
int last_cycle_minutes = 0;
int last_cycle_hours = 0;
int last_cycle_run_minutes = 0;
int last_cycle_run_seconds = 0;
int seconds = 0;
int minutes = 0;
int hours = 0;
int run_minutes = 0;
int run_seconds = 0;
int avg_mins_per_cycle = 0;
int avg_hrs_per_cycle = 0;
int avg_min_per_cycle = 0;
unsigned long current_Millis = 0;;
boolean blr_ON_status = false;
boolean blr_on_state = false; // used to capture millis() once when boiler comes on
boolean blr_off_state = false; // used to capture millis() once when boiler goes off
boolean blr_on = false;
void setup() {
Serial.begin(115200);
}
void loop() {
current_Millis = millis();
if (blr_ON_status == false && blr_off_state == false) {
blr_OFF_Millis = current_Millis;
blr_on_state = false;
blr_off_state = true;
latest_on_cycle = (blr_OFF_Millis - blr_ON_Millis);
blr_daily_run_Millis = (blr_daily_run_Millis + latest_on_cycle);
}
last_cycle_seconds = latest_on_cycle / 1000;
last_cycle_minutes = latest_on_cycle / 60000;
last_cycle_hours = latest_on_cycle / 3600000;
last_cycle_run_minutes = last_cycle_minutes % 60;
last_cycle_run_seconds = last_cycle_seconds % 60;
if (blr_ON_status == true) {
current_on_cycle = current_Millis - blr_ON_Millis;
current_cycle_seconds = current_on_cycle / 1000;
current_cycle_minutes = current_on_cycle / 60000;
current_cycle_hours = current_on_cycle / 3600000;
current_cycle_run_minutes = current_cycle_minutes % 60;
current_cycle_run_seconds = current_cycle_seconds % 60;
total_daily_run_Millis = blr_daily_run_Millis + current_on_cycle;
}
seconds = total_daily_run_Millis / 1000;
minutes = total_daily_run_Millis / 60000;
hours = total_daily_run_Millis / 3600000;
run_minutes = minutes % 60; // modulus operator provides remainder/leftover value after division
run_seconds = seconds % 60;
avg_mins_per_cycle = (total_daily_run_Millis / 60000) / blr_cycles_counter;
avg_hrs_per_cycle = (total_daily_run_Millis / 3600000) / blr_cycles_counter;
avg_min_per_cycle = avg_mins_per_cycle % 60;
Serial.println();
Serial.print(" Avg runtime hour/min: ");
Serial.print(avg_hrs_per_cycle);
Serial.print(": ");
Serial.print(avg_min_per_cycle);
Serial.println();
delay(1000);
}
Use a flag (bool; seen_first_cycle seems a reasonable choice for the variable name). Set it (true) after the first cycle. Until the flag is set, don't go through any code that could divide by zero.
They are counts of events. It's impossible to have less than zero events. unsigned is the correct choice.
Because the Arduino Uno has a simple microcontroller, a division by zero will go wrong without warning. There is no error function that is called.
Sometimes a integer division by zero is runtime, I think that the result will be -1 or all FF (0xFFFFFFFF for a 32 bit variable).
Sometimes a integer division is already detected by the compiler, then some code might not even be generated. It is detected with all warnings turned on: warning: division by zero [-Wdiv-by-zero]
You have too many variables, too much if-else constructions, variables with almost identical names, and 2000 lines is still a small sketch for some of us.
There are programming techniques to create consistent code, or libraries that keep track of timing.
I think there are better ways to make your sketch easier to maintain.
A little improvement is how to use 'bool' variables. They are already 'true' or 'false', so you don't have to check them against 'true' or 'false':
bool umbrella;
bool raining;
if (!raining and umbrella)
{
Serial.println("There was no need to bring an umbrella.");
}