Of course every household needs a Geiger Counter and I bought this kit to do all the fancy 400/500V voltage work along with an SBM-20 Geiger-Muller Tube on eBay for the actual radiation detecting. Typically it seems people hook this up to a tablet etc. and run an app but my plan was to log to InfluxDB. It can also operate stand-alone which is why I added a handy display (Nokia 5110).

Notes:
This type of detector is designed to detect Beta & Gamma rays. (it cannot detect Alpha rays but this sensor can be added easily if wanted.
What it does:
– Listens & counts pulses for 60 seconds
– After 60 seconds writes this value to InfluxDB
– Updates display with current metrics. (last 60 second reading, average reading, max reading, estimated dosage & the current IP address)
Connecting it up:
| LCD Pin | ESP8266 Labelled Pin | ESP8266 GPIO Pin | Geiger Detector Board |
| 1 – RST | D0 | GPIO 16 | |
| 2 – CE | D1 | GPIO 5 | |
| 3 – DC | D2 | GPIO 4 | |
| 4 – DIN | D3 | GPIO 0 | |
| 5 – CLK | D4 | GPIO 2 | |
| 6 – Vcc | 3.3V | 3.3V | |
| 7 – Backlight | 3.3V (on) | 3.3V | |
| 8 – Ground | Ground | Ground | Ground |
| D5 | GPIO 14 | Int (interrupt) | |
| VU/ 5V | VU / 5V | 5V |
Code:
See latest code at my GitHub (or below):
– Requires Adafruit libraries. Link 1, Link 2
– Requires Running Average Library
– Requires InfluxDb library
#include <ESP8266WiFi.h>
#include <InfluxDb.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#include "RunningAverage.h"
#define INFLUXDB_HOST "192.168.1.XXX"
#define WIFI_SSID "XXXXXXXXXXXX"
#define WIFI_PASS "XXXXXXXXXXXX"
#define DATABASE "XXXXXXXXXXXX"
#define MEASUREMENT "XXXXXXXXXXXX"
#define DEVICE "XXXXXXXXXXXX"
#define ID "Geiger_Counter"
#define LOG_PERIOD 60000
Influxdb influx(INFLUXDB_HOST);
Adafruit_PCD8544 display = Adafruit_PCD8544(2, 0, 4, 5, 16); //LCD 1.5 Inch (Nokia 5110)84×48 (x,y) pixels
RunningAverage raMinute(60);
//################
int debug = 1; //#
//################
int loopCount = 0;
int cpm = 0;
int cpm_max = 0;
int cpm_1hr_avg = 0;
int cpm_ravg = 0;
int counts = 0;
int cal_factor = 1;
int wifiStatus;
unsigned long currentMillis;
unsigned long previousMillis; //variable for time measurement
void setup(){
Serial.begin(9600); // start serial monitor
delay(1000);
Serial.println("");
Serial.println("");
Serial.println("Setup Routine of ESP8266 Geiger Counter");
display.begin();
display.setContrast(55);
display.display(); // show adafruid splashscreen
delay(2000);
display.clearDisplay(); // clears the screen and buffer
pinMode(LED_BUILTIN, OUTPUT); //D4
digitalWrite(LED_BUILTIN, HIGH); //Turns it off
pinMode(14, INPUT_PULLUP); // set pin INT0 input for capturing GM Tube events / GPIO5 = D1
attachInterrupt(14, tube_pulse, FALLING); //defines interrupts
raMinute.clear();
influx.setDb(DATABASE);
display.setTextSize(1);
display.setTextColor(BLACK);
display.setCursor(0,0); display.setTextSize(1);display.print("Up Hrs: ");display.setCursor(48,0);display.print("0");
display.setCursor(0,9); display.setTextSize(1);display.print("CPMi 1m:");
display.setCursor(0,17);display.setTextSize(1);display.print("CPM avg:");
display.setCursor(0,25);display.setTextSize(1);display.print("CPM Max:");
display.setCursor(0,33);display.setTextSize(1);display.print("uSv/hr: ");
display.setCursor(0,41);display.setTextSize(1);display.print("Not Connected");
display.display();
wifiStatus = WiFi.status();
if (wifiStatus != WL_CONNECTED) {
new_connection();
}
else {
display.fillRect(0,41,84,48, WHITE);
display.setCursor(0,41);
display.print(WiFi.localIP());
display.display();
}
if (debug == 1) {Serial.println("Setup Complete.");}
}
void loop(){
currentMillis = millis();
if(currentMillis - previousMillis > LOG_PERIOD){
cpm = counts * cal_factor;
raMinute.addValue(cpm);
cpm_ravg = raMinute.getAverage();
if (cpm > cpm_max){
cpm_max = cpm;
}
Serial.print("CPM: ");
Serial.println(cpm);
display.fillRect(48,0,40,40, WHITE);
display.display();
display.setCursor(48,0);display.print(loopCount*.0166);
display.setCursor(48,9);display.print(cpm);
display.setCursor(48,17);display.print(cpm_ravg);
display.setCursor(48,25);display.print(cpm_max);
display.setCursor(48,33);display.print(cpm_ravg*0.0057);
display.display();
Serial.println("Attempting to write to DB");
counts = 0;
InfluxData row(MEASUREMENT);
row.addTag("Device", DEVICE);
row.addTag("ID", ID);
row.addValue("CPM", cpm);
row.addValue("LoopCount", loopCount);
row.addValue("RandomValue", random(0, 100));
wifiStatus = WiFi.status();
while ( wifiStatus != WL_CONNECTED )
{
new_connection();
}
influx.write(row);
if (debug == 1) {Serial.println("Wrote Data.");}
//WiFi.mode(WIFI_OFF); // Probably turn off Wifi if want to save battery
//WiFi.forceSleepBegin();
//delay( 1 );
status_blink();
previousMillis = currentMillis;
loopCount++;
}
}
ICACHE_RAM_ATTR //Needed to fix ISR not in IRAM boot error
void tube_pulse(){ //procedure for capturing events from interrupt
counts++;
}
void new_connection() {
wifiStatus = WiFi.status();
if (wifiStatus != WL_CONNECTED) {
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
int loops = 0;
int retries = 0;
display.fillRect(0,41,84,48, WHITE);
display.setCursor(0,41);
display.print("Not Connected");
display.display();
while (wifiStatus != WL_CONNECTED)
{
retries++;
if( retries == 300 )
{
if (debug == 1) {Serial.println( "No connection after 300 steps, powercycling the WiFi radio. I have seen this work when the connection is unstable" );}
WiFi.disconnect();
delay( 10 );
WiFi.forceSleepBegin();
delay( 10 );
WiFi.forceSleepWake();
delay( 10 );
WiFi.begin( WIFI_SSID, WIFI_PASS );
}
if ( retries == 600 )
{
if (debug == 1) {Serial.println( "No connection after 600 steps. WiFi connection failed, disabled WiFi and waiting for a minute" );}
WiFi.disconnect( true );
delay( 1 );
WiFi.mode( WIFI_OFF );
WiFi.forceSleepBegin();
delay( 10 );
retries = 0;
if( loops == 3 )
{
if (debug == 1) {Serial.println( "That was 3 loops, still no connection so let's go to deep sleep for 2 minutes" );}
Serial.flush();
ESP.deepSleep( 120000000, WAKE_RF_DISABLED );
}
}
delay(50);
wifiStatus = WiFi.status();
}
wifiStatus = WiFi.status();
Serial.print("WiFi connected, IP address: ");Serial.println(WiFi.localIP());
display.fillRect(0,41,84,48, WHITE);
display.setCursor(0,41);
display.print(WiFi.localIP());
display.display();
}
}
void status_blink() {
digitalWrite(LED_BUILTIN, LOW); // Turn the LED on (Note that LOW is the voltage level
delay(100);
digitalWrite(LED_BUILTIN, HIGH); // Turn the LED on (Note that LOW is the voltage level
delay(100);
digitalWrite(LED_BUILTIN, LOW); // Turn the LED on (Note that LOW is the voltage level
delay(100);
digitalWrite(LED_BUILTIN, HIGH); // Turn the LED on (Note that LOW is the voltage level
}
ToDo:
– Comment code
– Add in check at start of code to see if tube functioning.
– I would like to update the running average to 60min average but not enough time to currently do these 10 lines of code.
– Add in control (on/off ) for the LCD backlight, buzzer & Wifi for battery consumption.
– Perhaps would be nice to log to SD card also, not sure if I still have enough I/O for that.
– The ‘case’ is a very rough and not worthy of sharing, a nicer more bespoke would be ideal.
– Add radiation symbol on splash screen.
Resources I used:
– https://mightyohm.com/blog/2014/11/a-spotters-guide-to-the-sbm-20-geiger-counter-tube/
That’s it!