Arduino True Random Number Generator

67,002

65

58

Published

Introduction: Arduino True Random Number Generator

This is just a fun project I have been working on in the last little while. If you like this instructable, consider voting for it in the Arduino Challenge!

Anyone who has experience with programming will have probably used random numbers in their code. These random numbers aren't actually random though. They are actually generated using an algorithm that produces numbers that appear to be random, but the numbers actually follow a sequence. While these "pseudo-random" numbers are fine for some purposes, they just won't do for others. Cryptography is a case where the predictability of pseudo-random would allow someone to break codes with ease.

True random numbers on the other hand rely on quantum phenomena, or chaotic systems. Quantum systems include things like radioactive decay, and shot noise in electronic circuits, and are fundamentally random processes. Chaotic systems are things like atmospheric noise, which is so chaotic, that it can effectively be used as a source of randomness.

I wanted to build a true random number generator just for fun, and to see how well it would work considering that it is fairly cheap and easy to set up.

Step 1: Materials

Arduino - ~$30

MightyOhm geiger counter - $100 without case, $115 with acrylic case  (or any geiger counter with a pulse out)
http://mightyohm.com/blog/products/geiger-counter/

22 gauge solid core copper wire - $4 (for a whole roll. You can probably even use some multi-strand wire)

3 pin female header - found for free

salt substitute (optional) - $4

Step 2: Assemble the Geiger Counter

A geiger counter is a device that is capable of detecting radioactive particles. A particle passes through the geiger tube and ionizes the gas inside. The tube is connected to a high voltage supply, and the ionized gas allows a small current to flow. This pulse is detected, indicating that a radioactive decay has happened. Because it is impossible to predict when a radioactive atom will decay, we can use the time between pulses to generate random bits.

I bought my geiger counter from mighty ohm (www.mightyohm.com). It comes as a kit, so you need to solder it up yourself. It didn't take me long to put it together and it worked perfectly on the first try. Full assembly instructions can be found on their website. Although the geiger counter doesn't come with a display, it does have an LED indicator and a peizo speaker that beeps whenever it detects a particle. The board also has a pulse out pin that we'll use to hook it up to the arduino.

Step 3: Connecting to the Arduino

As I said in the previous step, the geiger counter board has a pulse out pin. The pulse pin is a part of three pins, and the other two provide access to ground and to power. I used a 3 pin female connector to connect to the pins, and soldered a piece of wire to each pin. The geiger counter typically runs off two AAA batteries and draws about 10mA. I chose to save the batteries and run the board off the 3.3v line on the arduino board, which can handle about 50mA of current. I have let it run overnight and it works just fine.

These instructions are specific to the mighty ohm geiger counter, but should be similar to connecting any other geiger counter with a pulse out.

If you want to run the geiger counter without batteries

1. Locate the 3 pin connector labeled PULSE
2. Connect the first pin (marked with an arrow on the board) to the 3.3v output on the arduino.
3. Connect the middle pin (pulse out) to digital pin 8 on the arduino.
4. Connect the last remaining pin to a ground pin on the arduino.

If you want to run the geiger counter with batteries, only do steps 3 and 4, leaving the first pin unconnected

Step 4: Connect the Arduino to a Computer

To interface the arduino with the computer, connect it using a USB port. I chose to program the software in a language called processing, which has built in libraries for communication with an arduino. Its also cross platform, so you should be able to use all the software for this project without a problem.

First download the arduino sketch (make sure you have the newest version of the arduino software) and burn it to your arduino.
Then, download one of the processing sketches.

A couple of notes about the software:

The arduino sketch constantly reads pin 8, checking for a pulse from the geiger counter. When it detects a pulse, it checks the time in milliseconds that the arduino has been running for. It does this four times and then finds the length of time between the first and second pulses and the third and fourth pulses. If the first length of time is greater than the second length of time, then the bit will be a 0. If the second length of time is greater than the first length of time, then the bit will be a 1. Once the bit is generated, it is sent to the computer. This is based of the algorithm used by http://www.fourmilab.ch/hotbits/

There are two different versions of the processing sketch, one with biased bits, and the other with unbiased bits. The difference is that the biased one may be biased slightly due to the hardware, but produces a bit every four counts of radiation. The unbiased sketch preforms an XOR operation on two incoming bits to remove hardware bias, but produces a bit every 8 counts, doubling the time it takes for bits to be produced.

Regardless of the version you chose, the processing sketch will run until it makes 1000000 bits (or you turn it off). Every 500 bits, it saves the bits to a text file that you specify when the sketch starts up.

Step 5: Detect Radiation

Once the arduino has been programmed, you can run the processing sketch. The geiger counter should detect about 20 counts of radiation a minute, as natural background radiation. This equates to about 5 bits a minute, which is pretty slow. To increase the number of counts per minute, I bought salt substitute, which contains potassium chloride. A small percentage of potassium atoms are naturally radioactive (its still perfectly safe) , and we can actually measure the increased radioactivity with the geiger counter. I was able to get up to 60 counts per minute, or a bit over twice background radiation (again perfectly safe). The increase in radioactivity allows the counter to produce bits at a faster rate.

Step 6: Using the Bits

Now you should have your random bits, but what can you do with them? Well you can group them up and convert them into binary numbers. A group of 8 bits will give random numbers between 0 and 255. You can then use scaling algorithms to generate any range of random numbers. You can convert the numbers into characters and make your own one time pad to send unbreakable encrypted messages (just use the processing sketch below!). You can use the bits like a coin, but based on quantum randomness.

At this point you should be able to generate random numbers for whatever you want. If you do something cool with it, post an instructable about it!

Note: I have not subjected the bits to any statistical test to verify how random they are, beyond testing 1000 bits to see if the number of 0s occured as often as 1s (very close to 50/50) Also, I cannot assure that the bits will be random enough for real world serious applications where random numbers are needed, but they should be good enough for whatever a hobbyist would have in mind.

Share

Recommendations

  • Creative Misuse Contest

    Creative Misuse Contest
  • Clocks Contest

    Clocks Contest
  • Oil Contest

    Oil Contest

58 Discussions

Hello, I am very interested in this project.

Have you considered using the Die Hard Tests to evaluate the randomness of this solution?

I built several random number generators for the arduino platform and even though they seemed to produce random numbers, they completely failed all of the Die Hard and other tests that I did on them, meaning they weren't truly random.
I used Avalanche noise generated by a circuit (verified by an oscilloscope) and fed to an Arduino, instead of a geiger counter as you have done.

Some links: (The latter two contain programs that can be used to test randomness)

https://en.wikipedia.org/wiki/Diehard_tests

http://www.phy.duke.edu/~rgb/General/dieharder.php

https://www.fourmilab.ch/random/

1 reply

Hello! Your advanced project is exactly what I'm seeking to realise using Avalanche or thermal(johnson)noise .I will be grateful if you guide me through this process.

Very fun project! It took me awhile to realize that Processing was an interpreted language that ran in an environment that isn't the Arduino software. I think a link to the Processing website might prevent future confusion. My next question is: How do I get it to spit out 4096-bit strings of random upper, lower case, special chars and numbers?

The idea of using a banana as a source of radioactivity almost convinces me to have a go at this project: but Brazil nuts might be better, since bananas don't last long in my house.

Hi i am wanting to build a random number generator also, I need the numbers between 1 and 90 and each number can only be used once..... do you have any suggestions for me??

thanks

2 replies

The following code should give you a general idea


// The Entropy library provides true random numbers and can be obtained from:
// http://code.google.com/p/avr-hardware-random-number-generation/wiki/WikiAVRentropy
#include <Entropy.h>

const byte MAX_VALUE=11;
boolean RandomDraw[MAX_VALUE];
byte tmp;

void setup() {
Serial.begin(9600);

for (int i=0; i<MAX_VALUE; i++) {
RandomDraw[i] = false;
}

// This routine sets up the watch dog timer with interrupt handler to maintain a
// pool of real entropy for use in sketches. This mechanism is relatively slow
// since it will only produce a little less than two 32-bit random values per
// second.
Entropy.Initialize();

Serial.println("Starting to draw the numbers!");
// This loop will produce the values from 1 to MAX_VALUE in random order,
// with each value only showing up once
for (int i = 1; i<MAX_VALUE; i++) {
// The do loop ensures that the selected value has not been selected before
do {
tmp = Entropy.random(1,MAX_VALUE);
} while (RandomDraw[tmp]);
RandomDraw[tmp] = true;
Serial.print(i);
Serial.print(", ");
Serial.println(tmp);
}
Serial.println("Finished!");
}

void loop() {
}

You can't have "random numbers" which also meets the constraints of 1-90 but only once. The whole point of random numbers is that you can't predict what subsequent values will be. So in your case, after generating 89 numbers, I would be able to predict with 100% accuracy what the 90th number would be!

Nice Idea, but the $100 for the geiger counter part can be done cheaper.

Look on the web for hacking a smoke detector.

They work much the same. They have a small isotope and sensor when smoke particals pass between the two they trigger reaction much like the geiger counter.

A cheaper source of random triggering components. Just make the chamber a bit larger to your liking and tweak the trigger thresholds and your in business. Oh yea, disable the alarm too, its a bit load.

Another approach, put the the isotope aside ( in a metal box, it is radioactive ) and point the sensor to the sun.  The sensor will usually react to the small gama from the sun's rays.

Though I was not looking to make a random numbers generator, about 7 years ago I needed to develop a particulate detector and found that interfacing to the smoke detector turned out to be quite easy and just needed to change the thresholds to my needs.

Hope this can help anyone trying to save a bit to develop on your idea.

5 replies

Mickey,
I think this is actually not the case. The sensor in the Am-241 smoke detectors does not detect individual gammas. It compares the electrical currents through two ionization chambers: one that's open to air versus a sealed one for reference, both irradiated to ionize air in them. Smoke reduces ion mobility in the open one, hence measurable difference in current. Your particle detector from 7 years ago perhaps reacted to ionization current by UV light that affected one chamber more than the other...?
cheers, M

Actually you are both right and wrong.

There are 2 types of smoke detectors out there on the market.
 1.  Ionization based, these are very fast but also cost more
 2. particle based, these though the do use an isotope, they look at a capacitive difference between chambers enough to trigger a response when particles pass into one of the chambers.

you need the second type because they use a radioactive isotope that randomly decays.   

You don't tap the output from the control chip, that would be as you said true.

You want to tap one of the inputs to the control chip so you are getting the decay not the comparison.

By picking up the gamma pulses on the trigger plate you are getting the randomness of the decay itself and not the decision making of the control chip, thus, it's random.

Hope that clears any the difference.



Hi Mickey, thanks for coming back, but this would not be the case.

1. Ionization type is the one with the Am-241 source. Nowhere in the device would there be pulses from detection of individual gammas or individual alphas. The mechanism is that alphas, ionize air and make it conductive. Even with an ideal scope, you would not see pulses because the ions take quite a while to travel to capacitor plates, hence all signal is smeared out to DC current.

2. The other type is called optoelectrical and simply observes light scattering.

I can see that you don't believe me on this topic. Would you take it from another source? http://en.wikipedia.org/wiki/Smoke_detector
Knoll's or Leo's textbooks on radiation detection are also nice.

with kind regards, Matjaz

I've heard of a similar hack but with the isotope placed into a dark box with a cmos camera aimed at it. Each particle that hits the cmos at any given time will show up as a pixel of light. The program interprets each pixel in the camera's resolution as a certain number in a range. Whichever pixel "lights up" is the number chosen at random by the isotope.

Probably not random enough. Some people have apparently tested the TrueRandom library for Arduino, which uses the Analog 0 pin, open, as a noise source.

http://code.google.com/p/tinkerit/wiki/TrueRandom

Problem is, it doesn't pass ANY of the NIST randomness tests, and it should pass all of them. I highly doubt it would pass any of the DieHard tests of randomness, either.

I don't know if that's due to software insufficiency, lack of entropy in the noise in the analog pin (due to digital quantization), or both. A simple avalanche diode setup or noise generator amplified and piped into the analog pin would help with this tremendously.

"TrueRandom does it by setting up a noisy voltage on Analog pin 0, measuring it, and then discarding all but the least significant bit of the measured value."

That sounds dumb. Aren't they just throwing away entropy? When I did a similar program on a micro, the LSB and MSB never changed! I would think the best thing to do is read the ADC, bitshift, read the ADC, XOR with previous measurement, bitshift, read the ADC, etc. for all 8 bits, so that any true randomness on one bit becomes randomness of all bits.

From Wikipedia:

"Problems

It is very easy to misconstruct hardware or software devices which attempt to generate random numbers. Also, most 'break' silently, often producing decreasingly random numbers as they degrade. A physical example might be the rapidly decreasing radioactivity of the smoke detectors mentioned earlier. Failure modes in such devices are plentiful and are complicated, slow, and hard to detect."

:/

Yeah, that's why it's good to constantly sample the randomness stream and test it for quality, as well as do a thorough test every now and then.

I've been gathering data from TrueRandom trying to get enough to run dieharder on it, but then discovered "ent", which works with any size data, and TrueRandom doesn't seem to test very well with even the most basic tests:

https://gist.github.com/2472824

Assuming I did it correctly, it's skewed toward producing lots of 0s and other low numbers.

I'd like to see this test done on the geiger counter version.

I have an idea for a way to get better results out of the Arduino's ADC, though. Need to write it and test it.

Nifty!!

Have you tried building a noise circuit? This is similar to one of the designs I've wanted to build, but have never gotten around to it:

https://mywebspace.wisc.edu/lnmaurer/web/minirng/minirng.html