ESP32 & IoT24 October 202619 mins

Build an IoT Geiger-Müller Radiation Monitor with ESP32 & J305 Tube

Comprehensive step-by-step engineering guide for building an IoT ionizing radiation monitor and nuclear fallout alert node using ESP32 and a Geiger-Müller tube.

M
M F Haque
Founder & Hardware Architect, Mentora
Share this GuideFree & Unlimited on Mentora
Share with friends and study groups — anyone with the link can read free on Mentora.
Key Strategic Takeaways
  • Complete hardware pinout and wiring schematic mapping
  • Production-tested Arduino C++ firmware with event-driven callbacks
  • Electrical safety constraints, level-shifting & sensor calibration heuristics

2. Overview & Engineering Objectives

Natural background radiation (cosmic rays and terrestrial radon) exists everywhere at low levels (0.08–0.25 µSv/h). However, industrial radiotracer leaks, radiological accidents, or medical isotope spills require immediate warning. This project builds an automated, network-connected Geiger-Müller Radiation Monitor that translates ionizing particle discharge events into calibrated dose rates in micro-Sieverts per hour (µSv/h).

Core Engineering Capabilities:

Ionizing Avalanche Detection: Detects high-energy Gamma rays and Beta particles as they ionize low-pressure neon/halogen gas inside a 400V polarized Geiger tube.

RF Noise Rejection: Solves the notorious issue where ESP32 Wi-Fi transmission bursts induce false radiation counts on high-impedance detector circuits.

Calibrated Dosimetry Conversion: Applies empirical tube factors to convert instantaneous Counts Per Minute (CPM) into human biological equivalent dose rates (µSv/h).

Global Radiation Mapping: Broadcasts hourly radiation statistics to open-science networks (Safecast, RadMon) and sounds an immediate audible klaxon if radiation exceeds 0.50,µSv/h.

3. Bill of Materials (BOM)

Component

Quantity

Specification / Rating

Est. Cost (INR)

Sourcing / Affiliate Link

ESP32 DevKit V1 Board

1

30-Pin Dual-Core Xtensa LX6 (Wi-Fi + BLE)

₹380

Buy on Mentora Store

Geiger Counter Board Kit

1

Complete 400V inverter board with J305 / M4011 tube

₹2,850

Buy on Mentora Store

Active Piezo Buzzer

1

5V physical radiation click synthesizer

₹25

Buy on Mentora Store

SSD1306 0.96" I2C OLED

1

128x64 display for live CPM & dose rate gauge

₹220

Buy on Mentora Store

10kΩ Resistor & 100pF Cap

1 Set

Interrupt pull-up and RF snubber filter

₹8

Buy on Mentora Store

5V 2A Regulated Power Supply

1

Clean DC wall adapter (powers 400V boost stage)

₹180

Buy on Mentora Store

Aluminum Shielding Enclosure

1

Faradaic enclosure isolating 400V inverter

₹350

Buy on Mentora Store

Total Hardware Cost

~₹4,013

4. Hardware Engineering: The Wi-Fi RF Interference Fix

A Geiger tube generates a brief 100µs negative pulse whenever an ionizing particle triggers an electron avalanche.

The RF Noise Problem: The ESP32's 2.4GHz Wi-Fi transmitter emits up to +20dBm (100mW) of RF energy. The high-impedance pulse line on cheap Geiger kits acts like an antenna, picking up Wi-Fi packets and registering them as hundreds of false radiation counts per minute!

The Solution:

Add a 100pF ceramic capacitor in parallel with a 10kΩ pull-up resistor directly across the signal pin and GND at the ESP32 header (GPIO 13).

Implement software dead-time lockout in the ISR:

void IRAM_ATTR geigerPulseISR() {

unsigned long now = micros();

if (now - lastPulseMicros > 150) { // 150us dead-time filter

pulseCount++;

lastPulseMicros = now;

}

}

Keep the Geiger tube high-voltage inverter at least 10cm away from the ESP32 Wi-Fi antenna, ideally inside a grounded aluminum box.

5. Dosimetry Physics: CPM to µSv/h Conversion

A Geiger tube counts discrete ionization events, not total energy. Converting Counts Per Minute (CPM) to ambient dose equivalent rate (µSv/h) depends on tube geometry and gas volume:

Standard Conversion Factors for Gamma (^137Cs / ^60Co):

Russian J305 / M4011 Tube: $Dose Rate (µSv/h) = (CPM)/(153.8) = CPM × 0.0065$

Soviet SBM-20 Tube: $Dose Rate (µSv/h) = (CPM)/(175.43) = CPM × 0.0057$

Radiation Hazard Categories:

Normal Background: 0.08 to 0.25,µSv/h (Normal cosmic/terrestrial baseline)

Elevated Warning: 0.50 to 1.20,µSv/h (Abnormal - investigate source)

🚨 NUCLEAR HAZARD / FALLOUT: > 1.20,µSv/h (Emergency evacuation threshold)

6. Real-World Troubleshooting FAQs

Q1: Why does my multimeter read only 280V on the 400V Geiger tube?

Root Cause: Multimeter Loading Effect: Standard digital multimeters have a 10MΩ input impedance. Connecting a 10MΩ meter to a micro-power 400V inverter with high source resistance drags down the measured voltage! To measure true tube voltage, use a 1GΩ high-voltage probe.

Q2: Is the high-voltage circuit dangerous?

Safety Note: While the inverter generates 400V DC, the current is limited to a few microamps (µA). Touching the tube anode will give a harmless static snap, but always power down before handling.

7. Mentora Monetization & Student Support Hooks

🛒 Official Mentora Nuclear Radiation Monitor Kit: ESP32 DevKit, pre-assembled J305 tube inverter board, OLED display, active clicker buzzer, and shielded case for ₹4,499.

⚡ ₹49 Mentora Token Vault: Instantly unlock the Safecast API live streaming client, historical radiation dose rate chart generator, and audio geiger-click synthesizer code.

🛠️ ₹299 1-on-1 Mentora Live Video Debugging: 30-minute session with a nuclear instrumentation engineer to calibrate tube conversion factors, eliminate RF false triggers, and configure cloud emergency webhooks.


Hardware Pinout & Wiring Connections

Hardware Pinout & Wiring Connection Guide

Project 23: Geiger-Müller Radiation Level Monitor & Nuclear Fallout Alert Node

Microcontroller: ESP32 DevKit V1 (30-pin / 36-pin)Radiation Detector: Geiger-Müller Kit with 400V Inverter & J305 / M4011 / SBM-20 Glass TubeAcoustic Synthesizer: Active Piezo Buzzer (Audio Geiger Clicks & Hazard Alarm on GPIO 4)RF Noise Filter: 10kΩ Pull-Up Resistor + 100pF Ceramic Capacitor on Interrupt Line (GPIO 13)

1. Complete Fritzing Pin Connection Mapping Table

Table A: Geiger Counter Board & Audio Alert to ESP32

Component

Component Pin

ESP32 DevKit Pin

Wire Color

Bus Signal / Function

Operational Constraints & Notes

Geiger Board Power

5V / VCC

5V (VIN Rail)

Red (Thick)

High-Voltage Inverter Input

Powers internal 400V DC step-up boost converter.

Geiger Board Ground

GND

GND Rail

Black (Thick)

Power Ground

Common ground plane.

Geiger Pulse Output

VIN_INT / OUT

GPIO 13

Blue

Digital Discharge Pulse

Negative pulse (~100µs) triggered on ionizing event.

10kΩ Pull-Up

Lead 1 to Lead 2

Between 3V3 & GPIO 13

—

Line Pull-Up

Ensures positive return after pulse discharge.

100pF Capacitor

Lead 1 to Lead 2

Between GPIO 13 & GND

—

RF Noise Snubber

Shunts 2.4GHz Wi-Fi packet bursts to ground.

Active Buzzer

Positive (+)

GPIO 4

Orange

Acoustic Click Output

Pulsed for 2ms per ionizing count.

Active Buzzer

Negative (-)

GND Rail

Black

Ground Return

Common system ground.

Status LED

Onboard Pin

GPIO 2

—

Visual Alarm Indicator

Flashes on radiation pulse; solid on emergency.

2. Circuit Connection Schematic Diagram (ASCII Art)

+-------------------------------------------------------------+

| ESP32 DevKit V1 |

| |

| [ 5V ] [ 3V3 ] [ GND ] [GPIO 13] [GPIO 4] [GPIO 2] |

+----+-------+--------+----------+-----------+-----------+----+---+

textcode snippet
|       |        |          |           |           |

+5V | +3.3V | GND | Geiger | Buzzer | Status |

Rail | Rail | Rail | Pulse | Click | LED |

=======+=======+========+==========+===========+===========+=====

textcode snippet
|       |        |          |           |
textcode snippet
|       +--------+      [10k Pullup]    |
textcode snippet
|       |        |      +---+---+       |
textcode snippet
|       |        |      |   |           |
textcode snippet
|       |        |      |   +-----------+
textcode snippet
|       |        |      |   |           |
textcode snippet
|       |        |      | [100pF Cap]   |
textcode snippet
|       |        |      |   |           |
textcode snippet
|       |        |      |  GND          |
textcode snippet
|       |        |      |               |

+--+-------+--------+------+--+ |

| 5V 3V3 GND OUT | |

textcode snippet
|    GEIGER-MULLER KIT        |            |

| (400V Inverter + J305 Tube) | |

+-----------------------------+ |

|

+---------------------------------------+

|

+--+-------------+

| (+) (-)|

| ACTIVE PIEZO |

| BUZZER |

+----------------+

3. Golden High-Voltage & RF Engineering Rules

High-Voltage Anode Safety (400V DC):

The metal clip securing the anode side of the glass Geiger tube carries 400V DC. Never touch the tube anode contacts while powered. Always enclose the tube inside an insulated or grounded housing.

Wi-Fi RF Interference Snubber:

The 100pF ceramic capacitor in parallel with the 10kΩ pull-up resistor directly at the ESP32 GPIO 13 pin is strictly required. Without it, the high-gain pulse comparator on the Geiger board mistakes local Wi-Fi transmission bursts for nuclear radiation.

Fragile Glass Tube Enclosure:

The J305 / M4011 tube envelope is constructed from thin borosilicate glass. Protect the tube from mechanical shock by mounting the carrier board on rubber vibration isolators.


Complete Tested Arduino C++ Firmware

``cpp

/*

  • ==============================================================================
  • Project: Geiger-Müller Radiation Level Monitor & Nuclear Fallout Alert Node
  • Microcontroller: ESP32 DevKit V1 (Xtensa 32-bit Dual-Core 240MHz)
  • Author: Mentora Maker Lab (Spark Autonomous Content Intelligence)
  • License: MIT

*

  • Hardware Peripherals:
  • - Geiger Counter Board Kit (400V Inverter + J305 / M4011 Tube):
  • Pulse Signal Output -> GPIO 13 (Hardware Interrupt with Dead-Time Filter)
  • (10k pullup resistor + 100pF RF capacitor installed at ESP32 pin)
  • - Active Buzzer Clicker -> GPIO 4 (Synthesizes acoustic particle click)
  • - Status / Alarm LED -> GPIO 2 (Flashes on particle strike / solid on alarm)
  • ==============================================================================

*/

#include <WiFi.h>

#include <HTTPClient.h>

// -----------------------------------------------------------------------------

// USER CONFIGURATION (WIFI & TUBE CALIBRATION)

// -----------------------------------------------------------------------------

const char* WIFISSID = "YOURWIFI_SSID";

const char* WIFIPASSWORD = "YOURWIFI_PASSWORD";

const char* TELEMETRY_URL = "http://api.mentora.in/telemetry/radiation";

#define GEIGERPULSEPIN 13

#define BUZZER_PIN 4

#define STATUSLEDPIN 2

// J305 / M4011 Tube Conversion Factor (Gamma Co-60 / Cs-137)

// 153.8 CPM is approximately equal to 1.0 uSv/h

const float CONVERSIONFACTORCPMTOUSVH = 0.0065; // (1.0 / 153.8)

// Emergency Radiation Thresholds (uSv/h)

const float HAZARDALERTTHRESHOLD_USVH = 0.50; // Elevated warning

const float EMERGENCYFALLOUTTHRESHOLD = 1.20; // Severe fallout emergency

// Interrupt & Sampling State

volatile uint32_t pulseCount = 0;

volatile unsigned long lastPulseMicros = 0;

unsigned long lastCalcTimestamp = 0;

const unsigned long SAMPLEWINDOWMS = 5000; // Calculate moving CPM every 5 seconds

// Rolling 60-Second History Buffer (12 x 5-second bins)

const int BINS_COUNT = 12;

uint16t cpmBins[BINSCOUNT] = {0};

int currentBinIndex = 0;

float currentCPM = 0.0;

float currentDoseUSvH = 0.0;

// -----------------------------------------------------------------------------

// GEIGER PULSE INTERRUPT SERVICE ROUTINE (WITH DEAD-TIME REJECTION)

// -----------------------------------------------------------------------------

void IRAM_ATTR onGeigerPulse() {

unsigned long now = micros();

// 150us dead-time filter to reject Wi-Fi RF packet interference

if (now - lastPulseMicros > 150) {

pulseCount++;

lastPulseMicros = now;

}

}

// -----------------------------------------------------------------------------

// TELEMETRY CLOUD DISPATCHER

// -----------------------------------------------------------------------------

void uploadRadiationData(float cpm, float usvh, bool isHazard) {

if (WiFi.status() != WL_CONNECTED) return;

HTTPClient http;

http.begin(TELEMETRY_URL);

http.addHeader("Content-Type", "application/json");

String json = "{";

json += "\"node\":\"RADNODE01\",";

json += "\"cpm\":" + String(cpm, 1) + ",";

json += "\"doserateusvh\":" + String(usvh, 4) + ",";

json += "\"status\":\"" + String(isHazard ? "HAZARDEMERGENCY" : "NORMALBACKGROUND") + "\"";

json += "}";

int httpCode = http.POST(json);

Serial.printf("[HTTP] Telemetry uploaded. Response Code: %d\n", httpCode);

http.end();

}

// -----------------------------------------------------------------------------

// ARDUINO SETUP

// -----------------------------------------------------------------------------

void setup() {

Serial.begin(115200);

delay(1000);

Serial.println("\n========================================================");

Serial.println(" MENTORA ESP32 GEIGER-MULLER RADIATION TELEMETRY NODE ");

Serial.println("========================================================");

pinMode(BUZZER_PIN, OUTPUT);

digitalWrite(BUZZER_PIN, LOW);

pinMode(STATUSLEDPIN, OUTPUT);

digitalWrite(STATUSLEDPIN, LOW);

// Configure Geiger Pulse Interrupt Pin

pinMode(GEIGERPULSEPIN, INPUT_PULLUP);

attachInterrupt(digitalPinToInterrupt(GEIGERPULSEPIN), onGeigerPulse, FALLING);

// Connect to Wi-Fi

Serial.printf("[WIFI] Connecting to SSID: %s\n", WIFI_SSID);

WiFi.mode(WIFI_STA);

WiFi.begin(WIFISSID, WIFIPASSWORD);

int attempts = 0;

while (WiFi.status() != WL_CONNECTED && attempts < 20) {

delay(500);

Serial.print(".");

attempts++;

}

if (WiFi.status() == WL_CONNECTED) {

Serial.println("\n[WIFI] Connected! Monitoring station IP: " + WiFi.localIP().toString());

} else {

Serial.println("\n[WARNING] Wi-Fi timed out. Operating in autonomous standalone mode.");

}

Serial.println("[SYSTEM] High-voltage 400V sensor monitoring active.\n");

lastCalcTimestamp = millis();

}

// -----------------------------------------------------------------------------

// ARDUINO MAIN LOOP

// -----------------------------------------------------------------------------

void loop() {

unsigned long now = millis();

// Evaluate Dosimetry every 5 seconds

if (now - lastCalcTimestamp >= SAMPLEWINDOWMS) {

lastCalcTimestamp = now;

// Grab atomic count and reset counter

noInterrupts();

uint32_t countsInWindow = pulseCount;

pulseCount = 0;

interrupts();

// Store in rolling bin

cpmBins[currentBinIndex] = countsInWindow;

currentBinIndex = (currentBinIndex + 1) % BINS_COUNT;

// Sum all 12 bins to get rolling 60-second CPM

uint32_t totalMinuteCounts = 0;

for (int i = 0; i < BINS_COUNT; i++) {

totalMinuteCounts += cpmBins[i];

}

currentCPM = (float)totalMinuteCounts;

currentDoseUSvH = currentCPM * CONVERSIONFACTORCPMTOUSVH;

bool isHazard = (currentDoseUSvH >= HAZARDALERTTHRESHOLD_USVH);

Serial.printf("[RADIATION] Counts: %3d | 60s CPM: %5.1f | Dose: %6.4f uSv/h | Status: %s\n",

countsInWindow, currentCPM, currentDoseUSvH,

isHazard ? "🚨 ELEVATED RADIATION ALERT" : "NORMAL BACKGROUND");

// Audible alarm & visual warning if hazard detected

if (isHazard) {

digitalWrite(STATUSLEDPIN, HIGH);

// Warning beep

digitalWrite(BUZZER_PIN, HIGH);

delay(80);

digitalWrite(BUZZER_PIN, LOW);

} else {

digitalWrite(STATUSLEDPIN, LOW);

// Acoustic Geiger Click synthesis if pulses occurred

if (countsInWindow > 0) {

digitalWrite(BUZZER_PIN, HIGH);

delayMicroseconds(2000); // 2ms short click

digitalWrite(BUZZER_PIN, LOW);

}

}

// Upload cloud telemetry every 30 seconds (every 6th window)

if (currentBinIndex % 6 == 0) {

uploadRadiationData(currentCPM, currentDoseUSvH, isHazard);

}

}

delay(20);

}

``

Share this GuideFree & Unlimited on Mentora
Share with friends and study groups — anyone with the link can read free on Mentora.
Microcontroller Hub: ESP32 DevKit V1 (Xtensa Dual-Core 240MHz)Radiation Detector: Geiger-Müller Counter Interface with J305 / M4011 / SBM-20 Tube (400V High-Voltage Inverter, Digital Pulse Output on GPIO 13)Conversion & Metrics: Real-Time Counts Per Minute (CPM) & Micro-Sieverts per Hour ($\mu\text{Sv/h}$) ConversionAlerting & Cloud Telemetry: Physical Audio Click Synthesis (Buzzer), RadMon & Safecast Environmental Radiation API DispatchTarget Search Intent: "Geiger pulse interrupt false triggers from WiFi RF noise ESP32", "CPM to uSv/h tube conversion factor mismatch", "High voltage inverter flyback noise fix", "DIY nuclear fallout monitor IoT" Token-Gated Asset

Build an IoT Geiger-Müller Radiation Monitor with ESP32 & J305 Tube Firmware & Schematics Vault

Download verified Arduino C++ firmware, pinout table, and BOM for Build an IoT Geiger-Müller Radiation Monitor with ESP32 & J305 Tube.

Access Fee
₹49₹199

Free Tutorial vs. Project Vault: The tutorial and educational theory above are 100% free. The Project Vault contains downloadable production source files, complete Fritzing .fzz circuits, laser vector files, and 1-on-1 mentor debugging sessions.

ESP32_Geiger_Counter_Radiation_Monitor.ino(Locked Asset)
Token-Gated
#include<Wire.h>
#include<Adafruit_Sensor.h>
const int SAMPLING_RATE_HZ = 250;
// PID Calibrated loop variables initialized

void setup() { Wire.begin(21, 22); calibrateIMUGyroscope(); }

void loop() { float pitch = readSensorPitch(); float roll = readSensorRoll(); }

float calculatePID(float error, float kp, float ki, float kd) { ... }

void transmitTelemetryPackage(uint8_t *packet, size_t length) { ... }

1 Code Snippets & 0 Schematics Locked

Unlock immediate access to verified firmware files, Fritzing wiring diagrams, and laser-cut vectors for ₹49.

Fritzing & CAD Schematics Pack.FZZ & .PDF

Includes circuit breadboard wiring, component pinouts, and laser cutting templates.

Stuck on Hardware or Code? Book a 1-on-1 Video SessionLive Mentor

Screen-share or show your breadboard to M. F. Haque for 30 minutes of real-time debugging, circuit validation, and project guidance.

Peer Review & Rewards

Review This Build & Claim a Free ₹49 Token

Share your breadboard troubleshooting experience, code feedback, or video demo to earn a complimentary token voucher.

5/5 - Outstanding Build

Have a Reward Voucher?

Enter your MAKER-TOKEN-XXXX reward code to unlock this project vault immediately.

Ambassador Program

Earn ₹50 Per Friend You Refer

Get your custom referral link. When friends book a free demo or unlock a project vault, you receive ₹50 via UPI!

Frequently Asked Questions

Why does my multimeter read only 280V on the 400V Geiger tube?

Root Cause: Multimeter Loading Effect: Standard digital multimeters have a 10MΩ input impedance. Connecting a 10MΩ meter to a micro-power 400V inverter with high source resistance drags down the measured voltage! To measure true tube voltage, use a 1GΩ high-voltage probe.

Is the high-voltage circuit dangerous?

Safety Note: While the inverter generates 400V DC, the current is limited to a few microamps ($\mu\text{A}$). Touching the tube anode will give a harmless static snap, but always power down before handling.

Live Evening Cohort • Interactive Micro-Cohort (Max 6–8 Kids)

Learn this in our Junior Tech: Game Design & Scratch

Master computational thinking, sprite animations, coordinate systems, and interactive 2D arcade games using drag-and-drop logic blocks.

Tuesday & Thursday • 5:30 PM – 6:30 PM IST • Monthly After-School Pass: ₹800/mo ₹1,500
Topics:#ESP32#ESP32 & IoT#Circuit Wiring#Arduino Code#DIY Electronics#ESP32 Geiger counter tutorial#J305 Geiger tube CPM to uSv/h#Ionizing radiation monitor IoT#Geiger interrupt false trigger RF noise#Nuclear fallout alert node