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
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?
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.
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.
// 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;
}