Das Projekt realisiert die Messung der Füllstandshöhe in der Zisterene mit einem ESP8266 und dem Ultraschallsensor US100. Die Daten werden dann mittels MQTT and FHEM gesendet und in FHM visualisiert.
Die Schaltung gestallet sich recht einfach. Es wird ein ESP8266 ( am besten mit Antennenanschluss) benötigt und ein US100 Ultraschall Sensor.

Der Quellcode
Programmiert wurde mit VisualCode und PlatformIO. Es werden mehrere Messungen durchgeführt und die Ergebnisse gemittelt und über MQTT and FHEM gesendet. Nach erfolgreicher Messung wird der ESP32 in den DeepSleep Modus für ca. 1 Stunden versetzt. In diesem Modus verbraucht er sehr wenig Strom.

/*
* This sketch measure the distance from top to the watersurface of the zysterne
*
*
*
*
*/
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <MQTTClient.h>
#include <SoftwareSerial.h>
#define _TEST
#define STAND "/Zysterne/Stand"
#define TEMP "/Zysterne/Temperatur"
#define WifiRSSI "/Zysterne/RSSI"
#define ZQM "/Zysterne/QM"
#define ZINFO "/Zysterne/Info"
const char* ssid = "****";
const char* password = "****";
const char* host = "192.168.xxx.xxx";
//FHEM Host
int nVal = 0;
// 4294967295 max time
// 1 Second 1000000 -- 60*60* 1000000;
unsigned long sleepTimeS = 4294967295;
long interval = 1000*10;
int nLed = 4;
int trigPin = 5; //Trig
int echoPin = 4; //Echo
long temperatur = 0;
int nSendState = 0;
int nState = 0;
int nResendCount = 0;
unsigned long previousMillis = 0;
bool bFinish = false;
int nUS100MeasureState = 0;
#ifdef ESP8266
extern "C" {
#include "user_interface.h"
}
#endif
const int US100_TX = 5;
const int US100_RX = 4;
// Instancia nuevo canal serie
SoftwareSerial US100Serial(US100_RX, US100_TX);
MQTTClient mqtt;
WiFiClient net;
#define BAUD 115200
void setup() {
Serial.begin(9600);
US100Serial.begin(9600);
delay(10);
WiFi.begin(ssid, password);
mqtt.begin(host, net);
mqtt.onMessage(messageReceived);
pinMode(nLed, OUTPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
digitalWrite(nLed, LOW);
}
bool ConnectWifi()
{
Serial.print("Connecting to ");
Serial.println(ssid);
int nCount = 0;
while(WiFi.waitForConnectResult() != WL_CONNECTED)
{
if( nCount >= 10 )
return false;
WiFi.begin(ssid, password);
Serial.println("WiFi connection failed. Retry.");
delay(1000);
nCount++;
}
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.print("RSSI:");
Serial.println(WiFi.RSSI());
PrintMqttInfo("IP address: " + String(WiFi.localIP()) );
PrintMqttInfo("RSSI: " + String(WiFi.RSSI()) );
return true;
}
//------------------------------------------------------------------------------------------------------------------
void loop()
{
mqtt.loop();
if( nState >= 1 && !bFinish )
{
SendToFhem();
return;
}
if( bFinish)
{
unsigned long currentMillis = millis();
delay(100);
if (currentMillis - previousMillis < 2000 )
return;
if( nSendState < 4 && nResendCount < 5)
{
Serial.println("Resending....");
nState = 1;
nSendState = 0;
bFinish = false;
nResendCount++;
}
else
CloseAll();
return ;
}
delay(2000);
#ifdef _TEST
ConnectWifi() ;
#endif
bool bOk = false;
int nCount = 10;
while( !bOk )
{
PrintMqttInfo("Reading US100: " + String(nCount));
int n1 = ReadingUS100();
PrintMqttInfo("N1: "+String(n1));
nVal = ReadingUS100();
PrintMqttInfo("N2: "+ String(nVal));
int nDiff = abs(nVal-n1);
PrintMqttInfo("Diff - "+ String(nDiff));
if( nDiff < 100 && nUS100MeasureState == 2 )
{
PrintMqttInfo("Read finish...");
bOk = true;
continue;
}
nCount--;
if( nCount <= 0)
{
PrintMqttInfo("Going to deepSleep....");
mqtt.loop();
ESP.deepSleep(10000 );
}
delay(1000);
}
if( ConnectWifi() )
nState = 1;// Starts
else
CloseAll();
}
//------------------------------------------------------------------------------------------------------
void PrintMqttInfo(String val)
{
Serial.println(val);
#ifndef _TEST
return;
#endif
SendMQTT(ZINFO,val);
}
int ReadingUS100()
{
int nCount = 2;
int n = 0;
for( int i = 0; i < nCount; i++ )
{
n += MeasurePingRx();//random(60,105);
delay(500);
}
return n/nCount;
}
//------------------------------------------------------------------------------------------------------
void CloseAll()
{
mqtt.disconnect();
net.stop();
Serial.println();
Serial.println("closing connection");
WiFi.disconnect();
delay(1000);
while (WiFi.status() == WL_CONNECTED )
{
delay(100);
Serial.println("Disconnecting..");
}
delay(4000);
//DeepSleep
ESP.deepSleep(sleepTimeS );
}
bool ConnectMQTT()
{
if( mqtt.connected() )
return true;
Serial.println("Connecting mqtt....");
while (!mqtt.connect(host))
{
Serial.print(".");
delay(200);
}
delay(200);
mqtt.subscribe(STAND);
mqtt.subscribe(WifiRSSI);
mqtt.subscribe(TEMP);
mqtt.subscribe(ZQM);
#ifdef _TEST
mqtt.subscribe(ZINFO);
#endif
return true;
}
//------------------------------------------------------------------------------------------------------------------
bool SendToFhem()
{
Serial.println("Sending... ");
switch(nState)
{
case 1: SendMQTT(STAND, String(nVal));
nState++;
break;
case 2:
{
double qm = (1650 - nVal) * 0.0041547;
SendMQTT(ZQM, String(qm));
nState++;
}
break;
case 3:
SendMQTT(TEMP, String(temperatur));
nState++;
break;
case 4:
SendMQTT(WifiRSSI, String(WiFi.RSSI()));
nState++;
bFinish = true;
break;
}
previousMillis = millis();
return true;
}
//------------------------------------------------------------------------------------------------------------------
bool SendMQTT(String key,String val)
{
ConnectMQTT();
Serial.print(key); Serial.println(val);
mqtt.publish(key, String(val));
mqtt.loop();
return true;
}
//-----------------------------------------------------------------------------------------------------------------------------------------
int MeasurePingRx()
{
unsigned int HighLen = 0;
unsigned int LowLen = 0;
unsigned int Len_mm = 0;
unsigned int temp = 0;
Serial.print("Read.... ");
US100Serial.flush();
US100Serial.write(0x55);
delay(1000);
nUS100MeasureState = 0;
if(US100Serial.available() >= 2)
{
nUS100MeasureState++;
HighLen = US100Serial.read();
LowLen = US100Serial.read();
Len_mm = HighLen * 256 + LowLen; // Distanz
if((Len_mm > 1) && (Len_mm < 10000)) // c
{
Serial.print("Distancia: ");
Serial.print(Len_mm, DEC);
Serial.println(" mm");
PrintMqttInfo("Distanz: "+ String(Len_mm) + " mm");
}
}
US100Serial.flush();
US100Serial.write(0x50);
delay(1000);
if(US100Serial.available() >= 1)
{
nUS100MeasureState++;
temp = US100Serial.read();
if((temp > 1) && (temp < 130))
{
temp -= 45; // corrige offset de 45º
temperatur = temp;
Serial.print("Temperatur: ");
Serial.print(temp, DEC);
Serial.println(" C.");
PrintMqttInfo("Temperatur: "+ String(temp,DEC) + " C");
}
}
return Len_mm;
}
//------------------------------------------------------------------------------------------------------------------
void messageReceived(String &topic, String &payload) {
Serial.print("incoming: ");
Serial.print(topic);
Serial.print(" - ");
Serial.print(payload);
Serial.println();
if( topic.compareTo(STAND) == 0 )
nSendState++;
else
if( topic.compareTo(ZQM) == 0 )
nSendState++;
else
if( topic.compareTo(TEMP) == 0 )
nSendState++;
else
if( topic.compareTo(WifiRSSI) == 0 )
nSendState++;
Serial.print("State: ");
Serial.println(nSendState);
}
//------------------------------------------------------------------------------------------------------------------