I have this if statement:
if (now.hour() == 5 && now.minute() == 10 && now.second() == 0 && now.dayOfTheWeek() != 1 && now.dayOfTheWeek() != 7){
Is there a way to condense that for the purposes of saving on some bytes?
Ultimately trying to say "At 5:10 every weekday do X"
2 Answers 2
The following saves a couple of program bytes (but no RAM) when now
is a structure with a byte called DayofWeek
:
if ((byte)(now.DayofWeek+249)>250) ...
-vs-
if ((now.DayofWeek != 1 && now.DayofWeek != 7)) ...
It might save slightly more than that in your case, where now.dayOfTheWeek()
appears to be a function reference. This technique will work if function now.dayOfTheWeek()
returns a byte
, that is, an unsigned char
. The technique depends on value 7+249 overflowing to zero (削除) in byte arithmetic (削除ここまで) when truncated to a byte, because 7+249 is 0 modulo 256.
The cast to byte
[or uint8_t
] of now.DayofWeek+249
is needed because of int
promotion as Edgar Bonet pointed out.
-
This does not work. You have to cast the sum to
uint8_t
. Otherwise, per the rules of integral promotion, everything in the expression is evaluated as 16-bit signed ints.Edgar Bonet– Edgar Bonet2016年05月21日 11:56:15 +00:00Commented May 21, 2016 at 11:56 -
@EdgarBonet, it does work. Specifically, it gives correct results for
now.DayofWeek
values from 1 to 7. Note,now.DayofWeek
is declared as a byte (which is equivalent to uint8_t except for being easier to pronounce) sobyte
, notint
, arithmetic is used.James Waldby - jwpat7– James Waldby - jwpat72016年05月21日 23:31:46 +00:00Commented May 21, 2016 at 23:31 -
No, it doesn't, and you obviously did not try. If
DayofWeek
is 7, thenDayofWeek+249
is 256, and since 256>250, the test succeeds, while it shouldn't. Note: there is no such thing as "byte arithmetic" in C: the operation is done on ints. C.f. for example this CERT article on integer conversion rules and, more specifically, the section titled "Integer Promotions".Edgar Bonet– Edgar Bonet2016年05月22日 07:38:26 +00:00Commented May 22, 2016 at 7:38 -
@EdgarBonet, unfortunately my test printed out the result of assigning
now.DayofWeek+249
to a byte – hence the value I expected – rather than the result of the comparison :( , See editJames Waldby - jwpat7– James Waldby - jwpat72016年05月22日 16:21:48 +00:00Commented May 22, 2016 at 16:21
Yes. The method now() Returns the current time as seconds since Jan 1 1970. Simply keep tract of all your time this way and you only need to test this one value.
The Arduino is not a good source of time over long periods. Consider using an RTC (Real Time Clock) chip. This Arduino page links to this page which talks about an RTC. (I will leave it up to you to research any compatibility issues.)
Many RTCs contain a register set specifically designed to handle tasks such as you outlined above. For example, setting alarms off on weekdays only or on specific days of the month.
If absolute time is not important in your application I would try the following code outline. Each test only has 2 operands:
// Turn on Arduino on Monday at the time task is to be performed. Task
// should be performed at that time on Monday, Tuesday, ... Friday.
// Nothing should happen on Saturday & Sunday. Then cycle repeats.
// Set time to zero.
// Count through days (0, 1, 2, ...).
// Wait each day until number-of-seconds is greater then seconds-in-a-day
// times the day number.
// If day number is 4 or less do activity. Else skip activity.
// If day number is more than 6 set the day counter to 0 and set the time
// to zero.
If you want to start the Arduino at arbitrary times, set the initial Arduino clock value to the number of seconds from the time the activity would have been performed on Monday and initialize the day counter to the appropriate value. For example if you started the Arduino on Tuesday 23 hours after the time the activity should have happened on Monday set the Arduino clock to 23 * 60 * 60 seconds and initialize the day counter to 2. Of course you can calculate the initial day counter value using = initial_number_of_seconds / 60 * 60 * 24.
-
I'm trying to get it to be
true
at a specific time every weekday, so I'm not sure how what you've said applies here.Shpigford– Shpigford2016年05月21日 01:36:54 +00:00Commented May 21, 2016 at 1:36 -
Answer has been changed. Consider an RTC. Most RTCs contain a hardware solution for your situation. If Arduino time drift is tolerable, use the code outline which only uses seconds in a week to drive events.st2000– st20002016年05月21日 14:47:57 +00:00Commented May 21, 2016 at 14:47
now
.&& now.dayOfTheWeek() != 1 && now.dayOfTheWeek() != 7
.now.dayOfTheWeek()
will actually calculate the day of the week, where at the other functions just load their value straight from the RTC chip. Calculating the day of the week is quite a bit of work. That would explain the jump in code size. The weird thing is that the RTC chip will actually keep track of the day of the week.