So, there seem to be an inordinate number of "how do I get random numbers on the Arduino that don't suck" posts. This is understandable, because as we all know, the RNG always starts with the same seed, and therefore always produces the same string of "random" numbers.

The stock advice of "seed the RNG with an unused analog pin" is grossly insufficient, because reads from said analog pins are *not* in any way random, and fall in a small range of values.

So, here's my method:

- Take only the lowest bits (LSB) from two analogRead calls
- Put them through a von Neumann extractor - if the bits are equal, they are discarded. If the bits differ, the first bit is used
- Collect 32 bits, and assemble them into a 32 bit number
- Repeat (1) - (3) several times, and hash the results together with a hash function.
- Hash in the micros counter. This may seem silly, but since this function takes a different amount of time each time it's run, the microseconds counter will be different each time.
- Use the result of the hash to seed the RNG

Code below:

```
/* initial seed - this is the first 32-bits
of the fractional part of pi - no particular
reason, just a "nothing-up-my-sleeve" number
to ensure that the seed doesn't initialize
to "0".
*/
uint32_t seed = 0x243F6A88;
uint32_t hash(uint32_t x){
// Fowler-Noll-Vo hash function
uint32_t c;
for (uint8_t i = 0; i < 4; i++) {
c = x>>(i*8) & 0xff;
seed ^= c;
seed *= 0x01000193;
}
}
uint32_t seed_rng(){
// loop 16 times
for(uint8_t i=0; i<16; i++){
/* von Neumann extractor -
* gets two bits from analogRead
* if they are equal, discard
* if they are different, uses the
* first bit. Loops until 32 bits are
* collected
*/
uint8_t bits = 0;
// use uint32, because shifting by more than
// the length of a variable will throw a
// warning at compile time
uint32_t a, b, n = 0;
while(bits < 32){
// get LSB of two analogReads, delaying
// 256 uS in between
a = analogRead(A0) & 0b1;
delayMicroseconds(256);
b = analogRead(A0) & 0b1;
if(a !=b){
// if bits are not equal, use bit "a"
n |= a << bits;
bits++;
}
}
// hashes number with existing seed
hash(n);
n = 0;
}
// hash in microseconds counter for some
// added entropy, because why not?
hash(micros());
// seed Arduino RNG
randomSeed(seed);
}
```

Instructions for Use:

- Place the above code in the body of the project (before setup and loop)
- Call seed_rng() from setup. It generally takes a second or two to run, depending on a variety of factors
- Generate random numbers using the Arduino random() function as usual

Caveats - This is designed for game / novelty / non-crypto applications. I have not run this through any formal, statistical tests for randomness, so safety for applications requiring this is not guaranteed.

Apologies about my garbage code; I'm a Python programmer, not a C developer.

If anyone tries this out or has any questions / comments / compliments / feedback / complaints, or just feels like replying, please do.

Also, I'm thinking of packaging this together into a nice, clean library if anyone is interested.