I've created code where to simulate a coin toss and tally the results of heads or tails. I'm using a random value generated from the noise on an unattached analog A0 pin as the seed value.
// PINS USED
#define tails 13 // led for tails
#define heads 12 // led for heads
// VARABILES
int tail_counter = 0;
int head_counter = 0;
long random_number;
void setup()
{
Serial.begin(9600);
pinMode(tails,OUTPUT);
pinMode(heads,OUTPUT);
/* if analog input pin 0 is unconnected, random analog
noise will cause the call to randomSeed() to generate
different seed numbers each time the sketch runs.
randomSeed() will then shuffle the random function.
*/
randomSeed(analogRead(0)); // reads random noise on A0
}
void loop()
{
delay(400);
// generate random number from 0 -1023 from pin A0
random_number = random(1023);
Serial.print(random_number);
if (random_number % 2 == 1) // odds, since there's a remainder
{
Serial.println(" - odd");
tail_counter++;
digitalWrite(tails,HIGH);
delay(300);
digitalWrite(tails,LOW);
delay(300);
}
else // evens
{
Serial.println(" - even");
head_counter++;
digitalWrite(heads,HIGH);
delay(300);
digitalWrite(heads,LOW);
delay(300);
}
// print running coin flip tally
Serial.println();
Serial.print("***tails = "); Serial.println(tail_counter);
Serial.print("***heads = "); Serial.println(head_counter);
Serial.println();
}
There's a few points I'm confused on. What I understand is that the value of the random noise on A0 is inserted into the microcontroller's algorithm at a random point, and values are then generated from that starting point, hence a "planned seed' in the algorithm.
But this means that the seed value is constant each loop, and the algorithm, whatever it is, won't truly be random.
What I think would actually be random would be if I were to move this line:
randomSeed(analogRead(0)); // reads random noise on A0
...to setup() into the void loop() and have it read the value on A0 each loop and then reset the algorithm with a new seed each loop.
But having said that, it seems cumbersome to even call a pin when I could just use millis() as the seed value, and read the timer each loop, which would accomplish the same thing, with more "randomness" (since potential for larger numbers), I think.
From a cryptographic point of view, you are right - successive calls to random() are not genuinely random because they are actually a repeating pseudorandom sequence with a very, very long cycle. But seeding with a value every time won't help you because you haven't increased the entropy of the analog pin, which is relatively low. Many times you will be seeding with the same value.
The key to randomness with millis(), is the "when". For example, if you happen to always seed with millis exactly 1 milliseconds apart in your code, the following bit will always be opposite to the previous one, not random. In a casual sense, it might not matter if you mash the bits by running random() a fixed number of times, because then any given bit may or may not have changed. It's exhibits a kind of show of randomness, but it really isn't because it will repeat when the seed repeats.
Thank you for your response. I get what you mean that I haven't "increased the entropy of the analog pin". This should probably only occur with external noise to the UNO, e.g. a passing magnetic field or movement, etc. occurs near it.
What I'm now curious about is when the seed from the analog noise is returned, it will be somewhere between 0-1023.
In this line:
random_number = random(1023);
I think I am setting a range of 0-1023 for a random number, generated from the analog pin A0, to be "seeded in" or "placed in".
So here's my question: Is it correct that the returned seed value from the analog pin a0 will then be placed somewhere in this 0 - 1023 range as a "starting" point in the microcontroller's pseudorandom sequence?
If that's the case, should I have extended the range instead using:
random_number = random(1000000);
My hold up here is that I thought I needed the 1023 since it is a 10 bit analog pin, but I may be confusing myself here...
the "seed" is not returned from the random() function. It changes the starting point in the sequence of the pseudo random numbers. What is returned is the next element but within the range you specify.
project_science:
What I'm now curious about is when the seed from the analog noise is returned, it will be somewhere between 0-1023.
It's not that good. It will actually be more like (for example) between 750-770. It won't jump around much. So you're really only getting a few bits of randomness from it.
Thanks for all your responses. I've taken a break from the code, but returned to figure out how to generate a truly random number (if that actually exists), or at least closer to it. It seems that the unattached analog pin would have a larger randomness of noise if it were in a dynamic setting, e.g. affected by movement, temp, magentic fields, etc., vs. that of sitting on my desk.
Having said that, can you use a "random of a random" (function of a function), and thus increase the overall randomness of a number? The following, though possibly not correct syntax, illustrates what I'm thinking (hopefully):
randomSeed(millis(randomSeed(analogRead(0))));
What I'm trying to do here is take a somewhat random value from the noise on the unattached A0 pin (even if it's in a small range as aarg said, and use that to call the timer at different time intervals between the last call.
The resulting seed value would then be placed at far more random starting sequence points in this range:
random_number = random(4294967295); /* using var data type 'unsigned long = random_number' where range max is 4,294,967,295 */