Pedro52
Published © GPL3+

Handheld Geiger Counter with Arduino Nano

Geiger counter measuring radioactivity using Arduino Nano in 3D-printed housing, with OLED display and Li-ion battery.

AdvancedFull instructions provided11,688
Handheld Geiger Counter with Arduino Nano

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
Ready made Geiger Counter kit
×1
0.96" OLED color display 96 * 64
×1
micro USB charger board
×1
3.7v 4000mAh Protected Rechargeable 18650 Li-ion Battery
×1
Transistor BC547
×1
BUZZER -12MM
×1
Resistor 1k ohm
Resistor 1k ohm
×1

Software apps and online services

Fusion
Autodesk Fusion
Arduino IDE
Arduino IDE
CURA
ClickCharts
EasyEDA
Fritzing

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)

Story

Read more

Custom parts and enclosures

housing for the OLED display

3D printed housing for the 0,96” OLED display

housing for the Geiger Counter

housing made with Fusion 360, consisting of a top and bottom part:

Top part Handheld Geiger counter

3D stl file

Schematics

circuit diagram for the Geiger Counter

This diagram shows the setup of the electronics:

Code

Geiger_Counter.ino

Arduino
ARDUINO Sketch for the Geiger Counter running on an Arduino Nano:
/*********
  This project has been developed and produced by Pierre Pennings (December 2019),
  This Project is about making a handheld Geiger Counter using a ready made Geiger Counter kit, in a 3D printed handheld radiation detector, 
  De kit is connected to an Arduino Nano that counts the number of impulses from the Geiger/Muller tube in a period of 10 seconds and then displays the average CPM (Counts Per Minute) on a 96*64 OLED color display.
  The measured CPM is also displayed as micro Sievert per Hour (with a simple conversion factor of 151)
  The OLED display also displays the momentary measured amount of impulses (per second) and displays the measurements as a moving red bar on the display. 
  The 3D printed housing contains also the 18650-Ion Lithium battery (rechargeble) which provides the 5V power to the Arduino Nano as well as the Geiger Counter kit and 3,3V for the OLED display.
  A power-on swith and an external beeper complete the detector.
  Upon power-on, the charging level of the 18650 battery is shown on the color display.
        
  This code is licensed under GPL3+ license.
  
*********/

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1331.h>
#include <SPI.h>
                                  //Connections for the OLED display
#define sclk 13                           //SCL  (blue wire)
#define mosi 11                           //SDA  (white wire)
#define cs   10                           //CS   (grey wire)
#define rst  9                            //RES  (green wire)
#define dc   8                            //DC   (yellow wire)

#define LOGtime 1000                      //Logging time in milliseconds (1 second)
#define Minute 60000                      //the period of 1 minute for calculating the CPM values

#define show endWrite
#define clear() fillScreen(0)

// Color definitions
#define BLACK        0x0000
#define BLUE         0x001F
#define RED          0xF800
#define GREEN        0x07E0
#define CYAN         0x07FF
#define MAGENTA      0xF81F
#define YELLOW       0xFFE0  
#define WHITE        0xFFFF

Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, rst);

int Counts = 0;                           //variable containing the number of GM Tube events within the LOGtime
unsigned long previousMillis = 0;         //variable for storing the previous time
int AVGCPM = 0;                           //variable containing the floating average number of counts over a fixed moving window period
int TenSecCPM = 0;
int units = 0;
int tens = 0;
int hundreds = 0;
int thousands = 0;
float Sievert = 0;

int COUNTS[10];                         // array for storing the measured amounts of impulses in 10 consecutive 1 second periods
int t = 0;

////////////////////the setup code that follows, will run once after "Power On" or after a RESET///////////////////
void setup() {

  Serial.begin(115200);
  display.begin();
  display.fillScreen(BLACK);
  
  float Battery = analogRead(A3);       //(orange wire)
  float BattPerc = 100 * (Battery/770);
  
  //Serial.print ("battery value = "); Serial.println (Battery); Serial.print ("battery percentage = "); Serial.println (BattPerc);
  display.setCursor(4,4);
  display.setTextSize(2);
  display.setTextColor(MAGENTA);
  display.println("Battery");
  display.setCursor(4,24);
  display.print (int (BattPerc)); display.print("."); display.print (int((10*BattPerc)-(10*int(BattPerc)))); display.print(" %");
  delay(3000);
  display.fillScreen(BLACK);

  for (int x = 0; x < 10 ; x++) {           //put all data in the Array COUNTS to 0 (Array positions run from 0 to 10; 
    COUNTS[x] = 0;                          //10 positions covering a period of 10 seconds
  }
  
  attachInterrupt(0, IMPULSE, FALLING);     //define external interrupt on pin D2/INT0 to start the interupt routine IMPULSE  (green wire)
  
  display.drawRect(0,0,96,64,WHITE);
  display.setCursor(4,4);
  display.setTextColor(RED);
  display.setTextSize(2);
  display.print("CPM");
  display.setCursor(50,4);
  display.setTextSize(1);
  display.print("10 sec");
  display.setCursor(50,12);
  display.print("window");
  
  display.setCursor(4,38);
  display.setTextSize(1);
  display.setTextColor(GREEN);
  display.print("uSv/hr");
  
  display.drawRect(0,48, 96, 16, YELLOW);
}

////////////////////////the loop code that follows, will run repeatedly until "Power Off" or a RESET/////////
void loop() 
{
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > LOGtime)
    {
    previousMillis = currentMillis;

    COUNTS[t] = Counts;
    for (int y = 0; y < 10 ; y++) {               //add all data in the Array COUNTS together 
    TenSecCPM = TenSecCPM + COUNTS[y];            //and calculate the rolling average CPM over a 10 second period
    }
    AVGCPM = 6* TenSecCPM; 
    TenSecCPM = 0;
    t++ ;
    if (t > 9) { t = 0 ;}
    
    //Serial.print ("COUNTS "); Serial.print(t); Serial.print (" = ");Serial.println (COUNTS[t]);
    display.fillRect(4,20,90,17,BLACK);           // clear the CPM value field on the display
    display.setCursor(4,20);
    display.setTextColor(RED);
    display.setTextSize(2);
    display.println(AVGCPM); 

    //Serial.print ("AVGCPM = "); Serial.print (AVGCPM); //Serial.print ("   CPM = "); Serial.println (CPM);
    display.fillRect(45,38,50,10,BLACK);          // clear the uSv/Hr value field on the display
    display.setCursor(45,38);
    display.setTextColor(GREEN);
    display.setTextSize(1);
    
    Sievert = (AVGCPM /151.0) ;                                                     //Serial.print ("  Sievert = "); Serial.println (Sievert);
    units = int (Sievert);                                                          //Serial.print ("units = "); Serial.println (units);
    tens = int ((10*Sievert) - (10*units));                                         //Serial.print ("tens = "); Serial.println (tens);
    hundreds = int ((100*Sievert) - (100*units) - (10* tens));                      //Serial.print ("hundreds = "); Serial.println (hundreds);
    thousands = int ((1000*Sievert) - (1000*units) - (100*tens) - (10*hundreds));   //Serial.print ("thousands = "); Serial.println (thousands);
    display.print (units); display.print("."); display.print (tens); display.print (hundreds); display.println (thousands);
    
    display.fillRect(1,49,94,14,BLACK);            // clear the CPM indicator field on the display
    display.fillRect(1,49,Counts,14,RED);          // fill the CPM indicator field on the display
    
    Counts = 0;
    }
}
//////////////////END of LOOP////////////////////////////////////

/////////////////////////////////Hereafter follows the Function for counting the number of impulses from Geiger Counter kit
void IMPULSE()
  {
  Counts++;
  }

Credits

Pedro52

Pedro52

6 projects • 47 followers

Comments