i bought one, needed some mods to get it working. put esphome on it. works a treat.
that is just some grafics with the duration of the data?
the device puts out CPM. The Geiger tube has a specific micro Sieverts per hour calibration depending on the type of tube. Just added ESP32 and ESP home to count and transmit the data.
Here is my ESPH code.
esphome:
name: esp-geiger01
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
#level: VERY_VERBOSE
# #Enable Home Assistant API
api:
password: "getyourown"
encryption:
key: "getyourown="
ota:
password: "getyourown"
wifi:
ssid: urssid
password: "getyourown"
domain: .urdomain.local
# #Optional manual IP
manual_ip:
static_ip: x.x.x.x
gateway: x.x.x.x
subnet: 255.255.255.0
dns1: x.x.x.x
switch:
- platform: restart
name: "esp-geiger01 Restart"
sensor:
- platform: uptime
name: "esp-geiger01 Uptime"
update_interval: 60s
- platform: wifi_signal
name: "esp-geiger01 Wi-Fi Signal"
update_interval: 60s
- platform: pulse_counter
pin: GPIO36
name: "esp-geiger01 geiger counter CPM"
id: "geiger_counter"
update_interval: 60s
unit_of_measurement: 'CPM'
on_raw_value:
- sensor.template.publish:
id: radiation_level
state: !lambda 'return x *0.0081;'
# # this was what I got for my data sheet and it matched reasonably well with the background data that I have. Many people are using other values.
- platform: template
name: "esp-geiger01 Radiation Level"
id: "radiation_level"
unit_of_measurement: 'µSv/h'
update_interval: 60s
icon: mdi:radioactive
accuracy_decimals: 5
- platform: dht
update_interval: 10s
pin: GPIO16
model: DHT11
temperature:
name: "esp-geiger01 Temperature"
unit_of_measurement: "°C"
filters:
offset: 0
humidity:
name: "esp-geiger01 Humidity"
filters:
offset: 10
binary_sensor:
- platform: template
device_class: safety
name: "esp-geiger01 Radiation Warning"
# # This doesn't necessarily represent a "dangerous" count, but one that is abnormally high
lambda: |-
if (id(geiger_counter).state > 100) {
// High Count.
return true;
} else {
// Normal Count.
return false;
}
text_sensor:
- platform: version
name: "esp-geiger01 ESPHome version"
time:
- platform: homeassistant
id: homeassistant_time
I know that my question is about the graphs… I know how to do them with time but…. How do you do the top limit? I assume that it’s the security point isn’t it?
type: custom:mini-graph-card
name: Radiation Level - 1hr
icon: mdi:radioactive
hours_to_show: 1
points_per_hour: 60
line_width: 1
entities:
- entity: sensor.esp_geiger01_radiation_level
name: µSv/h
units: µSv/h
line_width: 5
color: green
show_state: true
show_line: true
show_fill: true
show_points: true
- entity: sensor.virtual_sensor_020_usv
name: 020 µSv
units: µSv
line_width: 5
color: orange
show_state: false
show_legend: false
show_line: true
show_fill: false
show_points: false
Create Virtual sensors in your HA configuration.yaml and add them to the graph
#Virtual CPM for Graphing
- platform: virtual
name: 'sensor.30_CPM'
class: measurement
initial_value: 30
initial_availability: true
#Virtual µSv for Graphing
- platform: virtual
name: 'sensor.020_µSv'
class: measurement
initial_value: 0.20
initial_availability: true
I’ve posted my finished thing in the Share Your Projects area.
Thank You!!!
Realized I didn’t actually post my source code. It’s mostly the Brian Gauger example code with MQTT communication added.
I used an STM32 “Blue Pill” because I already had one set up on a breadboard with a W5500 module however any Arduino will work if you adjust the library used (from Ethernet_STM to Ethernet) and the pin used for attachinterrupt() . See Arduino interrupt pins.
/*************************************************************************
* Filename: rhGeiger.ino *
* Author: Brian K. Gauger (based loosely on code by Alex Boguslavsky) * *
* Date: 11 Oct 2018 *
* Purpose: Arduino code for http://rhelectronics.net v3.00 board, *
* Serial Monitor version *
* *
* Arduino IDE version: 1.0.6 *
* Executable Size: ~5.6 kbytes *
* *
* Copyright 2018 Brian K. Gauger *
* *
* Licensed under terms of Creative Commons Attribution-ShareAlike 4.0 *
* International (CC BY-SA 4.0). You can do pretty much anything you *
* want with this code, provided you: *
* a) Give me credit somewhere in the comments, and *
* b) Distribute your modified code under the same terms. *
*************************************************************************
* *
* ===================================================================== *
* Speaking of credit... MANY THANKS to Alex Boguslavsky for developing *
* the rhGeiger kit, and for the original code that inspired this! *
* ===================================================================== *
*************************************************************************
*
* IMPORTANT NOTE:
* ===============
* The radiation levels reported by your Geiger Kit are APPROXIMATE only!
* GM tubes vary greatly in terms of sensitivity to alpha, beta, and
* gamma radiation. Some good info at:
* https://sites.google.com/site/diygeigercounter/gm-tubes-supported
*
* If you need the CPM to microSievert conversion factor for GM tubes
* OTHER than the SBM-20, this is a good place to begin looking.
*
* Remember, your unit is NOT calibrated to a standardized source.
* So, take your readings with a large grain of salt substitute (a slightly
* radioactive "check source"! A small plastic bag of KCl laid on top of my
* SBM-20 yields about 6x background in my area. Your results will vary).
*/
/////////////////////////////////////////////////////////
// HARDWARE CONNECTIONS -- //
// A) Connect Geiger PCB INT output to Arduino pin 2. //
// B) Connect Geiger PCB & Arduino grounds together. //
// C) Ensure C-INT (103, 0.01 uF) is soldered on the //
// Geiger PCB. //
/////////////////////////////////////////////////////////
// Averaging (logging) period in milliseconds, typically 15000-60000.
#define AVG_PERIOD 15000
#define ONE_MINUTE 60000
// I'm using the SBM-20 Geiger-Muller (GM) tube with my kit. Conversion
// factors for other GM tubes may be found scattered throughout the Web.
#define SBM_20
#ifdef SBM_20
#define CONV_FACTOR 0.0057 // SBM-20 counts to uSv/hr multiplier
#endif
#include <itoa.h>
//PubSubClient library for MQTT
#include <PubSubClient.h>
//ethernet related includes
#include <SPI.h>
#include <Ethernet_STM.h> //ethernet2 for non-STM32
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io
;
#else
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
#endif
// Initialize the Ethernet client library
EthernetClient ethClient;
//MQTT
//MQTT sever address
#define MQTT_SERVER "192.168.1.10"
void MQTTCallback(char* topic, byte* payload, unsigned int length); //function prototype for MQTT callback
char const* MQTTClientName = "geiger"; //MQTT client name. Keep short, don't waste RAM
const char TelemetryTopic[] = "/geiger/tele/"; //Suffix added to board topic for telemetry heatbeat
const char CountTopic[] = "/geiger/cpm/";
const char DoseTopic[] = "/geiger/dose/";
PubSubClient MQTTClient(MQTT_SERVER, 1883, MQTTCallback, ethClient); //pass Ethernet object to PubSubClient and create MQTT client
unsigned long counts; // # of raw GM Tube events
unsigned long cpm; // Counts Per Minute (CPM)
unsigned int mult; // CPM = (counts in a given interval) * multiplier
char CountString[16];
char DoseString[16];
// Interrupt handler that counts raw events from Geiger Kit
void tube_impulse() {
counts++;
}
void ConnectToMQTTBroker() {
// Loop until connected to MQTT broker
while (!MQTTClient.connected()) {
Serial.println(F("MQTT: Attempting connection..."));
//if connected, subscribe to the relay topics as BoardTopic/relay number
if (MQTTClient.connect((char*)MQTTClientName)) {
Serial.println(F("MQTT: Connected"));
}
}
}
void MQTTCallback(char* topic, byte* payload, unsigned int length) {
//function called when MQTT message received
}
void setup()
{
counts = 0;
cpm = 0;
// Initialize Serial communications
Serial.begin(9600);
Serial.println(F("Boot"));
// start the Ethernet and obtain an address via DHCP
Serial.println(F("Start: Ethernet..."));
if (Ethernet.begin(mac) == 0) {
Serial.println(F("FAIL: Ethernet: No DHCP."));
}
Serial.print(F("Success: Ethernet. DHCP IP: "));
Serial.println(Ethernet.localIP());
delay(3000);
ConnectToMQTTBroker(); //connect to MQTT broker
// Determine multiplier for your log period
mult = ONE_MINUTE / AVG_PERIOD;
pinMode(PA0, INPUT); // Set pin 2 up for GM tube event interrupts
digitalWrite(PA0, HIGH); // Use internal pullup resistor
//attachInterrupt(0, tube_impulse, FALLING);
attachInterrupt(digitalPinToInterrupt(PA0), tube_impulse, FALLING);
Serial.print(F("First reading in "));
Serial.print(AVG_PERIOD / 1000);
Serial.println(F(" sec..."));
}
void loop()
{
//reconnect if connection is lost
if (!MQTTClient.connected()) { ConnectToMQTTBroker(); }
MQTTClient.loop(); //maintain the MQTT connection
// Elapsed time stuff
static unsigned long then;
unsigned long now = millis();
// Approx radiation level in microsieverts
double uSv;
switch (Ethernet.maintain()) {
case 1:
//renewed fail
Serial.println(F("ERROR: DHCP Renewal Failure"));
break;
case 2:
//renewed success
Serial.println(F("SUCCESS: DHCP Renew"));
//print your local IP address:
Serial.print(F("IP Address: "));
Serial.println(Ethernet.localIP());
break;
case 3:
//rebind fail
Serial.println(F("ERROR: Rebind failure"));
break;
case 4:
//rebind success
Serial.println(F("SUCCESS: Rebind"));
//print your local IP address:
Serial.print(F("IP Address: "));
Serial.println(Ethernet.localIP());
break;
default:
//nothing happened
break;
}
if (now - then > AVG_PERIOD) {
then = now;
if (counts) { // i.e., if (counts != 0)
cpm = counts * mult;
uSv = cpm * CONV_FACTOR;
}
else {
uSv = 0;
}
Serial.print(F("Counts: "));
Serial.println(counts);
Serial.print(F("CPM: "));
Serial.println(cpm);
Serial.print(F("uSv/hr: "));
Serial.println(uSv, 4); // Display 4 decimal places
//convert both numbers to cstrings for MQTT publish
itoa(cpm, CountString, 10);
dtostrf(uSv, 5, 5, DoseString);
counts = 0, cpm = 0; //reset the counts fo rnext loop
Serial.print(F("MQTT Publish:"));
Serial.print(CountTopic);
Serial.println(CountString);
Serial.print(F("MQTT Publish:"));
Serial.print(DoseTopic);
Serial.println(DoseString);
MQTTClient.publish(CountTopic, CountString);
MQTTClient.publish(DoseTopic, DoseString);
}
}
Hi. I have the CAJOE version of the Radiation detector. I calibrated it, and it powers up fine, and beeps and has VIN drop low on an oscilloscope when it clicks from background radition.
I have an Olimex ESP32-POE-ISO unit that is powered by POE (the final home of this is on my roof, and thanks to mylar coated sheathing there is no WiFi up there. I am powering the geiger counter from the Olimex 5V and GND pins, and again, works just fine. I have the VIN pin wired to GPIO36, and tested the wiring for continuity, but for the life of me, the Olimex isn’t seeing any pulses. Everything just says 0…
Here is the code in esphome that I am using:
esphome:
name: radiation-monitor
platform: ESP32
board: esp32-poe
ethernet:
type: LAN8720
mdc_pin: GPIO23
mdio_pin: GPIO18
clk_mode: GPIO17_OUT
phy_addr: 0
power_pin: GPIO12
# Enable logging
logger:
text_sensor:
- platform: template
name: Uptime Human Readable
id: uptime_human
icon: mdi:clock-start
# Sensors with general information.
sensor:
# Uptime sensor.
- platform: uptime
name: Geiger Counter Uptime
id: uptime_sensor
update_interval: 60s
on_raw_value:
then:
- text_sensor.template.publish:
id: uptime_human
state: !lambda |-
int seconds = round(id(uptime_sensor).raw_state);
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
return (
(days ? to_string(days) + "d " : "") +
(hours ? to_string(hours) + "h " : "") +
(minutes ? to_string(minutes) + "m " : "") +
(to_string(seconds) + "s")
).c_str();
- platform: pulse_counter
pin: GPIO36
name: "Geiger Counter"
id: "geiger_counter"
unit_of_measurement: 'CPM'
on_raw_value:
- sensor.template.publish:
id: radiation_level
state: !lambda 'return x / 153.8;'
- platform: template
name: "Radiation Level"
id: "radiation_level"
unit_of_measurement: 'µSv/h'
icon: mdi:radioactive
accuracy_decimals: 5
Any ideas as why this isn’t working? The board documentation says pin 36 is available for input and has an internal pullup: https://www.olimex.com/Products/IoT/ESP32/ESP32-POE-ISO/resources/ESP32-POE-ISO-GPIO.png
Thanks!
There are no ideas. Everything looks correct at first glance.
ESPhome pulse counter enable pcnt by default on esp32.
You have to disable it to make the cajoe geiger working.
Try to add this line to the pulse counter definition:
use_pcnt: false
Also i had some problems with GPIO36, I have had better results with a pin without ADC.
That line doesn’t work in the pule counter definition. Where does it go?
I have tried GPIO35, but what other pin would you recommend?
I use this code on my esp32 (az-delivery v4):
- platform: pulse_counter
pin: GPIO17
use_pcnt: false
name: "Counts per minute"
id: "geiger_counter"
unit_of_measurement: 'CPM'
on_raw_value:
- sensor.template.publish:
id: radiation_level
state: !lambda 'return x / 153.8;'
Ah, I was using pulse_meter and not pulse counter. That is not an option for the pulse meter.
thx!
Well, I tried pulse_counter with the use_pcnt on my olimex esp32-poe, but still no go. Which pin would you recommend if not an ADC pin? I don’t have a GPIO17 on the olimex.
BTW, the problem was indeed the GPIO36 pin. When I used GPIO4 on my Olimex POE ESP32 board, everything worked fine!
Hello.
You don’t know why RadiationD CJAOE works great with wemos d1 mini pro on pin D7
but it doesn’t respond at all to esp32? on any pin?
connected from the VIN pin on the module directly to the GPIO (I also tried a divider on the esp32)
EDIT:
Only 36 VP gpio pin solved problem.
https://community.home-assistant.io/t/pulse-counter-pin-goes-high/140151/2?u=tiimsvk
this pin and probably also VN gpio 39 have a higher resolution than the others? why does the esp8266 handle it without problems?
Don’t know why - GPIO4 and GPIO36 pins are both ADC pins, but this site: ESP32 Pinout Reference: Which GPIO pins should you use? | Random Nerd Tutorials says GPIO36 is input only, so has no pullups on it.
We have recently made a new GitHub repo didicated for GGreg20_V3 + generic ESP32 with pulse counter GPIO debounce in microseconds up to SBM20 GM tube’s deadtime (190us). And tested this yaml-config on an ESP32 Wroom (NodeMCU-like module) and used GPIO23 as a pulse counter input.
Previously, we did not notice that the ESPHome Pulse Counter API has the ability to apply a low-pass filter. We hope that this example will help many users to counteract the bounce that can sometimes occur in GM-tubed and high voltage systems.
As I completed the weather station and installed the geiger counter, only then did I find a solution using
internal_filter: 190us..
It doesn’t matter, it works well on the high impedance pin