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);
}
}