A simple way get a true random() in Arduino

I have seen several solutions like randomSeed and reading varying pin voltage. I needed a real random() for my project. I can now get it using the basic random() from Arduino. The key is keeping the random() running in the background (in a void function of its own) and only picking the random() when needed . This only works if you have an external trigger like a motion sensor or button which is itself triggered by a random event (human interaction for one).

It is a very easy and simple way to get random into a prop code or anything else where you do not want the same sequence from boot every time. Thought it might be useful.

Here is my code:

/*
===========================================================
===XRAD'S frankencode T600 with sound and light effects====
===========================================================

I created this code to work for my needs using Adafruit 
Trinket Mo, Adafruit FXMini, and PIR sensor. PAM8403
amplifier w/manual volume pot more than enough power 
for TA6FD00-04 (04 ohm) speaker.

Some of the base code can be found here:

PIR sensor
https://learn.adafruit.com/pir-passive-infrared-proximity-motion-sensor/using-a-pir-w-arduino

FXMini
https://www.adafruit.com/product/2341

============================================================
*/

#include "Adafruit_Soundboard.h"


#define ledEyes 0      // PWM out to led eyes
#define inputPin 1     //  input pin (for PIR sensor)
#define SFX_RST 2
#define SFX_RX 3
#define SFX_TX 4


Adafruit_Soundboard sfx = Adafruit_Soundboard(&Serial1, NULL, SFX_RST);


int pirState = 0;      // begin with no motion 
int val = 0;             // variable for pin status
int eyeRun = 150;      // runs through led display loop 'x' times

int brightness = 0;    // initial brightness of led (0-255)
int fadeAmount = 3;    // by how many fade segments
int t;                         //random number storage


void setup() {
Serial1.begin(9600);
//Serial.begin(115200);
Serial.println("Adafruit Sound Board!");

if (!sfx.reset()) {
  Serial.println("Not found");
  while (1);
}
Serial.println("SFX board found");
delay (100);
fileListFXMini();

pinMode(ledEyes, OUTPUT);     // the led eyes!
pinMode(inputPin, INPUT);     // IR sensor
}

void loop() {

playMe();  // start the rotating bingo numbers!

val = digitalRead(inputPin);  // read input value
if (val == HIGH) {
  pirState = 1;
  Serial.print("PIR TRIGGERED = ");
  Serial.println(pirState);
}
if (pirState == 1) {
  Serial.print("Playing Track  ");
  Serial.println(t);
  sfx.playTrack(t);   // pick a bingo number 't'!!
  fadeEyes();
}
}


// cool flickering and fading dying robot eye effect
void fadeEyes() {
for (int i = 0; i < eyeRun; i++) {
  brightness = brightness + fadeAmount;
  analogWrite(ledEyes, random(brightness));
  if (brightness <= 0 || brightness >= 150) {
    fadeAmount = -fadeAmount;
  }
  delay(50);
}
pirState = 0;
analogWrite(ledEyes, LOW);
Serial.print("PIR READY = ");
Serial.println(pirState);
}

void playMe(){  // this is running in background when loop is running
t = random(9);  // I only have 9 .wav tracks to rotate through
}


void fileListFXMini() {
uint8_t files = sfx.listFiles();
Serial.println("File Listing");
Serial.println("========================");
Serial.println();
Serial.print("Found "); Serial.print(files); Serial.println(" Files");
for (uint8_t f = 0; f < files; f++) {
  Serial.print(f);
  Serial.print("\tname: "); Serial.print(sfx.fileName(f));
  Serial.print("\tsize: "); Serial.println(sfx.fileSize(f));
}
Serial.println("========================");
}

You can use a floating analog pin to generate a real random number.

However, if you have an RTC you can use seconds in the seed function.

yes, but sadly, the Trinket M0 has only 5 pins, and they were all used up. Plus, this only really adds 3 extra lines of code. I quantified this thread title a bit better....

XRAD:
(in a void function of its own)

Thank you. correction made.

If you ever look for something 'true' random, read The reliable but not very sexy way to seed random.

Latest version of that code is in reply #52 but there is other interesting code in between.

Another way to get a really True Random Number Generator (reply #11) with a random 32-bit number every 1 us:

https://forum.arduino.cc/index.php?topic=472905.0

This is what I use:

XRAD:
yes, but sadly, the Trinket M0 has only 5 pins, and they were all used up. Plus, this only really adds 3 extra lines of code.

i had to look up some things about the trinket, but as i suspected the microprocessor does have (many !!) more pins, they are just not connected to the board... so they are floating, use one (or more) of them for a randomSeed() I do the same on an ESP-01 (which has no analogInput connected at all, works like a charm.

Great feedback. Yes. There are many more unused pins on the M0. I used PIN 7 and it works fine with the Arduino randomSeed. It's only a few more lines of code. I will use this for my next project! Thx Rishi and everyone!

random.org is slightly similar to this project in that it uses random noise from external source to generate the randomness. Pretty cool.

Code variant using randomSeed()

// XRAD'S frankencode T600 motion sensor


#include "Adafruit_Soundboard.h"

#define SFX_RST 2
#define SFX_RX 3
#define SFX_TX 4


Adafruit_Soundboard sfx = Adafruit_Soundboard(&Serial1, NULL, SFX_RST);

#define ledEyes 0      // PWM out to led eye led
#define inputPin 1     //  PIR sensor input pin   


int pirState = 0;      // start at 0 motion
int val = 0;            
int eyeRun = 150;      // runs through led display loop 'x' times

int brightness = 0;    // initial brightness of led (0-255)
int fadeAmount = 3;    // by how many fade segments

long randomNumber;

void setup() {
  Serial1.begin(9600);
  Serial.begin(115200);
  Serial.println("Adafruit Sound Board!");

  if (!sfx.reset()) {
    Serial.println("Not found");
    while (1);
  }
  Serial.println("SFX board found");
  delay (100);
  fileListFXMini();

  pinMode(ledEyes, OUTPUT);     // the led eyes!
  pinMode(inputPin, INPUT);     // IR sensor

  randomSeed(analogRead(7));  // unused floating pin 7 on the Trinket M0
}

void loop() {
  val = digitalRead(inputPin);  // read input value
  if (val == HIGH) {
    pirState = 1;
    Serial.print("PIR TRIGGERED = ");
    Serial.println(pirState);
  }
  if (pirState == 1) {
    randomNumber = random(9);
    int i = randomNumber;
    Serial.print("Playing Track  ");
    Serial.println(i);
    sfx.playTrack(i);
    fadeEyes();

  }
}


// cool flickering and fading dying robot effect
void fadeEyes() {
  for (int i = 0; i < eyeRun; i++) { 
    brightness = brightness + fadeAmount;
    analogWrite(ledEyes, random(brightness));
     if (brightness <= 0 || brightness >= 150) {
     fadeAmount = -fadeAmount;
    }
    delay(50);
  }
  pirState = 0;
  analogWrite(ledEyes, LOW);
  Serial.print("PIR READY = ");
  Serial.println(pirState);
}



void fileListFXMini() {
  uint8_t files = sfx.listFiles();
  Serial.println("File Listing");
  Serial.println("========================");
  Serial.println();
  Serial.print("Found "); Serial.print(files); Serial.println(" Files");
  for (uint8_t f = 0; f < files; f++) {
    Serial.print(f);
    Serial.print("\tname: "); Serial.print(sfx.fileName(f));
    Serial.print("\tsize: "); Serial.println(sfx.fileSize(f));
  }
  Serial.println("========================");
}