Skip to content

Instantly share code, notes, and snippets.

@Xitee1
Created October 30, 2022 18:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xitee1/5ede55927c9a37c06dc6015e38e46d51 to your computer and use it in GitHub Desktop.
Save Xitee1/5ede55927c9a37c06dc6015e38e46d51 to your computer and use it in GitHub Desktop.
This is a modified version of https://tutorials-raspberrypi.de/esp8266-regensensor-selber-bauen-wie-viel-pro-qm/ . I made lots of changes and made the code a bit cleaner looking (at least for me it is). Some main features are WiFi sleep to reduce power consumption, INBUILT_LED blinking on detections and overall a few "improvements".
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
// WiFi
#define WIFI_AP "WiFi SSID"
#define WIFI_PASSWORD "Password"
// MQTT
#define MQTT_SERVER "192.168.x.x" // MQTT Server IP (e.g. the IP of HA)
#define MQTT_USER "mqtt" // MQTT username
#define MQTT_PASSWORD "password"
#define MQTT_CLIENT "Regensensor1" // Device name
#define MQTT_TOPIC "esp/sensor/regen" // Topic
int triggerPin = 16; // The stick reading about it tipped.
int totalCount = 0; // a simple calculator that adds how many tipping it has done since its start.
const char* mmPerSquareMeter = "0.094175";// 1.25 ml per dipper change, 94.175 ml per m^2 (=1.25*75.34), = 0.094175mm/m^2
// diameter of raingauge is about 130mm, r = 65mm, surface = pi*r^2 = 132.73 cm^2
// therefore per m^2 (=10000cm^2) we have a factor of about 75.34
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
// Outcomment for debugging
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(triggerPin, INPUT);
digitalWrite(LED_BUILTIN, LOW);
connectWiFi();
connectMQTT();
digitalWrite(LED_BUILTIN, HIGH);
}
int lastState = 0; // The last reading
// Timers
unsigned long wifiEnergySave = 0;
void loop() {
int currentState = digitalRead(triggerPin);
// Checks whether the previous loop has the same loop as the current loop. Will not go into this first loop.
if(currentState == 0) {
digitalWrite(LED_BUILTIN, LOW);
wifiEnergySave = millis(); // Reset WiFi energy save
totalCount++; // Count the detections
delay(50); // Little delay in case that WiFi was put in sleep in the last loop (insanely rare I think, but just in case)
// Wake WiFi from sleep (if not already connected)
if(WiFi.status() != WL_CONNECTED) {
WiFi.mode(WIFI_STA);
connectWiFi();
connectMQTT();
}
// Generate Json
StaticJsonDocument<128> doc;
doc["name"] = "Regensensor 1";
doc["count_since_boot"] = totalCount;
// Check if state is not last state
// If it is, the "wipper?" likely hangs somewhere in the middle
if(currentState == lastState) {
doc["mm"] = 0.0;
doc["error"] = "1";
} else {
doc["mm"] = mmPerSquareMeter;
doc["error"] = "0";
}
char JSONmessageBuffer[128];
serializeJson(doc, JSONmessageBuffer);
// Send data
if(client.publish(MQTT_TOPIC, JSONmessageBuffer)) {
Serial.println("Sent data!");
}else{
Serial.println("Failed to send data!");
}
digitalWrite(LED_BUILTIN, HIGH);
delay(1000); // Only allow one change per second in case it changes 2 times really quickly
}
lastState = currentState;
/*
* Set WiFi to sleep after 30 minutes of no detections
* This reduces the power consumption nearly 4 times (700mA to 200mA) on the Wemos D1 mini
*
* Why only after 15 minutes?
* The WiFi takes a few seconds to reconnect. In a heavy rain, it would have to
* disconnect and reconnect really often (maybe even scipping a detection while connecting).
* With the delay, in a heavy rain it will not disconnect.
*
*/
if((millis() - wifiEnergySave) > 1000 * 60 * 15) {
if(WiFi.status() == WL_CONNECTED) {
client.disconnect();
WiFi.mode(WIFI_OFF);
WiFi.forceSleepBegin();
Serial.println("Put WiFi to sleep");
}
}
// Make sure that MQTT stays conencted
if(client.connected()) {
client.loop();
}
}
// WiFi and MQTT stuff
void connectWiFi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(WIFI_AP);
WiFi.begin(WIFI_AP, WIFI_PASSWORD);
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void connectMQTT() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
client.setServer(MQTT_SERVER, 1883);
// Attempt to connect
// If you do not want to use a username and password, change next line to
//if (client.connect(MQTT_CLIENT_NAME)) {
if (client.connect(MQTT_CLIENT, MQTT_USER, MQTT_PASSWORD)) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment