Achieving randomness from analogRead()


I got a reply to topic that suggests using analogRead() to get true random values, having in mind that if there are no potentiometer or resistor connected to the pin its value will be floating at random.

I'm using a function that adds analogRead(0)+...+analogRead(7) in the Nano. To get a random value between 0 and 9, I take modulo 10 from the sum.

I wonder if the pins will be always floating in an unstable state or will they stabilize after a while.


They will always float but will pick up everything around. Fat change they just ride the 50Hz/60Hz cycle of the mains that is all around it. But because the Arduino isn't synced to that it is pretty random. BUT, I doubt it is a flat random. That's why it most often is used as a random seed for the random function which is pseudo random but has (a more) even probability. So just seed it on startup with the adc and use the random function afterwards :slight_smile:

Interesting idea to use more than one input. I didn’t do that, but this worked well for me:

// random seed 1.04
// produces a generally random number based on processing
// error voltages from the readings taken from the analog to digital
// conversion port
// on the Arduino

// 2016-02-17 32 bit test/demo version

const byte analogPort = A1;

const int BUCKET_SIZE = 64;
int buckets[BUCKET_SIZE];

void setup() {

void loop() {
  long temp = getRandomSeed(31);

  for (int i = 0; i < BUCKET_SIZE; i++)
    if (buckets[i] == 0)
      Serial.print(' ');
    Serial.print(' ');

long getRandomSeed(int numBits)
  // magic numbers tested 2016-03-28
  // try to speed it up
  // Works Well. Keep!
  if (numBits > 31 or numBits <1) numBits = 31; // limit input range
  const int baseIntervalMs = 1UL; // minumum wait time
  const byte sampleSignificant = 7;  // modulus of the input sample
  const byte sampleMultiplier = 10;   // ms per sample digit difference

  const byte hashIterations = 3;
  int intervalMs = 0;

  unsigned long reading;
  long result = 0;
  int tempBit = 0;

  pinMode(analogPort, INPUT_PULLUP);
  pinMode(analogPort, INPUT);
  // Now there will be a slow decay of the voltage,
  // about 8 seconds
  // so pick a point on the curve
  // offset by the processed previous sample:

  for (int bits = 0; bits < numBits; bits++)

    for (int i = 0; i < hashIterations; i++)
//      Serial.print(' ');
//      Serial.print( hashIterations - i );
      delay(baseIntervalMs + intervalMs);

      // take a sample
      reading = analogRead(analogPort);
      tempBit ^= reading & 1;

      // take the low "digits" of the reading
      // and multiply it to scale it to
      // map a new point on the decay curve:
      intervalMs = (reading % sampleSignificant) * sampleMultiplier;
    result |= (long)(tempBit & 1) << bits;
//  Serial.println();
  return result;

I got a reply to topic that suggests using analogRead() to get true random values…

“Not reliable” is a good phrase to associate with the technique.

The linked article is worth reading…