Banana Random Number Generator

An Arduino based true random number generator. Takes it's name from the potassium present in bananas, used as radiation source.

Similar projects worth following
An Arduino based true random number generator.
Takes it's peculiar name from the potassium-40 present in bananas, used as radiation source for the random number generatation.

Disclaimer: the radioactivity from the bananas doesn't quite make the difference, the background radiation is more than enough to make the generator work and afaik the banana's is barely detectable. But it's funny.

The whole project is built around the STS-5 geiger tube. The 400V needed for the tube are provided by a 555-based step-up converter very common on the internet.

The geiger pulse is then inverted and fed to a monostable 555 to stretch the pulse. The 555 drives through a transistor a buzzer and a led, and the signal is sent to the microcontroller.

The microcontroller is an atmega328p. The geiger signal goes to the ICP1 (input capture for timer 1) pin, which stores the current 16 bit timer1 value in a register and generates an interrupt. When the interrupt is raised, the microcontroller takes the value from the capture register and sends it as two raw bytes over the serial to the computer. 

Ent test was taken on a two-day sampling and showed no significant problems in the randomness.


C Source File - 2.18 kB - 05/04/2018 at 16:27


x-zip-compressed - 147.23 kB - 05/04/2018 at 16:27



ms-excel - 1.44 kB - 05/04/2018 at 16:26


  • 1 × Banana A fresh and potassium-rich banana

  • Project blog post now in english

    valerio\new04/21/2022 at 11:19 2 comments
  • Computing PI from a banana

    valerio\new03/09/2019 at 20:08 0 comments

    My banana (given the right tools) can compute a good estimate of PI using the Monte Carlo method.

    Punti = points; Interni = inside; Esterni = outside.

    I've written a processing code that let's you see the points beeing added to the plot every radioactive event. Consult the internet if you don't know this method yet. It's probalby one of the most inefficient methods to get a numerical estimation of pi, but it works and it's very intuitive.

    The code is available in the github repo:

  • Observations on interrupt collision between Arduino's millis() and attachInterrupt()

    valerio\new05/19/2018 at 21:57 0 comments

    When i first concieved the project, in the first hardware and firmware revision, i was planning to generate random numbers with this code in arduino's environment:

    void setup(){
      attachInterrupt(digitalPinToInterrupt(2), randomCore, FALLING);
    void randomCore() {
      Serial.println((unsigned int)(( micros() >> 2 ) & 0xFFFF));

    The right shift by two is done because micros()'s two lower bits are always to zero. The ANDing with 0xFFFF is done to prevent the sequentialiy of the numbers. The micros() value overflows every 70 minutes, we have about 30 new values per minute. If this AND wasn't done, we would have monotonically increasing values for the span of 70 minutes). Doing this, our remaining 16 bit value overflows about every 200 mS, which is acceptable.

    Data is printed as a 16 bit number on the serial port and is collected by the computer. This data is then saved to a text file, the numbers are converted in two raw bytes and are analyzed by ent

    The first two-day sampling gave an alarming result:

    $ ent randomdat.bin -c
    Value Char Occurrences Fraction  
    0              739   0.004077  
    1              402   0.002218  
    2             1033   0.005699  
    3              674   0.003718
    ...              ...      ...       
    254   �         722   0.003983
    255   �         691   0.003812
    Total:        181256   1.000000
    Entropy = 7.997995 bits per byte.
    Optimum compression would reduce the size
    of this 181256 byte file by 0 percent.
    Chi square distribution for 181256 samples is 498.15, and randomly
    would exceed this value less than 0.01 percent of the times.
    Arithmetic mean value of data bytes is 127.4942 (127.5 = random).
    Monte Carlo value for Pi is 3.138799695 (error 0.09 percent).
    Serial correlation coefficient is 0.005408 (totally uncorrelated = 0.0).

    As you can see, i was getting about half times less "0x01" than all the other bytes, and about 1.5 times more "0x02" than the others. There was clearly something wrong. (byte values from 0x04 to 0xFD are omitted)

    At some point i decided to split the high order and low order bytes that i was getting from the 16 bit number into two separate files and analyize them separately. These were the results:

    $ ent MSBs.bin -c
    Value Char Occurrences Fraction  
    0              358   0.003950  
    1              393   0.004336  
    2              347   0.003829  
    3              333   0.003674
    ...              ...     ...
    254   �          374   0.004127
    255   �          330   0.003641
    Total:         90628   1.000000

    The MSB showed no significant problems. 

    $ ent LSBs.txt -c
    Value Char Occurrences Fraction  
    0              381   0.004204  
    1                9   0.000099  
    2              686   0.007569  
    3              341   0.003763
    ...              ...     ...
    254   �         348   0.003840
    255   �         361   0.003983
    Total:         90628   1.000000

    But i was obviously having a problem with the LSBs. All my 0x01 values were counted as 0x02. 

    At this point i was totally clueless about what was going on, but some considerations about the periodicity of the 0x##01 value (where # is a dontcare) saved my day. 

    This value is periodic by 2^10 microseconds, which is about 1024 milliseconds. This led me to think to how the millis() value is updated via TIMER0_OVF interrupt in Arduino.  From Arduino's wiring.c for AVRs

        // copy these to local variables so they can be stored in registers
        // (volatile variables must be read from memory on every access)
        unsigned long m = timer0_millis;
        unsigned char f = timer0_fract;

    Basically the prescaler of the timer0 is set so that it overflows every 1024 microseconds: clock frequency is 16MHz, the prescaler is set to 64 and it overflows every 256 counts = overflow every 1024 uS. The function then takes into account for the extra 24 uS per overflow to calculate the milliseconds, and that's how the millis() work.

    Just as another side note: 16MHz with 64 as a prescaler gives minimum resolution of 4 uS, and that's why the micros() function has only 4 uS resolution. 

    What i think was happening with my problem is this: interrupts have priorities. INT0 (the external interrupt)...

    Read more »

View all 3 project logs

Enjoy this project?



Jan wrote 05/04/2018 at 15:58 point

HAHA. I want one. NOW! Even if the background noise is stronger than the bananas radiation, who cares.
This will give people plenty to talk about at a party. It even has a banana for scale!

  Are you sure? yes | no

valerio\new wrote 05/04/2018 at 17:05 point

It's time to get one! 😁 I think that generating random numbers from the most random fruit ever should be everyone's dream! 

  Are you sure? yes | no

Mike Szczys wrote 05/08/2018 at 15:09 point

Was it background noise or the fruit? This is Schrodinger's Banana

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates