To use, just run it for your Arduino – I’m very curious if everyone else has this very narrow range of values.

Now this list is decidedly not random, especially since this port should return a value from 0-1023, or 10 bits of information.

But the hardware isn’t the problem – after all, it’s not made to be random, just a useful side effect of the design. So what we need to do is figure out how to make this side effect work for us – and get real random values.

In a nutshell, I decided to use the change between values – if the next number from analogRead() was different from the previous one, I counted it as a single ‘1’, and if no change, I’d count it as a ‘0’.

So looking at the previous values, I’d get a series of bits as they change:

However, that isn’t quite random enough – notice the ratio of ones to zeroes (30 zeroes and 65 ones). While the input seems random enough, it’s seriously biased, and I needed to unbias it.

Fortunately, the solution is easy: Von Neuman had a simple way of removing random bit bias by “casting off” extra bits. Basically, you take pairs of random bits. If they are identical, you throw them away. If not, then the first bit is used for the final result. Do it often enough, and your bits are biased properly, with more or less even amounts of ones and zeroes (but not too even of course, since even that should be random!)

The code shows how to use the two functions, bitOut() and seedOut(), which contain all the details of bit handling. Add them to your code, and then call seedOut() to get a random number back. You can use this number directly, or as a seed value via randomSeed(). You call it with the number of bits you want in your result, and it returns them. I’d recommend no more than 31, since 32 bits can cause strange results if you’re not expecting it (in C, this is a sign bit and could make the number negative if you aren’t familiar with C/C++ casting rules). However, even if you use 15 for the value, that’s 32,768 possible start positions for random numbers.

As you can imagine, using only one bit per reading, and then throwing away many bit pairs to unbias the values can use a LOT of cycles. In my tests, it’s at least 10:1 – 10 port readings to get one usable bit. So you’re better off using these routines once to get your seed value, using randomSeed(), and then letting the random() function get all the rest of your numbers.

The value in bitOut() called limit keeps the loop from running forever. What it does is limit the number of bit pairs thrown out per sample. Making it low makes the routine run faster, but risks the bias creeping back in. Raising it higher can slow the program down. I found 99 worked well, but as a rough guide, 10 is at the lower end (faster, but more bias), while 1000 is at the upper end (slower, but less bias). However, don’t be tempted to take the limit out: if for example the port always returned the same number (say, because of something connected to it), then you’d stay in an infinite loop.

Feel free to use the code, and I’d like to hear how it helps your projects!

Note: an update with more (and simpler) code is available on this post.

4 thoughts on “Fixing The Randomness ‘Bug’ In randomSeed() For The Arduino”

Many thanks to you ..very useful.. My project was to get two servos for robot neck and two on-off switch for eye blink and eyeballs horizontal movement all obtained randomly…sadly when I duplicated the code w different integer names..it did not work.. Any advice plz ?

Great idea, but I found another way around the lack of randomness from analogRead() – Simply attach 8 inches or so of cable to the analogue port which acts as an antenna and gives much more “randomness”. Before this, like you, I saw numbers returned +/-10 or so