ESPGeiger Compatible Hardware
ESPGeiger is written to be compatible with both the ESP8266 and ESP32 range of MCUs.
ESP8266
The Wemos D1 Mini (4MB) is the recommended ESP8266 MCU for ESPGeiger.
The ESP8266 ESPGeiger build is the base firmware for the official ESPGeiger-based hardware ESPGeiger-HW and ESPGeiger Log.
ESP32
Classic
The ESP32 DevKit / WROOM-32 (classic ESP32) is the recommended ESP32 target. Any 4 MB board built on the original ESP32 (Tensilica dual-core, IDF target esp32) should work with the esp32_* builds. ESP32 / ESP32-S3 / ESP32-C3 builds bundle SSD1306 OLED support and auto-detect the panel at boot, so the same env works whether or not a display is fitted.
ESP-S3
For ESP32-S3, the ESP32-S3-WROOM-1 N16R8 dev board (44-pin Type-C, 16 MB flash, 8 MB PSRAM, onboard NeoPixel on GPIO 48) is a target for the esp32s3_* builds.
ESP-C3
For the world’s smallest ESPGeiger, the Seeed Studio XIAO ESP32-C3 (21x17.5 mm, USB-C, BLE 5.0, external u.FL antenna) flashes cleanly with the esp32c3_* builds. Bare-minimum receiver: just power, an attached tube or upstream UDP feed and you have a working monitor in a footprint that fits inside almost any enclosure.

Other variants and devboards for the ESP classic, C3 and S3 should all be supported. Most options are selectable runtime for various pins, OLED options, NeoPixel and LED.
Variant support
| Variant | Status | Notes |
|---|---|---|
| ESP32 (classic) | Fully supported | All esp32_* build envs. PCNT hardware counter. SSD1306 OLED bundled and auto-detected. |
| ESP32-S3 | Supported | Generic esp32s3_pulse / _pulse_no_pcnt / _serial / _udp / _test envs. As on ESP32 classic, _pulse uses the PCNT hardware counter and _pulse_no_pcnt uses the interrupt counter. SSD1306 OLED bundled and auto-detected. |
| ESP32-C3 | Supported | esp32c3_* envs (RISC-V, no PCNT - software pulse counter). SSD1306 OLED bundled with default SDA=5 / SCL=6. |
| ESP32-S2 | Experimental | Base config present, no shipped end-user envs. |
| ESP32-C6 / H2 | Not supported | No build envs. RISC-V cores not tested. |
Boards with onboard OLED
Several popular ESP32 / ESP8266 boards ship with an SSD1306 OLED soldered to the same PCB. ESP32 family envs bundle OLED support and auto-detect the panel; just set SDA / SCL (and RST if your board wires it) from the Config page after flashing. ESP8266 still uses dedicated esp8266oled_* builds.
| Board | MCU | OLED pins (SDA / SCL) | OLED RST | Build | Notes |
|---|---|---|---|---|---|
| NodeMCU + 0.96” OLED | ESP8266 | 4 / 5 (default) | tied to 3V3 | esp8266oled_* | Works out of the box - matches firmware defaults. |
| Heltec WiFi Kit 32 V2 | ESP32 classic | 4 / 15 | GPIO 16 | esp32_* | Set SDA=4 / SCL=15 / RST=16 from Config page after flashing. |
| Heltec WiFi LoRa 32 V3 | ESP32-S3 | 17 / 18 | GPIO 21 | esp32s3_* | Set SDA=17 / SCL=18 / RST=21 from Config page after flashing. |
| TTGO LoRa32 V1 | ESP32 classic | 4 / 15 | GPIO 16 | esp32_* | Same recipe as Heltec V2. |
| LilyGo T-Beam | ESP32 classic | 21 / 22 (default) | none | esp32_* | Works with stock defaults. |
MINI ESP32-S3-N16R8 (sold as “XH-S3E-AI”; small purple board, onboard speaker + mic + button + NeoPixel + OLED header) ![]() | ESP32-S3 (16 MB flash, 8 MB PSRAM) | 41 / 42 (fixed) | none | xh_s3e_* | Dedicated env set; pin map hard-fixed in build flags. See buildtargets. |
Boards that wire the OLED’s reset line to a GPIO (Heltec / TTGO) need the firmware to pulse that pin at boot. The -DOLED_RST=N build flag enables that pulse; if omitted, the OLED stays in reset and shows a blank screen. Once defined, the pin is also runtime-adjustable from Config → Display → Reset Pin.
If your board isn’t listed but matches one of these patterns, the same recipe applies - set OLED_SDA, OLED_SCL and OLED_RST (if relevant) in a custom build env.
PCNT
The ESP32 range of MCUs feature an in-built hardware pulse counter (PCNT). The ESP32 and ESP32-S3 _pulse builds count with PCNT. The _no_pcnt builds use the same interrupt counter as the ESP8266 builds. The Web Installer offers the interrupt build as its standard Pulse option and PCNT as a separate choice. ESP32-C3 has no PCNT and always uses the interrupt counter.
The PCNT input pin floats by default, which suits modules that drive the line both ways. Change PCNT Pull in the Input tab’s advanced settings to pull-up for open-drain outputs, or pull-down for active-high modules with no idle pull of their own.
PCNT Filter
The PCNT hardware includes a glitch filter that can ignore pulses shorter than a configurable threshold. This helps filter out electrical noise and interference that could otherwise be counted as false radiation events.
The filter value can be configured from the ESPGeiger web interface under Config. The value ranges from 0 to 1023, representing APB clock cycles at 80MHz (each unit = 12.5ns). A value of 0 disables filtering.
| Filter Value | Pulse Duration Filtered | Use Case |
|---|---|---|
| 0 | Disabled | No filtering |
| 200 (default) | < 2.5μs | Filters electrical noise while passing all real geiger pulses |
| 500 | < 6.25μs | More aggressive filtering for noisy environments |
| 1023 | < 12.8μs | Maximum filtering |
Real Geiger-Muller tube pulses are typically 50-200μs in duration, so even the maximum filter value will not affect real readings. The filter is only available on ESP32 PCNT builds.
Custom builds can change the starting value. See Build Options.
Interrupt Debounce
On builds that use software interrupt counting instead of PCNT (all ESP8266 pulse builds and ESP32 no_pcnt builds), a debounce window rejects any edge that arrives within a configurable number of microseconds of the previously accepted pulse. This serves the same purpose as the PCNT filter - suppressing electrical noise and contact bounce without affecting real tube pulses.
The debounce value can be configured from the ESPGeiger web interface under Config. The value is in microseconds, with a range of 0 to 10000. A value of 0 disables the debounce.
| Debounce Value | Pulses Rejected | Use Case |
|---|---|---|
| 0 | Disabled | No debounce |
| 200 (default) | < 200μs apart | Suppresses typical switching noise, passes all real pulses |
| 1000 | < 1ms apart | More aggressive for noisier setups |
Real Geiger-Muller tube dead time is around 50-200μs, so the default sits just below the tube’s own recovery time and passes real events. The debounce only applies to the software interrupt path; PCNT builds use the PCNT Filter above instead.
Custom builds can change the default. See Build Options.
Interrupt Saturation Guard
On interrupt-counting builds, an input flooded with far more edges than any tube can produce is paused for 5 seconds at a time while the rest of the device keeps running. The log shows ISR storm. See Troubleshooting for causes.
