Best way of random seed

I read a bunch of stuff, but I'm not able to get the best practice to generate "real" random number, i.e. numbers with a large entropy every single time. I understood that the key is to choose a good random seed.
I need a random for a uint32. I tried as randomSeed() both millis() and analogRead() of a disconnected pin.
With the first one, I get always increasing random numbers. With the second I get "very close" numbers. Big failure.

So, what's the point of having a random() function when I actually have to generate myself the random seed with large entropy? At the end I end up writing the random() myself :slight_smile:

Is there any best practice?

The point of having a random() function is speed, especially when you need more than 1 random number in your program. A good seed could take 100ms. While calling random() takes a fraction of that time.

As a seed you could take the LSB of analogRead() on a disconnected pin and read it multiple times to construct your seed.

A good question to ask yourself is how random do they really need to be? What is the purpous of your random number?

If you really need a good random seed (or random numbers), you can use the Entropy library:

(assuming you are using a board that is supported by the library)

I need it to assign UUID so that the collision of two identical UUID is statistically improbable.
For the small number of UUID I need, a uniformly distributed random in 0-uint32MAX is good enough, and the Entropy library seems to have what I need :).
Thanks.

Its very hard to generate entropy in a small deterministic microcontroller. If you just need a static UUID you
can use a unique ID chip like the 11AA02E48 http://ww1.microchip.com/downloads/en/DeviceDoc/11AA02E48-11AA02E64-2K-UNIO-Serial-EEPROMs-Data-Sheet-20002122E.pdf

A good question to ask yourself is how random do they really need to be? What is the purpous of your random number?

Random enough" is where I always start - You can get deeply into the philosophy of randomness or you can simply shoot for something “humanly unpredectable”, etc.

One way to improve it is to use millis() with a push-button so it “grabs” a seed when you press the button (if that’s practical for your application).

Or, I haven’t tried this but you could attach a “long wire” to a floating analog pin to act as an antenna picking-up the electromagnetic AC power line radiation. (If you’ve ever touched an audio input and heard a “buzz”, that’s what I’m talking about.) Of if your device has a power supply with a regular AC transformer you can tap-into the transformer secondary (after biasing and adjusting the voltage as necessary). Or you could build sine-wave or triangle wave oscillator to generate “random” analog readings.

Jane Nordholt’s Entropy Engine, currently a hot selling item for those who want to generate random seed numbers, uses the chaotic jostling of photons to generate random numbers.

Try this:

// 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() {
  Serial.begin(9600);
}

void loop() {
  long temp = getRandomSeed(31);
  buckets[temp%BUCKET_SIZE]++;

  for (int i = 0; i < BUCKET_SIZE; i++)
  {
    if (buckets[i] == 0)
    {
      Serial.print(' ');
    }
    else
    {
      Serial.print(buckets[i]);
    }
    Serial.print(' ');
  }
  Serial.println('*');
}

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;

  Serial.print("randomizing...");
  pinMode(analogPort, INPUT_PULLUP);
  pinMode(analogPort, INPUT);
  delay(200);
  // 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++)
  {
      Serial.print('*');

    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(result);
//  Serial.println();
  return result;
}
1 Like