Have you ever needed to generate random numbers with ESP32? then this post is for you. I have once again asked ChatGPT for help with Arduino coding. It helped me create a sketch that generates TRNG (true random numbers generator) using all of ESP32 -C3 and -C6 capabilities.
I have always been programming my ESP32’s using Arduino code and Arduino IDE, it would not be different this time. It features a function that generates PSEUDO random numbers, called
random(min, max) But those are really not random, so for more critical applications they would not do the job. I have used it before in this blog post, if you want to have a look. In that opportunity I blinked some LEDs with random().
Changing subject back to the meat and juice of this post. If you came after the code for a true random number generator TRNG, there you go. Enjoy, It is also in my Github.
#include <esp_system.h> // Required for esp_random() #include <WiFi.h> // Necessary to generate TRNG // Returns a random number in the range [0, bound) // Avoids modulo bias using rejection sampling uint32_t randomBounded(uint32_t bound) { if (bound == 0) return 0; // avoid division by zero uint32_t x; uint32_t limit = UINT32_MAX - (UINT32_MAX % bound); do { x = esp_random(); } while (x >= limit); // Retry until unbiased return x % bound; } // Returns a random number in the range [minVal, maxVal) uint32_t randomRange(uint32_t minVal, uint32_t maxVal) { if (maxVal <= minVal) return minVal; return minVal + randomBounded(maxVal - minVal); } void setup() { WiFi.mode(WIFI_MODE_STA); // or WIFI_STA WiFi.begin(); // starts WiFi driver (no need to connect) // Optional: immediately stop scanning/connecting attempts WiFi.disconnect(true); Serial.begin(115200); Serial.println("ESP32-C3/C6 True Random Example (Unbiased)"); } void loop() { // Example: number from 0 to 100 (inclusive) uint32_t r = randomRange(0, 101); //Serial.print("Random 0–100: "); Serial.println(r); delay(1000); } The code
The code is available here, as stated above. There are a few important things happening in that code. Most of the official information about the TRNG module of ESP32 came from here. That serves specifically for ESP32-C6 and is being tested in this article for ESP32-C3.

The first and foremost important feature of this code is that the WiFi module is enabled. It is not being used to fetch any information from the internet, it is just turn on as hardware feature. This is necessary since the TRNG module uses it for entropy. That means that non-linearities from the WiFi module itself are part of the random number generator.
This piece of code goes into the setup() part and enable the WiFi for us. You can see that the module is started with begin() then immediately disconnected(true). It guarantees that the module is ON but without any internet traffic.
WiFi.mode(WIFI_MODE_STA); // or WIFI_STA WiFi.begin(); // starts WiFi driver (no need to connect) // Optional: immediately stop scanning/connecting attempts WiFi.disconnect(true); Then in the loop() we have got a simple special function to ask for a new random number. It is limited in range by the number between the braces:
uint32_t r = randomRange(0, 101); The line above essentially calls the function randomRange(min, max) and passes that it wants back one number. It will be limited between 0 and 100, since “min” is inclusive and “max” is exclusive. Inside randomRange() there is the call for
x = esp_random(); Which actually does the magic for us. It will in fact return a 32-bit integer number, so between 0 and 4,294,967,295. Since most applications will not require such a wide range, we can and will limit this range to our will. I have decided to limit my generated number between 0 and 100, just for fun.
The rest of the code inside randomRange() takes care of the quality of the division that happens. This is since you have to divide the 2^32 integer by some number to obtain a 0-100 response. That also takes the module functions, hence all the math and functions inside randomRange().
Hardware
Not all ESP microcontrollers line feature true random number generator (TRNG) modules. Only the original ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6, and ESP32-P4. I have an ESP32-C3 super mini in hand at the moment, so I will use it. I have devised a development board for it, featuring all its pins in a single row.
That is perfect for breadboard, as you can see in the image below. This specific board I made also features one Neopixel LED (WS2812), one push button and a NTC analog temperature sensor. I have previously made a bunch of project using it, enjoy.

That form factor I devised allows for a single pin to be accessible via four breadboard holes. You can see in the image below that the board is connected to hole “a”, while its pins become availables in holes “b”, “c”, “d” and “e”. Besides an ESP32 microcontroller compatible with TRNG, we will not use any other hardware in this project.
It means not LEDs, no resitors, no buttons, no anything. Not even that breadboard is necessary, just the microcontroller itself and you are good to go.
Testing and modifications
I will show you two different outcomes for this code. One is generating number betwenn zero and one hunder and the other will be between one and six. So effectively we will create an electronic dice with true random numbers. For that, all you have to do is change this single line on the loop()
uint32_t r = randomRange(0, 101); from (0, 101) to (1, 7):
uint32_t r = randomRange(1, 7); There you go, now you have a fully random dice in your hands. It will serve to impress your friends and family; you could even make that into a fully marketable product. Image below shows the Arduino IDE’s serial plot function. It is plotting numbers betwee zero and one hundred:

I have modified the code slightly to print number every 100ms and in this format: x, x, x, x, x. Then generated a sequence of 210 of them and submitted to ChatGPT for analysis. It returned that my numbers are actually looking like random. For good measure I did the same with the random() function of Arduino, still using my ESP32.
void setup() { // put your setup code here, to run once: Serial.begin(115200); } void loop() { // put your main code here, to run repeatedly: int number = random(0, 101); String numberPrint = String(number) + ", "; Serial.print(numberPrint); delay(100); } It returned that the Arduino basic function random() actually produces fairly random numbers as well. For such a short list (around 200 entries) it is not possible to really evaluate anything. We would need a huge data set for a real analysis. But the fact that my TRNG code LOOKS random is already a win, at least it is not visibly biased.
Dice code
For good measure and to finish this article, I will run my TRNG code with a limit of
uint32_t r = randomRange(1, 7); So that it imitates a real world dice. Here is the Arduino IDE’s serial plotter screen of it:

Also seems fairly random to me, no patterns recognizable. Video about it is in the beginning of the article. That concludes our studies for today. If you want to buy the ESP32-C3 Super mini I used here today, click here. See you guys in the next posts.