This little block I am working should be stupid simple, but its making me mad. Basically I am trying to count down from the current day to January 1st, so I know which day of the year on am on. The && operator is breaking it. Currently the while loop exits when it reaches June 1st.
#include "RTClib.h"
RTC_DS3231 rtc;
void setup () {
Serial.begin(57600);
#ifndef ESP8266
while (!Serial); // wait for serial port to connect. Needed for native USB
#endif
//rtc.adjust(DateTime(2020, 06, 16, 17, 15, 0));
}
void loop() {
int hours;
int month;
int day;
DateTime now = rtc.now();
//hours = now.hour() * 60 + now.minute(); // minutes since midnight
int dayofyear = 0;
while ((month > 1) && (day > 1)) {
DateTime dayb4 (now - TimeSpan(dayofyear,0,0,0));
month = dayb4.month();
day = dayb4.day();
Serial.println(dayofyear, DEC);
Serial.println(dayb4.month(), DEC);
dayofyear++;
delay(100);
}
}
Well, admittedly not fully analyzing your code, it is generally the case that a while() is safer programming wise than a do..while(). It's a complex long winded topic, and there certainly are good cases for do..while() but anyway... it's because with the while(){} there is at least one check at the beginning which tends to validate the input, whereas do..while just does anything once without any complaining. If it works for you, great! Next project! I look at my old code and just shudder sometimes.
Otherwise they just get initialised with random values. Whatever happens to be on the stack/in the registers used to store them during the lifetime of the loop function.
Then when you got to this code...
while ((month > 1) && (day > 1)) {
Your while will never execute if either month or day are zero or less. Nothing immediately to do with June 1, other than that happens to leave the required values randomly on the stake/in registers for the next time through loop.
As arduino_new says, try...
void loop() {
int hours = 2; //must be assigned a value before attempting access
int month = 2; //must be assigned a value before attempting access
int day;
The value of 2 is purely arbitrary to satisfy the “greater than one” condition in the while the first time it is executed each time through loop. You can also test your code by setting a zero or negative value and see that the code in the while never executes.
Although do while will also work, since in this case you do always want the loop to execute at least once. And also with only one loop....
do {
....
} while (month > 1 || day > 1);
Edit: Come to think of it, if you are trying to count back to 1 Jan in the year, don’t you want || (OR) in both cases? Otherwise it will only count back to the first day of the current month.
So that’s 2 bugs in your original code...
Not setting initial values for moth and day, but then attempting to test them anyway
Using && when you meant to use ||
Edit again: Also isn’t the easiest way to calculate “ordinal day of the year” to get a TimeSpan representing the difference between now and 1 Jan in the current year? Surely TimeSpan has the ability to return the total elapsed days?
Thanks everybody. Is a blank int random or just null? I changed to the do while loop before I saw these responses, but I could also set a value above 1 and go back to a while loop.
It does need to be an and operator, otherwise the loop would exit if it was either the first month of the year, or the first day of any month. At least that's how powershell works, but im finding this to be much more difficult tan PowerShell. BUT...it still isn't working without a single condition and 2 loops, which makes no sense to me.
If somebody has a cleaner way to get the day of year, I would love to have it. For now, I need to move on. This little section has taken way to long:)
tsperry88:
Thanks everybody. Is a blank int random or just null? I changed to the do while loop before I saw these responses, but I could also set a value above 1 and go back to a while loop.
Depends where it is...
For a global, any uninitialised variable is ZERO. That’s not necessarily the same as NULL (but a lot of platforms, including Arduino it is). But it’s still wrong to conflate zero and NULL.
For a local, non-static, variable it is random junk left over from whatever was on the stack or in a temporary register.
It does need to be an and operator, otherwise the loop would exit if it was either the first month of the year, or the first day of any month.
Sorry, but you’re wrong. It needs to be OR to only exit when they are BOTH 1.
Otherwise, with AND, the loop terminates when EITHER is one.
Think about it...
Repeat while day > 1 AND month > 1
That expression is TRUE only if BOTH day is > 1 AND month is > 1.
If either condition is FALSE the result of AND is false. Therefore the loop exits when EITHER value is one, not when BOTH of them are 1.
At least that's how powershell works, but im finding this to be much more difficult tan PowerShell. BUT...it still isn't working without a single condition and 2 loops, which makes no sense to me.
I’m not totally familiar with powershell, but I’d be absolutely astounded if it’s while loops worked any other way that using standard Boolean logic. This is common to every single programming language I’ve ever encountered.
Please post the powershell script example if you still insist otherwise.
And did you try the single “do while (.... OR ....)” example?
You are right. Sorry. The statement becomes false and exits if either condition is met. Powershell would work the same way. Maybe I am not as good as I thought at a language I know:)
tsperry88:
You are right. Sorry. The statement becomes false and exits if either condition is met. Powershell would work the same way. Maybe I am not as good as I thought at a language I know:)
That fine. We all make mistakes, and Boolean logic can mess with your head, especially when they involve inverse logic.
tsperry88:
If somebody has a cleaner way to get the day of year, I would love to have it. For now, I need to move on. This little section has taken way to long:)