Circular Computing

Sunday, 31 January 2016

I bought a cheap Geiger Counter Kit from China to generate some random numbers. I wired it up to an Arduino Uno and wrote a basic sketch (lots plagiarised, but I have references back to their sources in the code) that generates random numbers from radioactive decay events. This is something that should, by its very nature be totally chaotic and not be predictable using classical or even quantum physics.

The basic theory is to record the time of 4 consecutive detected decay events. The time interval between the first two events will be greater than the time interval between the second two events 50% of the time on average. Allocate a 1 bit if this occurs and allocate a 0 bit if the opposite occurs [first interval is less than the second interval].

Wiring

Arduino 5V <-> middle pin of the three on the left side of the detector (labelled 5V).
Arduino Ground <-> top pin of the three on the left side of the detector (labelled GND).
Arduino Pin 2 <-> bottom pin of the three on the left side of the detector (labelled VIN)
I also removed jumper J1 on the detector to stop it clicking. The jumper actually still on the board but only on one pin, instead of bridging the both pins as it would by default.

One nice thing about this setup is that the Arduino is powering up the Geiger Counter Kit (both together are using about 0.04A @ 5.00 V =0.2 Watts - measured by a "USB Charger Doctor").

Radiation sources

The Geiger Müller tube used is sensitive to Beta and Gamma radiation (M4011), so I did a quick search for sources of radiation that I would feel comfortable owning, or ordering online and having delivered (for some odd reason I can picture the postman freaking out carrying a package with a big yellow radiation warning sticker on it).

Bananas have so little Potassium-40 in them, to be nearly invisible from background radiation (which is very comforting if you like to eat Bananas) - 0.098
μSv. And since the human body strictly controls the percentage of Potassium at a constant level, you should not let this information distract you from eating bananas their goodness far out ways any negative.

You can call me crazy but I do not really feel comfortable with most radiation sources, so for my test I decided to use background radiation and some easily accessible Potassium-40 which should be around about 10x background levels.

I only used two sources for my radiation. One thing to keep in mind is that my Geiger Müller tube itself is slightly radioactive, just like everything, so I get about 0.2 pulses/second from the tube.

I could always check into using Caesium-137 or a Strontium-90 source at some
later date. But in all honesty I think that I'll go in a different
direction for generating random numbers. The sources I would feel comfortable using are not all that cheap as well.

Here is the sketch that I used to measure the CPM of the background and LO-SALT and print the result every 60 seconds:

And, here is the sketch that I ran on my Arduino to generate the random numbers:

// This code generates random numbers based on nuclear decay events, // In my mind they would be the highest quality of random numbers.// The only downside is that it is very very very very very slow. //// Using only background radiation of about 18CPM it would take// about 30 hours to generate 1k of random goodness.// Using low-sodium kitchen salt, you can get about 10x background radiation.// Using LoSalt (66% potassium Chloride) 161CPM it would take about // 202 minutes to generate 1k of random goodness.// Using some crazy lethal radiation source of 170,000CPM (60*1000000/350)// (maximum with my GM tube recovery time of ~350uS) it would take about // 200 minutes to generate 1MiB of random numbers//// This is one of the reasons that I would not use a GM tube as my final solution // to generate high quality truly random numbers, but it is interesting to test.//// Using background where I am is about 18 CPM I can generate about 0.53 bytes/minute// Using Lo-Salt (66% Potassium Chloride) 161 CPM I can generate about 5 bytes/minute//// 2016-01-31// Remove all elegance and make it dumb, just bit bang pins until they change state.// For optimal timing resolution sometimes doing things as basic as // possible is the most efficient technique.//// 2016-01-30// This is a rewrite to gather 4 decays and generate one bit of randomness without// using interrupts also we will use the rising edge instead of the falling edge as// the trigger for a new decay This is so that code is running while the GM tube // is recovering from the previous decay event//// 2016-01-13// some critical code from // https://www.fourmilab.ch/hotbits/source/hotbits-c3.html// and some code is from // https://github.com/revspace/geiger// and some useful info from// http://tinkerman.eldiariblau.net/geiger-counter///// The Geiger Counter is connected to pin 2 // each pulse every time a decay is detected about ~350 microseconds in duration // I measured that with the following very basic code:// unsigned long array[101];
// int counter=0;
//
// void setup(){
// Serial.begin(115200);
// pinMode(2, INPUT);
//}
//
//void loop(){
// array[counter++]=pulseIn(2,LOW);
// if(counter > 100)
// for(;--counter;counter>1)
// Serial.println(array[counter]);
//}// For my Geiger Counter Kit it's default is low, it pulses high for ~350uS // on a decay event and returns to lowconstintGMpin=2;constintLEDpin=13;intLEDstate=HIGH;unsignedlongtriggeredTime[4];unsignedcharbits;unsignedlongduration1,duration2;intflipper=0;// flip bit that gets toggled every time a new bit is generated. intshift=0;// track how many bits have we shiftedvoidsetup(){Serial.begin(115200);pinMode(GMpin,INPUT);

digitalWrite(LEDpin,LEDstate);pinMode(LEDpin,OUTPUT);

digitalWrite(GMpin,LOW);// turn on internal pullup resistor}voidloop(){// 4 highs and 4 lows is one bit, or 4 independent decay events// 0L-(unknown)->1H-(~350uS)->2L-(unknown)->3H-(~350uS)->4L// 4L-(unknown)->5H-(~350uS)->6L-(unknown)-7H->(~350uS)->0L//// Wait 0L->1Hwhile(digitalRead(GMpin)==LOW){};// wait here while the GM is low.triggeredTime[0]=micros();// first decay has occurreddigitalWrite(LEDpin,LEDstate);// toggle the LED once for each new bitLEDstate=!LEDstate;// Wait 1H->2L (~350uS)while(digitalRead(GMpin)==HIGH){};// wait here while the GM is high ~350uS// Wait 2L->3Hwhile(digitalRead(GMpin)==LOW){};// wait here while the GM is low.triggeredTime[1]=micros();// second decay has occurred// Wait 3H->4L (~350uS)while(digitalRead(GMpin)==HIGH){};// wait here while the GM is high ~350uS// Wait 4L->5Hwhile(digitalRead(GMpin)==LOW){};// wait here while the GM is low.triggeredTime[2]=micros();// third decay has occurreddigitalWrite(LEDpin,LEDstate);// toggle the LED once for each new bitLEDstate=!LEDstate;// Wait 5H->6L (~350uS)while(digitalRead(GMpin)==HIGH){};// wait here while the GM is high ~350uS// Wait 6L->7Hwhile(digitalRead(GMpin)==LOW){};// wait here while the GM is low.triggeredTime[3]=micros();// fourth decay has occurredduration1=triggeredTime[1]-triggeredTime[0];// first two decay events 3H-1Hduration2=triggeredTime[3]-triggeredTime[2];// second two decay events 7H-5Hif(duration1!=duration2){/* There remains the possibility of a very slight bias due to long-term effects such as ionisation of a Geiger tube, poisoning of a silicon detector, or (absurdly small for any practical source) decrease in radioactivity of the source over time. To mitigate this, we invert the sense of the magnitude test between the first and second samples for alternate samples. This pushes the effect of any long-term bias to a much higher order effect. */flipper^=1;bits=(bits<<1)|(flipper^(duration1>duration2));shift++;if(shift>7){// we have bits 0-7 collected, time to display the two nibbles.if((bits&0xF0)==0x00)// is the first nibble zeroSerial.print("0");// if it is then print the leading zero.Serial.print(bits,HEX);// this command does not print out leading zeroesshift=0;// time to start collecting a new byte.}}// I could just assume that my code above will take longer than ~350uS // (5600 clock cycles @ 16MHz] which would be a bad assumption. So I added the // following line just to be safe. The worse case is that I miss one decay event.// Wait 7H->0L (~350uS)while(digitalRead(GMpin)==HIGH){};// wait here while the GM is high ~350uS}

The above code sends hex digits one byte at a time to the serial port. To capture the random numbers and store them to file I used the following commands on Linux "screen -L /dev/ttyACM0 115200" [^A D - to exit the screen session and return to the console] this creates a logfile called screenlog.0 which captures all data coming to the USB serial port from the Arduino. Or you could use "(stty -F /dev/ttyACM0 raw ispeed 115200 ; cat > random.txt) < /dev/ttyACM0"

And to convert them from ASCII into binary I used the following UNIX command:
$ cat screenlog.0 | xxd -r -p - random.bin

And this binary file can be tested with rngtest if the filesize is at least 2500 bytes (20000 bits). Unfortunately since the randomness generation rate is low, it would take multiple centuries to generate the Gigabytes of data required for one run of the full dieharder randomness test suite, using a single Geiger Müller tube even with the most radioactive source possible. So as much as it was fun playing with a Geiger counter, for generating random numbers, I feel that it is a dead end, at least for me. The quality of the randomness it fantastic but the generation rate is far too low, at least for my needs.

Sunday, 29 November 2015

Question 1: There are three multiplexed ADC channels in the Airspy, is there a simple way to access the other two if I wanted to implement a custom DDC firmware?Answer 1: .By default channel 0 is used for the R820T2, but channel 1 and channel 2
are unconnected. You could hack the firmware source code and modify
this line "#define DEFAULT_ADCHS_CHAN (0)" in
"firmware/airspy_m4/airspy_m4.c" to use channel 1 or channel 2 instead
of channel 0 which is connected to the output of the R820T2 tuner chip.
Of course the R820T2 would still be powered on so you should disable it,
since you are not using it (use disable_r820t_power() anywhere where
enable_r820t_power() is called) because it may add unwanted noise. Of course disabling the R820T2 chip, also means that you should
delete/disable any calls to set registers in it, since you are not be
using it. You should also delete/disable the frequency tuning from the firmware since the tuner is not used. And by the time you have done that it might be easier just to
write your own custom firmware.

Extra info 1:Since the spyverter is now available it might be easier just to use it unless you actually need an ADC, that in theory could run at 80MSPS. The problem is that the USB bus will limit the data transfer to about 20MSPS. And there is not enough RAM in the LPC4370 to buffer more than about 2x16KiB (double buffering) or 32KiB of data, and there is not enough processing power within the CPU to reduce this data. So unless 32KiB of data sampled at 80MSPS is enough for your function this is probably a dead end for your idea. If you are still going to use the two ADC ports the good news is that there is ESD protection in the R2 board, the R0 board had no ESD protection on the ADC inputs.

Monday, 2 March 2015

The basic idea behind the Kalibrate software is that a GSM mobile phone base station has an expensive very high precision atomic clock (0.01ppb), where as a RTL-SDR stick has a cheap low precision 28.8MHz quartz crystal (+/-100ppm). This cheap low precision oscillator is used to derive all frequencies when you tune the RTL-SDR, so the bigger the errors the more you are offset from the correct frequency. There are two pieces of good news the offset is linear and once the cheap crystal has warmed up it generally does not drift very much. Because the error is linear across the whole frequency range, only one correction value is required.

When you buy a 28.8MHz quartz crystal in a can, they are generally not 28,800,000Hz. There are two problems that need to be compensated for by the PPM offset in SDR receiver software. The first is manufacturing tolerance, generally about 100 PPM (0.01%) is the range to keep costs down, so the frequency of a new quartz crystal could be anywhere between 28,797,120Hz and 28,802,880Hz at 20 degrees Celsius. The second problem is that the frequency will change slightly as the device warms up. But the good news is once the device has warmed up it will not drift much, unless the ambient room temperature varies.

So basically you scan the local area for active GSM base station channels with a large amount of power (good signal strength, which will probably be from the base station that is physically closest to your current location). Then kal uses this channels GSM frequency correction bursts to workout the PPM (part per million) offset of the RTL-SDR that you are currently calibrating.

Use the kal software to scan GSM base stations for channels with high power

My RTL-SDR only goes from 24MHz to 1750MHz, so I can not use the DCS or PCS GSM system, even if they were active in my area. I know that EGSM is active where I am, but I'll test all the frequencies to time and show how long a scans takes when no GSM is present, as well as how long it takes when GSM base stations are present (about 2-10 minutes). This will also provide the warm up time of about 10 minutes for my RTL-SDR to reach its steady state operating temperature. Some of the GSM down link frequencies are used to send the frequency correction bursts, to calibrate mobile phone handsets, so that the phones know the correction offset to use when TX'ing on the up link frequencies. This allows mobile phone makers to use cheaper hardware in their handsets, and if you are making a few billion of them small savings quickly add up to more profit..

(print the help for the kal software to see what arguments should be used)$ kal
error: must enter channel or frequency
kalibrate v0.4.1-rtl, Copyright (c) 2010, Joshua Lackey
modified for use with rtl-sdr devices, Copyright (c) 2012, Steve Markgraf
Usage:
GSM Base Station Scan:
kal <-s band indicator> [options]

Use the kal software to calculate the PPM clock offset of a RTL-SDR.

So now that I have at least one channel number, with a high broadcast power in my region, I can calculate the PPM offset with the kal software (best if the RTL-SDR has had a chance to warm up, the cheap 28.8MHz quartz crystal probably drifts most with temperature).

Since there where no overruns and the signal was found every time I know that this is a good result, that I can confidently use this value with this particular RTL-SDR hardware in GRC or SDRSharp. I would round this number and use a PPM offset of -24 (0.0024%), since none of the software supports PPB corrections (yet). Even if there were 1 to 2 overruns or 1 to 5 not-found the PPM value would still probably be valid, it just meant that there was interference during the test or the signal strength of the channel used was not high enough, maybe try the test again using a different channel, that has more power (or less interference).

The Kalibrate software actually uses the GSM signals own inbuilt frequency correction bursts, that are used by mobile phone handsets (which also have cheap quartz crystals inside them) to calculate their ppm frequency correction. The original open source software was written for the Ettus Research USRP hardware and was ported work with the RTL-SDR.

ResultsPeak Internet transfer rate 10.87MiB/sec (91.2Mbps) - about 13 hops awayAverage Internet throughput 6.04MiB/sec - about 13 hops away.Because this server is so many hops
away it's throughput varies wildly with time of day and is effected by
so many uncontrolled fluctuations on every hop in between. This result
is more an example of a typical Internet based throughput than a maximum
throughput.

Peak LAN download transfer rate 38.88 MiB/sec (326.15Mbps) - for 1000Mbps (even limited to USB 2.0 480Mbps) this is a very good throughput.Average LAN download throughput 38.88 MiB/sec - for 1000Mbps (even limited to USB 2.0 480Mbps) this is a very good throughput.

I'm very pleased with the USB 2.0 Gigabit Ethernet Adapter result for
the Banana Pi. I was expecting a result somewhere between 20 MiB/sec and
40 MiB/sec.

I enabled jumbo frames ("sudo ifconfig eth1 mtu
9000") on the webserver and on the Banana Pi to see if I could get a
better result, but I couldn't get it to work. I'm not quite sure why,
yet but I'm still looking into it.

I'm not quite sure why upload is always less than download throughput rates, it is something that I'll have to think about for a while.

For two final tests I decided to unplug the USB 2.0 Gigabit ethernet adapter and use the Banana Pi's actual builtin Gigabit NIC and just get the average throughput in each direction (using a ramdisk on each machine to upload the file from as fast as possible).

Thursday, 20 November 2014

Update (2015-2): I'll update the below when I get more info on the new BCM2836 chip used in the Raspberry Pi Generation 2 model B. It CPU performance should jump up by about six, the RAM has doubled, but the GPU is the same as is everything else. RAM performance will be the same, no clocking improvement, just size. The quad core CPU (ARMv7) does now have NEON support so SIMD, should improve data processing ability. But the real bottleneck to the RPi is getting data into and out of the CPU from the real world, it is like a giant head sitting on a straw.

CPU

From each of the /proc/cpuinfo files shown below, in theory if an
application is single threaded the Banana Pi should win, and if it is
multithreaded the Banana Pi should still win. I have not run any direct
benchmark, just looking at the BogoMIPS and the Features supported by each ARM chip.Raspberry Pi (Model A,B,B+,A+ all have the same ARM1176JZF-S)------------Processor : ARMv6-compatible processor rev 7 (v6l)BogoMIPS : 697.95Features : swp half thumb fastmult vfp edsp java tlsCPU implementer : 0x41CPU architecture: 7CPU variant : 0x0CPU part : 0xb76CPU revision : 7

Weight

My conclusion would be if it is light weight I needed, then I'd go with a Pro Trinket (2.6g/0.09oz), unless I needed a 1920x1080HD camera as well then it would be the Raspberry Pi A+ (23g/0.81oz) with a camera module (3g/0.11oz). If it was easily accessible GPIO that I needed, with loads of inputs and outputs I'd pick the Beaglebone Black (It is a great piece of open hardware) 7ADC is nice. And finally if it was shoving large amounts of data about fast, or processing that data, I'd pick the Banana Pi (With SATA 2.0, Gigabit Ethernet and 1GiB of RAM it is an impressive piece of kit) or it's newer incarnation of hardware the Banana Pro (with builtin WiFi).

There are larger communities built up around the Raspberry Pi and Beaglebone Black, than there is around the Banana Pi/Pro hardware. So if you have a problem, sometimes you may have to solve it yourself rather than looking for a quick fix from someone else in the community who had the same problem already.

# 18 x 1GiB = 18GiB# assuming maximum write SATA2 286MiB/sec this should take more than a minute# assuming poor write speed of 5 MiB/sec this should take more than a hour# either way one pass should happen within 12 hoursecho touch $DEST/testbegin-write-starttimetouch $DEST/testbegin-write-starttimedateecho syncsyncdate

# 18 x 1GiB = 18GiB# assuming maximum read SATA2 286MB/sec this whould take just over a minute# assuming poor read speed of 5 MiB/sec this should take just over a hour# This script assumes that write-throughputtest.sh was run# previously to generate the data files.

I'm converting the results so that I can display them in MiB/sec instead of dd's default of MB/sec. Because I'm copying a Gigabyte of data with each block size all I need to do is divide 1024 by the number of seconds that it took to get the result in MiB/second.

I decided to run the tests again with an old 128GB SSD (write performance will be OKish because it is used, but read performance should be better than spinning rust). But to avoid killing it (small writes cause SSD's to fail prematurely) I started the write testing at 4K block size.The read test block size does not matter at all, SSD's always fail due to running out of writes (3000-5000 per block) long before any wear due to reads can happen. The reason I ran the tests again with a SSD was because I felt that the limiting factor was the Harddisk's poor read/write performance and not any limit of the Banana Pi's SATA 2.0 port.

Since the throughput is more than 150MB/sec, it does confirm that the SATA port in the Banana Pi is SATA 2.0. And I suspect that it could get closer to the SATA 2.0 limit of 300MB/sec if I used a brand new SSD. I have to admit that I am so much more impressed by a Banana Pi especially when compared to a Raspberry Pi. Especially for pushing large amounts of data about fast, it is brilliant hardware.