Go Down

### Topic: Problem reading random noise generator (Read 11867 times)previous topic - next topic

#### acegard

#45
##### Jun 04, 2014, 11:50 pm

I am very fond of the debugging approach of throwing away the parts of code that aren't working for me, and either recoding from scratch or even better trying a different approach/algorithm.

Me too! I have rewritten and refactored this sketch four or five times since the inception of the project. I have since layered XOR whitening on top of the Von Neumann, and am currently implementing the Jenkins hash you provided. It's making the 0-255 distribution improve each time, but not the mapped distribution, which remains pretty terrible. I would be surprised if it's something in your algorithm, because I've seen the vast and corroborated results of your tests.

#### wanderson

#46
##### Jun 05, 2014, 12:25 am
Ok, I have collected about 75,000 numbers from 0-19, using my original library code.  Looks like the algorithm itself is working (chi sq of 29.9283, p-value of 0.05272, so when I get finished playing with my new 3D printer that just arrived I will look at seeing what is wrong with your code in a day or two!

Code: [Select]

> library(foreign)
> tmp <- tmp\$X3
> cb <- table(tmp)
> pb <- rep(1/20,20)
> cb <- as.integer(cb)
> chisq.test(cb, p = pb)

Chi-squared test for given probabilities

data:  cb
X-squared = 29.9283, df = 19, p-value = 0.05272

> length(tmp)
[1] 73958
> sum(cb)
[1] 73958
>

#### acegard

#47
##### Jun 05, 2014, 12:49 am

Ok, I have collected about 75,000 numbers from 0-19, using my original library code.  Looks like the algorithm itself is working (chi sq of 29.9283, p-value of 0.05272, so when I get finished playing with my new 3D printer that just arrived I will look at seeing what is wrong with your code in a day or two!

Great! Have fun with the printer! I'll keep posting things as I run tests or figure out what is wrong.

#### acegard

#48
##### Jun 07, 2014, 09:26 pm
After some days of tinkering with my code, I am pleased to say that I think I have reached an acceptable level of randomness in the mapped values!
I implemented your suggestion to limit bit-length and toss out any number greater than my maximum required value, and it seems to work well. The map20() method I used which was based on your algorithm does not work, and I can't figure out why, but this method does seem to.

Thank you very much for your help! If you have any other input or notes for me, I would be glad to hear them.

Code: [Select]

#define BINS_SIZE 256
#define CALIBRATE_SIZE 10000

#define NO_BIAS_REMOVAL 0
#define EXCLUSIVE_OR 1
#define VON_NEUMANN 2

#define ASCII_BYTE 0
#define BINARY 1
#define ASCII_BOOL 2

#define BYTE_LENGTH 8
#define LONG_NIBBLE_LENGTH 5
#define NIBBLE_LENGTH 4
#define TWO_BIT_LENGTH 2
#define COIN_FLIP 1

#define MAP_MAX 20

#define LED_PIN 13

/***  Configure the RNG **************/
int bias_removal = VON_NEUMANN;
boolean TWO_LEVEL_WHITENING = true;
int output_format = ASCII_BOOL;
int max_length = LONG_NIBBLE_LENGTH;
boolean mapResults = true;
unsigned long maxSamples = 500000;
int baud_rate = 19200;
/*************************************/

unsigned int Bins[BINS_SIZE];
unsigned int Results[MAP_MAX];
boolean initializing = true;
unsigned int calibration_counter = 0;

boolean bufferFull = false;
byte buffer = 0;
byte threshold = 0;

unsigned long samples = 0;

void setup(){
pinMode(LED_PIN, OUTPUT);
Serial.begin(baud_rate);
for (int i=0; i < BINS_SIZE; i++){
Bins[i] = 0;
}
for (int i=0; i < MAP_MAX; i++){
Results[i] = 0;
}

analogReference(EXTERNAL);
}

void loop(){

Serial.println("Initializing...");
Serial.println("Calibrating...");
threshold = calibrate();
Serial.print("Threshold: ");
Serial.println(threshold);
delay(2000);
Serial.println("Collecting Data");
for (int i=0; i < BINS_SIZE; i++){
Bins[i] = 0;
}
while(samples < maxSamples)
{
byte rand = getRandomByte(threshold);
if(mapResults)
{
if(rand < MAP_MAX)
{
Results[rand]++;
samples++;
Serial.print(samples);Serial.print(": ");Serial.println(rand);
}
}
else
{
Bins[rand]++;
samples++;
Serial.print(samples);Serial.print(": ");Serial.println(rand);
}

}

Serial.println("Distribution:");
for (int i=0; i < BINS_SIZE; i++){
Serial.print(i);
Serial.print(": ");
Serial.println(Bins[i]);
}
for (int i=0; i < 20; i++){
Serial.print(i);
Serial.print(": ");
Serial.println(Results[i]);
}
while(true){
}
}

byte getRandomByte(byte tHold)
{
while(!bufferFull)
{
}
bufferFull = false;
return buffer;
}

boolean input_bool;
input_bool = (adc_byte < threshold) ? 1 : 0;
switch(bias_removal){
case VON_NEUMANN:
vonNeumann(input_bool);
break;
case EXCLUSIVE_OR:
exclusiveOr(input_bool);
break;
case NO_BIAS_REMOVAL:
buildByte(input_bool);
break;
}
}

void exclusiveOr(byte input){
static boolean flip_flop = 0;
flip_flop = !flip_flop;
buildByte(flip_flop ^ input);
}

void vonNeumann(byte input){
static int count = 1;
static boolean previous = 0;
static boolean flip_flop = 0;

flip_flop = !flip_flop;

if(flip_flop){
if(input == 1 && previous == 0){
if(TWO_LEVEL_WHITENING)
exclusiveOr(0);
else
buildByte(0);
}
else if (input == 0 && previous == 1){
if(TWO_LEVEL_WHITENING)
exclusiveOr(1);
else
buildByte(1);
}
}
previous = input;
}

void buildByte(boolean input){
static int byte_counter = 0;
static byte out = 0;

if (input == 1){
out = (out << 1) | 0x01;
}
else{
out = (out << 1);
}
byte_counter++;
byte_counter %= max_length;
if(byte_counter == 0){
buffer = out;
bufferFull = true;
out = 0;
return;
}
bufferFull = false;
}

unsigned int calibrate()
{
digitalWrite(LED_PIN,HIGH);
for(int i = 0; i < CALIBRATE_SIZE; i++)
{
byte analog = adc_value >>2;//truncates to 0-255
Bins[analog]++;
}

//find the median
unsigned long half;
unsigned long total = 0;
int i;

for(i=0; i < 256; i++){
total += Bins[i];
}

half = total >> 1;
total = 0;
for(i=0; i < 256; i++){
total += Bins[i];
if(total > half){
break;
}
}
digitalWrite(LED_PIN,LOW);
return i;
}

#### wanderson

#49
##### Jun 07, 2014, 09:36 pm
Glad to here you got the code working.  I am still climbing the 3D printing learning curve!

Go Up