Re: Random()

Off-topic posts split from...,132949.0.html

Seed the random number generator with your adc: adc a spare pin and get its lowest bit for as many times as you need - 8 times if your seed is an 8-bit type and 32-times if your seed is a 32-bit type.

I'm not sure if I completely understand what you are saying... I'm a real newbie w/ the arduino IDE.

He doesn't either or he would have offered his opinion... FWIW.


I'm not sure if I completely understand what you are saying

google rand() srand().

The approach I outlined will provide a truly random number.

That looks good.

One suggestion: you want to seed the random number generator with a truly random number. So do successive fills with the adc’s lowest bit.

  unsigned long tmp = 0x01, rseed=0;
  //create a 32-bit random number
  do {
    if (analogRead(1) & 0x01) rseed |= tmp; //test bit 0
    else rseed |= 0x00;
    tmp = tmp << 1; //left shift the mask
  while (tmp);
  randomSeed(tmp); //seed the random number generator

I would actually use rand() and srand() for their portability.

You can actually use this approach to generate a truly random number (vs. the pesudo random number from rand() or random()), but it takes a lot more time.

Using the LSB of an ADC reading can give pretty good results, but even with whitening it's not truly random.

There's a mega thread around where I (and others) tried it, when you graph the results you get definite banding.

It's well good enough for most applications though.


Here is the 1st ~2000 of adc data, using myanalogRead():

unsigned short myanalogRead(unsigned char pin) {
  ADMUX = 0x00;  //Vref = DEFAULT, adc on adc0, right justified
  ADCSRA =  (1<<ADEN) |    //enable adc
            (0<<ADSC) |    //don't start the adc yet
            (0<<ADATE) |  //no auto sampling
            (1<<ADIF) |    //clear adc flag by writing 1 to it
            (0<<ADIE) |    //no adc interrupt
            (1<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);  //1/16 adc prescaler
  ADCSRA |= (1<<ADSC);      //start the conversion
  while (ADCSRA & (1<<ADSC)) continue; //wait for the conversion to end
  return ADC;

I had it fixed on adc0.

adc rand.PNG

First 2500+ data points using the stock analogRead():

adc rand analogRead.PNG

myanalogRead(), over 4500 samples.

adc rand 4500.PNG

Looks pretty random to me.

Yes it does. I used analogRead() IIRC, interesting difference I wonder why. Maybe the /16 div factor you're using, They seem to use 2.


dhenry: google rand() srand(). The approach I outlined will provide a truly random number.

No, it doesn't. Using your function, I get a steady stream of...


I'll give you a hint, @dhenry, making a claim that something provides "truly random numbers" requires a mathematical proof. Posting a single function with one person's casual observations is not even close.

With the stock analogRead(), here are the top value counts after about 2500*8 samples:

value  count
0   107
84  96
42  89
21  89
10  81
64  79
80  78
8   78
85  77
2   77

Maybe the /16 div factor you're using,

That's not done without reason, :)

They seem to use 2.


dhenry doesn't need facts, he has an opinion about [u]everything[/u] and he IS NEVER wrong. Just ask him...


If you want true randomness, try biasing a diode near the "knee" of the I-V curve (around 0.7V for a silicon diode). The current will fluctuate randomly due to thermal noise.

73, NV1T

You already have that diode, in some mcus with a temperature sensor;

But the thermal noise is too small to produce a truly random figure by the onboard adc.

Yeah, you might need to amplify it with an op-amp circuit. I built one of these many moons ago. Y'all should read this informative article:

73, NV1T

There is an easier way: reverse connect a npn to form an esaki diode. Power that up via a capacitor + a low. It will form a flasher. The period of its flashes is random and can be easily measured by a timer.