8 years, 5 months ago.

Random number in C.

Using rand() function does not give me random number. If i reset the board, it will always return me the same number. Putting srand(time(NULL)) did not help. Is there any way to get random number?

Question relating to:

STUDENTS Team School of Computing Electronics and Mathematics Plymouth University UK

5 Answers

8 years, 5 months ago.

Hello,

STM32F4xx devices have a true random generator :-)

http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00073853.pdf?s_searchtype=keyword

Unfortunately, STM32f4 that are in Nucleos do not have these nice periphery. :(

posted by Nothing Special 12 Oct 2015
8 years, 5 months ago.

It would be nice if there was an mbed random function (or the C one being somehow overloaded, which should be possible I guess), which depending on the chip would use for example a hardware random number generator.

For your chip, I think adding your Time(NULL) doesn't work because the RTC is also reset when you reset the chip, so it always returns zero. But if you switch to latest mbed lib (or mbed-src, dunno if it is in mbed yet), I believe the RTC is not reset anymore upon a chip reset, so then it might properly seed your random number. Alternatively you can do a bunch of AD conversion for example, and use the noise from the LSB.

8 years, 5 months ago.

If you have a analog input free, you could use the code below to generate a random number.

It uses the two least significant bits of the analog signal to create a random number. You have to leave the analog pin unconnected. And I can tell you, it won't start every time at the same number ;)

AnalogIn analog (p20);
 
unsigned int random_generator (void)
{
    unsigned int x = 0;
    unsigned int iRandom = 0;
    
    
    
    for (x = 0; x <= 32; x += 2)
    {
        iRandom += ((analog.read_u16() % 3) << x);
        wait_us (10);
    }
    
    return iRandom;
}

Personally I'd use use that method to generate a single random number on startup and use that value to seed the normal c random number generator.

Reading analog inputs may be random but it's also very slow, once the random number generator has been seeded it should work fine.

posted by Andy A 12 Oct 2015
8 years, 5 months ago.

Andy is correct. Try this in MBED:

int a = rand();

It may not be the best random number generator (I would need to check), but it should suffice for most purposes. The time you need to be very careful is if you are writing a cryptography algorithm.

An ADC would be *very* slow in comparison and possibly not random.

It would be more random than an unseeded random number generator. At the very least you need something to seed it with something random.

posted by Erik - 20 Oct 2015

It depends on what you connect to the ADC of course. A white noise generator I accept would be the ideal, but you will have the performance hit of performing an ADC.

posted by Nicholas Outram 20 Oct 2015

Just about any ADC will have some noise on the least significant bit or two unless the inputs are tightly clamped to one of the rails.

Lets say that with a floating input the ADC you have a 90% chance of getting 0 and a 10% chance of getting a 1 on the LSB (I'd expect it to be closer to 50-50) then I make it about 10,000 possible values you could get by using 32 ADC reads. (crude back of the envelope number assuming you get 3 1's, it will be more random than that)

If you use that as your seed for the rand function then you're going to get a fairly random result.

If you need more randomness generate a second number from the ADC and xor the two together, that should roughly square the number of permutations. Repeat (with diminishing returns) until you reach the randomness required. The lower the probability of getting a 1 the more loops needed for a given level of randomness.

mbed will normalize the ADC output to 16 bits but as long as we wrap things around when we do a shift we don't need to know where the LSB is and so it remains hardware independent.

Untested (and uncompiled) code to perform an ADC size independent seed of the random number generator.

AnalogIn noise(pin something);

uint32_t seed =0;
const int loops = 1; // increase if LSB has a bias. 

for (int i=0;i<(32*loops);i++) {
  seed ^= noise.read_u16();
  if (seed & 1<31) { // shift left and wrap.
    seed <<= 1;
    seed |= 1;
  } else
    seed <<= 1;
}
srand(seed);
posted by Andy A 20 Oct 2015