Go Down

Topic: Re: Random() (Read 1 time) previous topic - next topic

dhenry

Nov 18, 2012, 01:31 am Last Edit: Nov 20, 2012, 03:44 am by Coding Badly Reason: 1

Off-topic posts split from...
http://arduino.cc/forum/index.php/topic,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.

Docedison

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

Bob
--> WA7EMS <--
"The solution of every problem is another problem." -Johann Wolfgang von Goethe
I do answer technical questions PM'd to me with whatever is in my clipboard

dhenry

Quote
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.

dhenry

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.

Code: [Select]

  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.

dhenry

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.

Graynomad

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.

_____
Rob
Rob Gray aka the GRAYnomad www.robgray.com

dhenry

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

Code: [Select]

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.


dhenry

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


dhenry

myanalogRead(), over 4500 samples.


dhenry

Looks pretty random to me.

Graynomad

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.

_____
Rob
Rob Gray aka the GRAYnomad www.robgray.com

Coding Badly

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...

Code: [Select]
1023
1023
1023
1023
1023
1023
1023
...
1023


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.

dhenry

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

Code: [Select]

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


dhenry

Quote
Maybe the /16 div factor you're using,


That's not done without reason, :)

Quote
They seem to use 2.


:)

Go Up