Random Isn't Random
We can create the random period of time needed for the countdown using the random()
function available in the Arduino library. However, it may not behave like you think it behaves. Let's take a look.
Try running the simple sketch below.
/////////////////////////////////////////////////////////////////////////////// // Circuit Playground Random Demo // // Author: Carter Nelson // MIT License (https://opensource.org/licenses/MIT) #include <Adafruit_CircuitPlayground.h> #define SHORTEST_DELAY 1000 // milliseconds #define LONGEST_DELAY 10000 // " /////////////////////////////////////////////////////////////////////////////// void setup() { Serial.begin(9600); CircuitPlayground.begin(); } /////////////////////////////////////////////////////////////////////////////// void loop() { // Wait for button press while (!CircuitPlayground.leftButton() && !CircuitPlayground.rightButton()) { // Do nothing, just waiting for a button press... } // Print a random number Serial.println(random(SHORTEST_DELAY, LONGEST_DELAY)); // Debounce delay delay(500); }
With this code loaded and running on the Circuit Playground, open the Serial Monitor.
Tools -> Serial Monitor
and then press either button. Each time, a random number from SHORTEST_DELAY to LONGEST_DELAY will be printed out. Let me guess, you got the same sequence I did as shown below.
And if you reset the Circuit Playground and try this again, you will get the same sequence again. So what's going on?
In turns out that the random()
function implemented in the Arduino library is only a pseudo-random function. This simply means it isn't fully random (pseudo = false). It just produces a random like sequence of numbers, and the same sequence every time.
To get around this, we need to initialize the random function with a random value. This is called seeding the function and the value is called the seed. But where can we come up with a random seed value? One way is to use some of the (hopefully) unconnected pads on the Circuit Playground and read in their analog values. Since the pads are not connected, the value returned by a call to analogRead()
will contain noise. Noise is random, and that's what we want.
Here's a new version of the code that includes a call to randomSeed()
in the setup()
. This seed is generated by reading all four of the available analog inputs.
/////////////////////////////////////////////////////////////////////////////// // Circuit Playground Random Demo with Seed // // Author: Carter Nelson // MIT License (https://opensource.org/licenses/MIT) #include <Adafruit_CircuitPlayground.h> #define SHORTEST_DELAY 1000 // milliseconds #define LONGEST_DELAY 10000 // " /////////////////////////////////////////////////////////////////////////////// void setup() { Serial.begin(9600); CircuitPlayground.begin(); // Seed the random function with noise int seed = 0; seed += analogRead(12); seed += analogRead(7); seed += analogRead(9); seed += analogRead(10); randomSeed(seed); } /////////////////////////////////////////////////////////////////////////////// void loop() { // Wait for button press while (!CircuitPlayground.leftButton() && !CircuitPlayground.rightButton()) { // Do nothing, just waiting for a button press... } // Print a random number Serial.println(random(SHORTEST_DELAY, LONGEST_DELAY)); // Debounce delay delay(500); }
Load this code, open the Serial Monitor, and try again by pressing the buttons. Hopefully you get a different sequence this time, and it's different than the one I got.
While this isn't perfect, it will work for our needs. This is what we will use to generate the random amount of time needed for our countdown timer.
Page last edited March 08, 2024
Text editor powered by tinymce.