[{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/723/original/PXL_20250323_171223313.jpg?1742749994","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eI've long had an interest in random number generation. In fact, a very early PCB I designed and built was exactly for this purpose: \u003ca href=\"https://emergent.unpythonic.net/01257868826\"\u003eArduino Random Number Generator\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eThat project used a property of transistors called \"avalanche noise\". Inconveniently, it required a supply of +-10V to work properly. Avalanche noise is sometimes explained as being a \"quantum effect\" and thus is supposed to be a source of true randomness.\u003c/p\u003e\n\u003cp\u003eWhen the TPS65131 went into the store, I knew it was time to revisit this project. This little PCB generates positive and negative voltages from a single +5V input.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/719/original/MSO1104Z_2025-03-23_11.26.51.png?1742747416","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2\u003eParts\u003c/h2\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eYou can choose almost any microcontroller for this project. I used the Metro ESP32-S3 because it was on my desk and because CircuitPython supports\u0026nbsp;\u003ccode\u003eanalogbufio\u003c/code\u003e, which allows efficiently reading many analog samples quickly.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/5500","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/6280","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/756","metadata":{}},{"element_type":"parts","content":"\n  \u003cdiv class=\"parts-details\"\u003e\n    \u003cdiv\u003e\n      \u003cspan class=\"parts-quantity\"\u003e3\u003c/span\u003e\u003cspan\u003e x \u003c/span\u003e\n        \u003cspan class=\"parts-name\"\u003eAssorted resistors\u003c/span\u003e\n      \u003cdiv class=\"parts-description\"\u003eThrough hole resistors 4.7k (x2) \u0026amp; 1M (x1)\u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"parts-action\"\u003e\n  \u003cdiv\u003e\n\n  \u003c/div\u003e\n\u003c/div\u003e\n\n  \u003cdiv class=\"clearfix\"\u003e\u003c/div\u003e\n","metadata":{"name":"Assorted resistors","url":null,"description":"Through hole resistors 4.7k (x2) \u0026amp; 1M (x1)","quantity":"3"}},{"element_type":"parts","content":"\n  \u003cdiv class=\"parts-details\"\u003e\n    \u003cdiv\u003e\n      \u003cspan class=\"parts-quantity\"\u003e1\u003c/span\u003e\u003cspan\u003e x \u003c/span\u003e\n        \u003cspan class=\"parts-name\"\u003eCeramic Capacitor\u003c/span\u003e\n      \u003cdiv class=\"parts-description\"\u003e0.1uf, 12V (\"104\" marking)\u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"parts-action\"\u003e\n  \u003cdiv\u003e\n\n  \u003c/div\u003e\n\u003c/div\u003e\n\n  \u003cdiv class=\"clearfix\"\u003e\u003c/div\u003e\n","metadata":{"name":"Ceramic Capacitor","url":null,"description":"0.1uf, 12V (\"104\" marking)","quantity":"1"}},{"element_type":"text","content":"\n  \n        \u003ch2\u003eBuild the Random Number Generator\u003c/h2\u003e\n\u003cp\u003eFollow the schematic or breadboard wiring plans. Note how the \"Q1\" transistor is not pointing the same way as the others, and one of its terminals isn't even connected. A transistor that is \"reverse biased\" like this can be used as a source of physical noise that is inherently unpredictable. \u003ca href=\"http://robseward.com/misc/RNG2/#performance\"\u003eRob Seward's write-up\u003c/a\u003e has been on the internet for a very long time and remains my reference on this topic.\u003c/p\u003e\n\u003cp\u003eTransistors Q2 and Q3 amplify the very small amount of noise produced by Q1, ultimately producing a signal that goes to a microcontroller.\u003c/p\u003e\n      \n","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/720/original/rng-avalanche_bb.png?1742748154","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/721/original/rng-avalanche_schem.png?1742748186","metadata":{}},{"element_type":"text","content":"\n        \u003cp\u003e\u003cstrong\u003eNote on component damage\u003c/strong\u003e: Transistor Q1 is operated in a non-standard mode that can permanently affect its properties, as brought to my attention by graham on discord: 'Any transistor that has been operated in base-emitter avalanche mode should not be used as a regular transistor afterwards. Operation in base-emitter avalanche causes the gain of the transistor to drop permanently, and it may no longer meet specifications. The circuit works as you describe, but the transistor in avalanche changes permanently. You can search the internet for something like \"Current gain degradation induced by emitter-base avalanche breakdown in silicon transistors.\"'\u003c/p\u003e\n\u003cp\u003eThe figure below is from the cited paper. Note that in the circuit shown here the emitter-base current is up to about 5mA, based on the 4.7k resistance and +-12V supply rails.\u003c/p\u003e\n      ","metadata":{}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/737/original/Screenshot_2025-03-31_18-06-18.png?1743462402","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2\u003eConnecting to a microcontroller\u003c/h2\u003e\n\u003cp\u003eDepending on your needs, you can access the randomness as digital or analog data.\u003c/p\u003e\n\u003cp\u003eOn the Metro ESP32-S3 with CircuitPython, make these connections (it's similar for other microcontrollers):\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eConnect\u0026nbsp;\u003cstrong\u003e3v3\u003c/strong\u003e where the schematic calls out \u003cstrong\u003e5V\u003c/strong\u003e (use the I/O voltage of your microcontroller)\u003c/li\u003e\n\u003cli\u003eConnect\u0026nbsp;\u003cstrong\u003eGND\u003c/strong\u003e to\u0026nbsp;\u003cstrong\u003eGND\u003c/strong\u003e\n\u003c/li\u003e\n\u003cli\u003eConnect the circuit \u003cstrong\u003eoutput\u003c/strong\u003e (Collector of Q3) to pin\u0026nbsp;\u003cstrong\u003eA5\u003c/strong\u003e (or choose any other input pin according to your needs; On the ESP32-S3, pin\u0026nbsp;\u003cstrong\u003eA5\u003c/strong\u003e is capable of both use as a digital pin and also as a high speed analog capture pin)\u003cbr\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u0026nbsp;\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2\u003eGrabbing random analog values in CircuitPython\u003c/h2\u003e\n\u003cp\u003eThe\u0026nbsp;\u003cstrong\u003eanalogbufio\u003c/strong\u003e module in CircuitPython allows grabbing analog data at a given sample rate. Here's how to grab 256 random analog values at once.\u003c/p\u003e\n\u003cp\u003eA plot of the data will show that while it is unpredictable, it is \u003cstrong\u003ebiased\u003c/strong\u003e, with more values occurring in the center of the range. It is probably also \u003cstrong\u003ecorrelated\u003c/strong\u003e, meaning that adjacent samples are more likely to be close in value. This pattern, if it exists, is much harder to see here. However, it is obvious in the very top image of a high speed oscilloscope capture.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"code","content":"import board\nimport analogbufio\nimport array\nbuf = array.array('H', [0]) * 256\naio = analogbufio.BufferedIn(board.A5, 83333)\naio.readinto(buf)\nprint(buf)","metadata":{"language":"auto","linenums":false}},{"element_type":"code","content":"array('H', [0, 25029, 33991, 12258, 17876, 35032, 41689, 26454, 40793, 33207,\n40585, 18036, 11922, 17956, 15731, 37096, 26982, 43017, 37560, 31175, 27926,\n…, 43001, 19300, 12994, 22133])","metadata":{"language":"terminal","linenums":false}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/722/original/analog-randomness.png?1742748822","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2\u003eGrabbing random digital values with CircuitPython\u003c/h2\u003e\n\u003cp\u003eIt's possible to use the\u0026nbsp;\u003cstrong\u003eSPI\u003c/strong\u003e peripheral to capture digital values at high speed. This works across a wide range of microcontrollers, with the caveat that an unused pin has to be available to be used as the clock or SCK signal.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"code","content":"import array\nimport board\nimport busio\nspi = busio.SPI(SCK=board.A0, MISO=board.A5, baudrate=10_000_000)\nspi.try_lock()\na.readinto(buf)\na.unlock()\nprint(\"\".join(f\"{bi:016b}\" for bi in buf))","metadata":{"language":"python","linenums":false}},{"element_type":"code","content":"'11000111101100100111110111000000111111110111001100001001110111101001111\n111110111111111111111111110011110111110111101011111011111001111111111000\n011111111100111111111111111111111110000111100001111111001111111111111111\n110000111111011111011111011111111101001101100000111100111010000001011000\n011001111111011110000000011110110111111110011101110000111000001111111111\n…1101011100011000111111100111111101001111000111111001110011101001000010'","metadata":{"language":"terminal","linenums":false}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eHere, the effect of correlation is much more apparent: a \"1\" is very likely to be followed by a \"1\", and a \"0\" by another \"0\". For digital values it's easy to count the frequency of different 1-bit and 2-bit outcomes:\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"code","content":"\u003e\u003e\u003e s.count('0')\n1502\n\u003e\u003e\u003e s.count('1')\n2594\n\u003e\u003e\u003e s.count('00')\n566\n\u003e\u003e\u003e s.count('01')\n578\n\u003e\u003e\u003e s.count('10')\n578\n\u003e\u003e\u003e s.count('11')\n1122","metadata":{"language":"python","linenums":false}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eOn the whole, \"1\"s are much more plentiful than \"0\"s; \"11\" is twice as common as any of \"00\", \"01\", and \"10\". And, contrary to my intuition, \"00\" is about as common as either \"01\" or \"10\", meaning that runs of zeros are not actually excessively frequent despite what I think I see in the above data \"by eye\".\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2\u003e\"Whitening\" data\u003c/h2\u003e\n\u003cp\u003eMy \u003ca href=\"https://adafruit-playground.com/u/jepler/pages/circuitpython-ring-oscillator-rng-with-sn74ahct14#using-a-cryptographic-hash-to-mix-random-data-3189461\"\u003eprevious RNG article\u003c/a\u003e describes how to use the sha1 hash to convert a biased \u0026amp; correlated stream into a fully unpredictable stream of bytes.\u003c/p\u003e\n\u003ch2\u003eClosing remarks\u003c/h2\u003e\n\u003cp\u003eYou probably shouldn't use a homemade random number generator for anything of consequence. That doesn't mean it's not interesting to build one, to see that it works, \u0026amp; to try to understand the theoretical basis of why it works.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n","metadata":{}}]