An STM32 HAL demo of a true random number generation achieved by tapping into thermal noise of resistors, opamps and ADCs.
The Geiger counter, the lavarand or the automatic dice roller are not very practical concepts as far as integrating them into a uC is envisaged to get a built-in RNG peripheral. On the other hand, thermal noise is very practical source of entropy in uC. Let us experiment with that concept by building an external to a uC RNG, which, however, exploits a phenomenon that makes it practical to be integrated into a uC.
Johnson-Nyquist noise (thermal noise, Johnson noise, or Nyquist noise) is the electronic noise generated by the thermal agitation of the charge carriers (usually the electrons) inside an electrical conductor at equilibrium, which happens regardless of any applied voltage. Thermal noise is present in all electrical circuits, and in sensitive electronic equipment (such as radio receivers) can drown out weak signals, and can be the limiting factor on sensitivity of electrical measuring instruments.
This electronic noise is usually something we want to get rid off (precisely speaking, to reduce) in our circuits. However, there are scenarios in which such a noise can be exploited to our benefit. One of them is obtaining truly/hardware random numbers. What we need is to "measure" that noise, i.e. to get a digital signal effectively affected by the thermal noise. Check e.g. "A true random number generator that utilizes thermal noise in a programmable system-on-chip (PSoC)" by Shunsuke Matsuoka, Shuichi Ichikawa, and Naoki Fujieda for some calculations. We are in the realm of uV, therefore an opamp and a high-resolution ADC will be helpful here. And the more noisy they are themselves, the better, so you don't have to go for high-end devices.
HX711 suits our experiment as it offers the 24-bit resolution and the 128x PGA (programmable gain amplifier1). The evaluation board can be easily bought under $2. Note the filtering capacitor removed from the board - the more noisy measurement, the better. Select 80 SPS output data rate to reduce waiting time for 1 million bits for NIST testing.
My setup includes two grounded 4 MOhm resistors (4x 1 Mohm) connected to the differential inputs INA- and INA+ of the HX711 chip. The channel A is chosen to take advantage of its 128x PGA. The 1 W resistor is there to make the adjacent resistors more noisy - the variance goes up with the temperature.
Tip
Select carbon composition or thick film resistors to increase thermal noise2.
Tip
If you are interested in more scenarios in which making a system less deterministic3 can be beneficial, check e.g. spread-spectrum frequency dithering4567.
Don't worry 🙂 Just hit Alt-K to generate /Drivers/CMCIS/ and /Drivers/STM32G4xx_HAL_Driver/ based on the .ioc file. After a couple of seconds your project will be ready for building.
- USB to UART converter (Waveshare) - just for the convenience of having two separate COM ports: one for debugging messages and the other one for streaming random bits to the computer for their statistical evaluation.
In this example I deployed probably the easiest randomness extractor in the form of a parity bit calculator:
if (__builtin_parity(adc_reading))
{
uint8_t bit1 = '1';
HAL_UART_Transmit(RNG_STREAM_UART, &bit1, 1, 10);
}
else
{
uint8_t bit0 = '0';
HAL_UART_Transmit(RNG_STREAM_UART, &bit0, 1, 10);
}
It's probably a waste of entropy harvested by the 24-bit ADC augmented with the 128x PGA. Sorry for that. Do it better!
Writing a README.md helps me a lot in finding new ideas to be put into the test. The "RFC" (request for comments)8 process and the readme driven development (RDD)9 resonate with me strongly. You should definitely try them even in your hobby projects. I've just realized that I should implement one more entropy extractor (more efficient one) and leave it for you to test. Fingers crossed 🙂
Entropy extractor 2 (potentially too biased - use von Neumann's strategy to get an unbiased bitstream)
for (uint8_t i = 0; i < NUMBER_OF_LSB; i++)
{
if (((adc_reading >> i) & 0x00000001) == 1)
{
uint8_t bit1 = '1';
HAL_UART_Transmit(RNG_STREAM_UART, &bit1, 1, 10);
}
else
{
uint8_t bit0 = '0';
HAL_UART_Transmit(RNG_STREAM_UART, &bit0, 1, 10);
}
}
My preliminary tests for #define NUMBER_OF_LSB 4
give some hope. However, the 4-bit approach consistently fails the runs test. Maybe I should try another test suite implementation1011.
Try to harness electromagnetic pollution around us. Connect an antenna to one of the resistors. For starters use a 50+ cm long wire flapping in the breeze. Note orders of magnitude higher HISTOGRAM_OFFSET
and HISTOGRAM_BAR_WIDTH
presets for this scenario. Check the distribution. Still Gaussian (bell-shaped) one? No? Why? Experiment with bringing the antenna closer to an electronic equipment powered from the mains. How do your actions affect randomness test results? Is it always beneficial to seek a signal characterized by a higher variance? Let me invite you for a thought experiment. Consider a discrete random variable that can take only two values (two distinct ADC readings). You can get any variance you want by separating these values with a high enough distance (remember, it's a thought experiment). And now apply the first of the above-mentioned entropy extractors. Is it bound to fail? Probably the safest answer is that it depends 🙂 But it depends on what?
Create your own home laboratory/workshop/garage! Get inspired by ControllersTech, DroneBot Workshop, Andreas Spiess, GreatScott!, ElectroBOOM, Phil's Lab, atomic14, That Project, Paul McWhorter, Max Imagination, and many other professional hobbyists sharing their awesome projects and tutorials! Shout-out/kudos to all of them!
Warning
Mathematics, electronics and embedded systems - do try this at home ❗
190+ challenges to start from: Control Engineering for Hobbyists at the Warsaw University of Technology.
Stay tuned!
Footnotes
-
Manual Gain Setting For Op Amp using Digital Potentiometer (Gadget Reboot) ↩
-
Yeah, I know, there are just two categories, deterministic XOR non-deterministic (stochastic), an trying to gradate them is a risky business ⛔ And yes, I know that non-deterministic and stochastic are not synonyms but in mathematics and computer science they are largely synonymous terms. ↩
-
Utilizing Dual-Random Spread Spectrum to improve EMI performance (Texas Instruments) ↩
-
Spread spectrum (Wikipedia) ↩
-
Demonstration firmware for PWM resolution enhancement through dithering technique software expansion for STM32Cube (AN4507) (ST) ↩
-
RM0456: Reference manual: STM32U5 Series Arm-based 32-bit MCUs (search for: dithering) ↩
-
Rust RFCs - RFC Book - Active RFC List (GitHub) ↩
-
Readme Driven Development (GitHub) and Readme Driven Development (RDD) (LoneStar Agile) ↩
-
sp800_22_tests (David Johnston) ↩