Random number generator (Part 3)
The early tests presented in this series of posts were dealing with a limited number of data. The risk exist that a long term repeated pattern may not be seen using these statistical tools. Here is an other approach to testing the randomness of data.
It consists in creating a black and white bitmap made out of millions of data points, each of them representing a unique random value. Although the result is a flat image, using gray scale for each cell from the matrix allows a clean and easy 3D graphical representation of these data points. The size of the matrix depends on the range of the random values. If the random values ranges from 1 to 65536 (so as to say 2^16), the matrix shall be squared and each side will be 256 (so as to say 2^8) cells wide. Each time the random number matches a cell, the content of this cell is increased resulting in brighter pixels. The test stops when a cell achieves the maximum brightness.
Here is a sample from multiple tests that I ran using the previously described hardware random generator:
As you can see, this image looks like sand paper without any obvious pattern. Compare it to the next one that I obtained after tweaking the biasing mechanism:
Interesting, isn’t it ?
Ultimately, these are the few lines of code that I used in processing for reading data out of Arduino and plotting random values. Oh! By the way, the random() function gives a very… random bit map too !
import processing.serial.*; Serial myPort; int _plotWidth; int _plotHeight; long _counter = 0; float _maxBright = 0; volatile int _inByte; volatile boolean _readStatus = false; void setup() { /* Set graphics */ size(256, 256); _plotWidth = width; _plotHeight = height; colorMode(RGB, 255); background(0); frameRate(60); /* Set serial port */ String portName = "COM29"; myPort = new Serial(this, portName, 1000000); } void draw() { _counter= 0; _maxBright = 0; clear(); background(0); loadPixels(); while(true) { int data = 0; for (int i = 0; i < 2; i++) { _readStatus = false; while (_readStatus == false); data <<= 8; data |= _inByte; } // data /= 64; /* Get the actual pixel color */ float actColor = red(pixels[data]); float newColor = (actColor + 4.0); /* Record maximum brightness */ if (newColor > _maxBright) { _maxBright = newColor; } /* constrain brightness */ if (newColor > 255.0) { break; } int c = color(newColor); pixels[data] = c; _counter += 1; print(_counter); print(";"); print(data); //print(";"); //print((newColor)); print(";"); print((_maxBright)); println(); } updatePixels(); save("pixels_map.tif"); //delay(2000); while(true); } void serialEvent(Serial myPort) { _inByte = myPort.read(); //myPort.clear(); _readStatus = true; }
This is real raw code, however it does the job nicely and snappy. Note that the bitmap image is recorded in a compressed lossless TIF format so that it could be analyzed after acquisition.
Next is a copy of the code taken from one of the examples prepared for PlainRNG library. Setting the random number generator is plain easy. This code generates unsigned 2 bytes random numbers for ever and matches the processing code as shown above.
/* PlainRNG library, hardware random numbers generator library Copyright (C) 2016 Didier Longueville This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <PlainRNG.h> PlainRNG RNG; const uint8_t _adcPin = 0; void setup() { /* Initialize serial port */ Serial.begin(1000000); /* Initialize analog port */ RNG.InitializeRNG(_adcPin); RNG.Calibrate(32768); } void loop() { uint8_t rn = (RNG.RandomNumber(8, BIA_REM_VON_NEUMANN) & 0xFF); Serial.write(rn); }
Enjoy and keep me posted with your comments.