This is just a demonstration code for what is happening. If I set: uint32_t hour, minute, second;
to: uint8_t hour, minute, second
or: int16_t hour, minute, second;
or basically any data type that has range up to 32767, counter overflows after 32767 and jumps to 4294934528 which doesn't make any sense to me. Why should variables: hour, minute or second be larger than 1 byte if they only store numbers up to 60? Tested on original Arduino Uno and Nano Every.
#include <Wire.h>
#include <DS3231.h>
uint32_t counter = 0;
uint32_t hour, minute, second;
DS3231 clock;
RTCDateTime dt;
void setup() {
Serial.begin(9600);
clock.begin();
clock.setDateTime(2024, 3, 29, 9, 6, 0);
}
void loop() {
dt = clock.getDateTime();
hour = dt.hour;
minute = dt.minute;
second = dt.second;
Serial.print("Hour: ");
Serial.print(hour);
Serial.print("\tMinute: ");
Serial.print(minute);
Serial.print("\tSecond: ");
Serial.print(second);
counter = hour * 3600 + minute * 60 + second;
Serial.print("\tCounter: ");
Serial.println(counter);
delay(1000);
}
Serial monitor:
Hour: 9 Minute: 6 Second: 0 Counter: 32760
Hour: 9 Minute: 6 Second: 1 Counter: 32761
Hour: 9 Minute: 6 Second: 2 Counter: 32762
Hour: 9 Minute: 6 Second: 3 Counter: 32763
Hour: 9 Minute: 6 Second: 4 Counter: 32764
Hour: 9 Minute: 6 Second: 5 Counter: 32765
Hour: 9 Minute: 6 Second: 6 Counter: 32766
Hour: 9 Minute: 6 Second: 7 Counter: 32767
Hour: 9 Minute: 6 Second: 8 Counter: 4294934528
Hour: 9 Minute: 6 Second: 9 Counter: 4294934529
Hour: 9 Minute: 6 Second: 10 Counter: 4294934530
Hour: 9 Minute: 6 Second: 11 Counter: 4294934531
Hour: 9 Minute: 6 Second: 12 Counter: 4294934532
Hour: 9 Minute: 6 Second: 13 Counter: 4294934533
Hour: 9 Minute: 6 Second: 14 Counter: 4294934534
Hour: 9 Minute: 6 Second: 15 Counter: 4294934535
It's due to the integer promotion rule.
Is there a way to solve this because I'm using other library with functions that have parameters with size of one byte?
counter = hour * 3600UL + minute * 60 + second;
or
counter = (uint32_t) hour * 3600 + minute * 60 + second;
Essentially: hour * 3600 can overflow, so one of the arguments (either one) needs to be cast to a 32 bit word before multiplication. Once you do that, the additions get promoted to 32-bits as well, so they won't overflow. The minute and second multiplications themselves should not overflow, so they don't need to be promoted.
The former code depends on "long" being 32 bit, which is true on arduino.
Integer promotion has helped you a bit by converting the smaller types to integers before performing operations, but if integers are 16-bit long, it is not enough. Hence, you need to explicitly cast to 32-bit.
counter = hour * 3600 + minute * 60 + second;
Think twice, hour is int16, so 9*3600 + 6*60 + 15 = 32775, but the largest value it can hold is 32767.
It overflows during the calculation, before the result is transfered to counter.
You can specify the compiler to convert hour into int32 when making calculations like ejeffrey said.
This way you can keep hour, minute and second as int8.
Before using a random integer size, check the largest value it can hold.
In your case it's 23h 59min 59s = 86.399. You definitely need int32 for calculation.