Using random() function in an IF statement with RTC

The random() function of the Arduino -though not really random- is a handy command simulate seemingly random occurrances on an Arduino.
For a home automation project I needed a specific action (a light being switched on) to occur at a specific time, but not always at the same time each day. This of course to make would be burglars think it wasnt a timer, but a human to switch on the light. Timers do it at the same time, humans vary.
So I used the following code:
if (now.hour() == 21 && now.minute() == random(10)) {
livingON();
}

My in hindsight stupid idea was that this way the light would switch on at any given moment between 9 and 9.10 pm… which ofcourse it didnt.
It always switched on at 9 pm exactly.
I will explain.
If at 21 hrs  the if statement is entered and the random(10) function generates a  ‘2’, then the condition isnt met because obviously, at 21.00 it is not 21.02. OK so far so good, the loop continues  and at a certain moment it is 21.01. Suppose the random generator then generates a ‘0’, well then the right time is passed already, so again no match.

The reason why it always switches on at 21.00 is because in one minute, the loop with this comparison may cycle maybe 150 times if not more, so obviously in that time the ‘0’ is going to pop up some time and the condition is then met (In my program the loop is passed 24 times/second =144 times/minute, but it is a big program) .

So I needed another way: I needed the outcome of the random function to stay the same every time the IF statement was entered and only to change the next day.

Usually the  SetUp would be great to come up with a one time random number, but that would then stay the same until a reset, so i made a function that would generate a random number and  call that once a day.

That would look like this:

void randomNr()
{
random1=random(5);
random2=random(10);
random3=random(15);
}

subsequently in my loop I would make a call to that function at a specific time, before any of the  numbers was needed, say at 5 am:

if (now.hour() == 5 && now.minute() == 0) {
randomNr();
}

and my earlier compare statement would become:
if (now.hour() == 21 && now.minute() == random1) {
livingON();
}

Now of course since the loop cycles faster than a minute, in fact the randomNr() function is called many times, but that is not really a problem as there will be only one outcome at  5:01:00 am.
If you want to avoid  calling the randomNr()  function for a full minute then of course you could take seconds into the comparison or set a flag that you clear  a little bit later.

As I mentioned before, the random() function on the Arduino in fact is not entirely random. in fact on a reset of the Arduino, the output of the function will be sequentially the same as before the reset. It is possible to let the  randomnumber generator start  with another number in the sequence with randomSeed(number);
But if the number in randomSeed(number) will be the same time after time, the outcome of the random() function will again be pseudo random.
Customary is to seed the randomSeed() function with the noise from an unused  Analog port, like
randomSeed(analogRead(A0));
That ensures a higher level of randomness

Advertisement