/************************************************************************* * 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//PubSubClient library for MQTT #include //ethernet related includes #include #include //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.107.11" 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); } }