Electronic – How to get random numbers on AVR

random number

I will try to make the game MegaMind. I need to get a random number, but how can I get these?

I have tried something:

secret_code[1] = random()&=6;

Best Answer

Random Numbers and Computers

Let us talk a second about what it takes to generate random numbers.

Randomness is very easy for humans to imagine or produce: Flip a coin. The result is random. The next time you flip the same coin, it will be random again, and there will be no correlation to the previous coin-flips.

That's way harder for processors. These are machines to be as deterministic as possible. Generally, when you build a digital circuit, any non-determinism ("random behaviour") is undesired.

In that framework, i.e. if your digital circuit (e.g. an AVR) works perfectly deterministically, then there's simply no way to generate truly random numbers. These numbers must always be a result of some calculation on numbers that were there before, so that there can only be a "seemingly" random sequence of numbers.
The next time you feed the same algorithm with the same "inital input", you get the same sequence of numbers. We call an algorithm that generates a seemingly random numbers a pseudo-random number generator (PRNG).

But that is practically always (aside from cryptography) an acceptable solution. There's typically a large numbers of initial states, and if the PRNG is any good, any of these initial states will yield a totally different, totally uncorrelated, totally fairly distributed sequence of numbers.

Pseudo-random number generation on microcontrollers in practice

On a microcontroller, you don't want to use a function like rand or srand with a hidden global state of a single pseudo random number generator (PRNG) - that is a waste of the little RAM you have, if you at some point can stop using the PRNG, and a recipe for disaster if you're interacting with the PRNG from interrupt routines.

Instead, use a "slim" random number generator function that takes and modifies an explicit, small state. The AVR stdlib possibly offers rand_r, but that's just a bad random number generator; with the same effort in state space and computation, you can get much "randomer" numbers.

For medium-to-high-quality PRNG, I personally use my state-external variant of the XOROSHIRO128+ algorithm. It requires 16B of state memory, and is probably far over the top for a microcontroller-based game.
The XORSHIFT32 algorithm, that XOROSHIRO128+ is indirectly based on, only uses four bytes of state, and should be plenty random for your use case, and will return one 32bit random number each call, and modify the state. If you look at it, it's also pretty fast – just three shifts and three XORs on 32 bit numbers. While your AVR (assuming it's not AVR32) doesn't have 32 bit integers (I think), these operations should still be faster than at least what the glibc implementation of rand() does.

Seeding your PRNG

The real question is how to initialize the state (seed the PRNG). That seed determines the only seemingly random sequence of numbers that you'll get!

That is especially challenging on a small device like an AVR: You can't use something like the current time (which was always a bad seed, but someone started telling people it's good one :(, so people use that), because it has no notion of time; you can't use physically random things like the seek time of your hard drive, because there is no hard drive, and so on.

But: your microcontroller has an ADC, for example. So, simply get a series of ADC measurements and use the least significant bits, which should essentially be noise, to generate the initial state that you use for your PRNG. Maybe take an ADC measurement, XOR with the last measurement, shift up, take the next measurement, repeat 16 times, use that as initial state.