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.

Download: file
///////////////////////////////////////////////////////////////////////////////
// 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.

The analog pads shown are for the Circuit Playground Classic, but the code will still run on the Express.
Download: file
///////////////////////////////////////////////////////////////////////////////
// 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.

This guide was first published on Dec 29, 2016. It was last updated on Dec 29, 2016.

This page (Randomest Random) was last updated on Nov 24, 2020.