Arduino Random Number Generator

Inspired by other designs I've seen online, most directly Rob Seward's design, I decided to build my own random number generator based Will Ware's "avalanche noise in a reverse-biased PN junction" (try this mirror of Will Ware's page). Also important is turbid which introduced me to the concept of hash saturation and the math behind it.

Unlike Seward's design, I treat the noise source as a digital input. The digital noise is biased, but with no excess correlation (after a few years of aging, ~80% "1" bits, entropy upper-bound (shannon entropy) of about .74 bits per bit). In order to ensure that the output data is high in entropy, 48 input bits are mixed into a 16-bit hash (a CRC with lots of '1' coefficients to ensure efficient mixing) which is then sent out via serial. If an entropy of .5 bits per bit is assumed in the input, and the hash is assumed to be well-distributed, then by the principle of hash saturation the output contains .9998 bits of entropy per bit of output, while giving a data rate of 200KB/s (2Mb/s the highest serial data rate possible in a 16MHz AVR -> FTDI design and 10 bits per byte is the fastest standard serial format)

However, the justification of ".5 bits per bit" as a true lower bound of the input entropy, and the justification of the CRC as a well-distributed hash are both hand-wavy at best, so I also check for gross failures in the generator with standard software like rngtest and dieharder. Needless to say, my generator passes these tests or I wouldn't be writing this page.

The package includes a program to read random bytes (rr), and one to add random bytes to the linux /dev/random entropy pool (rd). These programs are written in Python and require pyserial (Ubuntu package name: python-serial). In the latest release, rr has grown linux-dependent in an effort to shed the python-serial dependency but this may be a step in the wrong direction for portability's sake. If you found that an older release ran for you on another platform, just pluck rr out of an older zip.

For more details, see the README and source code (gplv2+) included in the latest zip file.

My circuit uses a MAX680 to produce ∼±10V so that I have the requisite 18V across the PN junction. At $4 (qty 1) you may be better off choosing 9VAC wall wart from your junk drawer plus a full bridge rectifier to obtain ~±12v, or design a charge pump to be driven by PWM to generate the needed voltage. You could also try the inexplicably cheaper MAX232 ($1 qty 1), which has RS232 level-shifting circuitry in addition to the +-9.5V charge pump converter. TI's MAX232 also specifies smaller caps (1µf instead of 4.7µf), so it looks like a good choice in a number of ways.

The astute eye will notice that there's a resistor in the board photo which is not present in the design files. This reflects an earlier revision of the circuit, in which ANALOG0 had a resistive divider R3:R4 as in Seward's design (but value 4.7k in both cases). R4 pulled the voltage down so low that it never reached the minimum voltage to provide a "1" input. I clipped it on my board and removed it from the design files.

There's also a peculiarity on the Arduino board: this is a very old board with no auto switching between USB and external power sources for the logic supply. The diode-on-tiny-circuit-board is my rudimentary attempt at adding this feature. It doesn't affect the functioning of the RNG.

I don't know whether the 2Mb/s serial data rate works on the newer arduino boards such as the Arduino Uno which use a second avr to implement the USB interface; I suspect that it does not. However, in the US, has recently added the 'red board' which is an Arduino-compatible board which retains the FT232-based interface. While I haven't actually tested with this board, I expect that it would work well.

Update, January 2013: I've heavily amended the original discussion based on my discovery of the turbid paper with an eye to providing justification of the high entropy of the output stream, and removed most references to the design of earlier revisions of the software.

Update, November 2013: To program the Sparkfun RedBoard (and presumably other UNO/Optiboot boards), you must modify the Makefile to use the following programming line:

AVRDUDE +=  -c arduino -p ATMEGA328P -P $(PORT) -b115200
My firmware is not comptible with Arduinos that use a second AVR to handle USB communication. It requires the FTDI-style USB which is capable of a 2Mbit/s data rate.

Files currently attached to this page:


Entry first conceived on 10 November 2009, 16:00 UTC, last modified on 20 November 2013, 2:11 UTC
Website Copyright © 2004-2021 Jeff Epler