Skip to content

Instantly share code, notes, and snippets.

@SyncChannel
Created February 1, 2016 01:17
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save SyncChannel/ffe320953fa26d3ab9b5 to your computer and use it in GitHub Desktop.
Save SyncChannel/ffe320953fa26d3ab9b5 to your computer and use it in GitHub Desktop.
MightyOhm Geiger Counter Wi-Fi and OLED Upgrade Example
// Example Program for MightyOhm Geiger Counter FeatherWing + OLED Upgrade
// This example is specifically for use with Adafruit Feather HUZZAH (ESP8266)
// It will also work with other Feather boards with modifications
//
// By: Dan Watson
// syncchannel.blogspot.com
// 1/31/2016
// This program makes use of the EspSoftSerial library to receive data from the Geiger counter.
// EspSoftwareSerial: https://github.com/scottwday/EspSoftSerial
// Thank you scottwday for this useful library!
// The Adafruit MQTT, MQTT_Client, GFX, and SSD1306 libraries are also used. Official documentation:
// https://learn.adafruit.com/adafruit-feather-huzzah-esp8266/overview
// https://learn.adafruit.com/adafruit-io/mqtt-api
// https://learn.adafruit.com/monochrome-oled-breakouts
// All of the MQTT code below is borrowed from Adafruit's example programs. Thank you!
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <CircularBuffer.h>
#include <EspSoftSerialRx.h>
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#define WLAN_SSID "your ssid here"
#define WLAN_PASS "your password here"
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883
#define AIO_USERNAME "your Adafruit IO user name here"
#define AIO_KEY "your Adafruit IO private key here"
/************ Global State (you don't need to change this!) ******************/
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
// Store the MQTT server, username, and password in flash memory.
// This is required for using the Adafruit MQTT library.
const char MQTT_SERVER[] PROGMEM = AIO_SERVER;
const char MQTT_USERNAME[] PROGMEM = AIO_USERNAME;
const char MQTT_PASSWORD[] PROGMEM = AIO_KEY;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, MQTT_SERVER, AIO_SERVERPORT, MQTT_USERNAME, MQTT_PASSWORD);
/****************************** Feeds ***************************************/
// Modify these feed names to match what you created on Adafruit IO
const char CPS_FEED[] PROGMEM = AIO_USERNAME "/feeds/GeigerCPS";
Adafruit_MQTT_Publish cpsfeed = Adafruit_MQTT_Publish(&mqtt, CPS_FEED);
const char CPM_FEED[] PROGMEM = AIO_USERNAME "/feeds/GeigerCPM";
Adafruit_MQTT_Publish cpmfeed = Adafruit_MQTT_Publish(&mqtt, CPM_FEED);
const char SIEVERTS_FEED[] PROGMEM = AIO_USERNAME "/feeds/GeigerSieverts";
Adafruit_MQTT_Publish sievertsfeed = Adafruit_MQTT_Publish(&mqtt, SIEVERTS_FEED);
/****************************************************************************/
#define buttonA 0
#define buttonB 16
#define buttonC 2
#define rxPin 13
Adafruit_SSD1306 display;
EspSoftSerialRx SerialGeiger;
#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
// Used to store strings arriving from geiger counter
String geigerSerial;
// Storage for stats
int cps = 0;
int cpm = 0;
float sieverts = 0;
// Misc variables for mode and monitoring
uint8_t mode = 1;
unsigned long geigerTimeout = 0;
bool geigerConnected = false;
uint8_t publishCounter = 0;
bool publishStatus = false;
void setup()
{
// String from geiger counter will be echoed on USB Serial
// Software serial Rx-only is used to receive the string from the geiger counter
Serial.begin(9600);
SerialGeiger.begin(9600, rxPin);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
// All three buttons on the OLED FeatherWing are used in this example
pinMode(buttonA, INPUT_PULLUP);
pinMode(buttonC, INPUT_PULLUP);
pinMode(buttonC, INPUT_PULLUP);
display.clearDisplay();
// Connect to WiFi access point.
Serial.println(); Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: "); Serial.println(WiFi.localIP());
}
void loop()
{
// Check if a button is pressed and change mode accordingly
bool gotButton = false;
if (!digitalRead(buttonA))
{
mode = 1;
gotButton = true;
}
else if (!digitalRead(buttonB))
{
mode = 2;
gotButton = true;
}
else if (!digitalRead(buttonC))
{
mode = 3;
gotButton = true;
}
if (gotButton)
delay(50); // Debounce
// End of button checking
// Monitor the serial connection from the geiger counter.
// If it is absent for > 3 seconds, display a warning to the user
if (millis() > (geigerTimeout + 3000) && geigerConnected == true)
{
geigerConnected = false;
display.setTextColor(WHITE);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,8);
display.println("GEIGER COUNTER");
display.println("NOT CONNECTED!");
display.display();
}
// End of serial connection monitoring
// Attempt to receive a serial character from the geiger counter
// If we got one, append it to the string
// If we got a new line character, parse the string and update the display
// The strings arrive about once a second, so this loop is also used for timing of publish events
unsigned char b;
if(SerialGeiger.read(b))
{
geigerSerial += char(b);
if (b == 0x0A) // New line, end of string. We need to parse.
{
Serial.print(geigerSerial); // Echo the string to USB serial for potential PC monitoring
geigerConnected = true; // Record that serial connection health is ok
geigerTimeout = millis();
publishCounter++; // When this gets to five (five seconds passed) we will publish
SerialGeiger.service(); // Periodic service routine required for this library
// Parse CPS, CPM, and uS/hr from the string
int comma1Index = geigerSerial.indexOf(',');
int comma2Index = geigerSerial.indexOf(',', comma1Index + 1);
int comma3Index = geigerSerial.indexOf(',', comma2Index + 1);
int comma4Index = geigerSerial.indexOf(',', comma3Index + 1);
int comma5Index = geigerSerial.indexOf(',', comma4Index + 1);
int comma6Index = geigerSerial.indexOf(',', comma5Index + 1);
String cpsString = geigerSerial.substring(comma1Index+1,comma2Index);
String cpmString = geigerSerial.substring(comma3Index+1,comma4Index);
String sievertsString = geigerSerial.substring(comma5Index+1,comma6Index);
cps = cpsString.toInt();
cpm = cpmString.toInt();
sieverts = sievertsString.toFloat();
geigerSerial = ""; // Clear the string for next time
// Update the display depending on what mode we are in
// Lots of potential to modify/improve this. You could do cool stuff like graphing!
switch (mode) {
case 1: // Stats
display.setTextColor(WHITE);
display.setTextSize(1);
display.clearDisplay();
display.setCursor(4,8);
display.print("CPS:");
display.print(cps);
display.print(" | CPM:");
display.print(cpm);
display.setCursor(4,20);
display.print("uSv/hr: ");
display.println(sieverts);
display.display();
break;
case 2: // CPM only in large text for greater visibility
display.setTextColor(WHITE);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(2,19);
display.print("CPM:");
display.setTextSize(3);
display.setCursor(30,4);
display.print(cpm);
display.display();
break;
case 3: // Status of Wi-Fi, publishing, and IP address
display.setTextSize(1);
display.setTextColor(WHITE);
display.clearDisplay();
display.setCursor(2,8);
display.print("Wi-FI: ");
if (WiFi.status() != WL_CONNECTED)
display.println("Not Connected");
else if (!publishStatus)
display.println("Can't Publish");
else
display.println("Connected");
display.setCursor(2,20);
display.print("IP: ");
display.println(WiFi.localIP());
display.display();
break;
}
}
}
MQTT_connect();
// We publish every five seconds to Adafruit IO
// If any publish attempt fails, the user will be notified on the Mode 3 screen
if (publishCounter >= 5)
{
publishCounter = 0;
bool publishResults = true;
if (!cpsfeed.publish(cps))
publishResults = false;
delay(10);
if (!cpmfeed.publish(cpm))
publishResults = false;
delay(10);
if (!sievertsfeed.publish(sieverts))
publishResults = false;
publishStatus = publishResults;
}
}
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
}
Serial.println("MQTT Connected!");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment