Update: 2023-02-12
Esp8266 Nodemcu Gaszähler Thingspeak
Auslesen des Gaszählers Elster BK-G4M mittels Reedrelais.
Die meisten mechanischen Gaszähler besitzen bereits ab Werk einen Impulsmagneten in der letzten Stelle des Rollenzählwerkes
und können einfach mit einem Impulsnehmer ausgestattet werden. Ob der Gaszähler dafür geeignet ist, erkennt man an einem Aufdruck
wie z.B. "1 Imp ? 0,01 m³" auf dem Typenschild.
Funktionen
Zur Anzeige vom Zähler Impuls wird die Onboard Led des Nodemcu genutzt. Die OnBoardLed des Esp 12E wird als Heartbeat-LED verwendet.
Dein händisch eingegebener Zählerstand wird in einer Datei im Flash des Esp8266 gespeichert und bei jedem Neustart aus dieser eingelesen.
Der Zählerstand wird, vorausgesetzt der Wert hat sich geändert, aller 4 Stunden erneut abgespeichert.
Ansicht Gaszähler im Webrowser.
Webinterface
Hier kannst du den aktuellen Zählerstand eingeben. Die Leds der optischen Anzeige schalten.
Der Zählerstand im Browser wird aller 5 Sekunden aktualisiert.
Die vergangene Zeit seit dem letzten Sendefehler wird bei aufgeklappter Eingabemaske angezeigt.
Beim Klick in den Bereich der Zähleranzeige erscheint die Eingabemaske.
Hier lassen sich auch beide Leds schalten.
Thingspeak Datenlogger
Aller 5 Minuten wird der aktuelle Stand der Gasuhr an deinen Thingspeak Account gesendet.
Die Antwort von Thingspeak, ob die Übertragung erfolgreich war, wird nicht blockierend ausgewertet. Im Fehlerfall wird der Zählerstand erneut zu Thingspeak gesendet.
Anzeige des letzten Sendefehler zu Thingspeak.
Da sich bei mir, als Holzheizer, der Gaszähler nur an extrem kalten Wintertagen dreht,
nochmals vielen Dank an Andreas für die ausführlichen praktischen Tests und Rückmeldungen.
Download Projekt
Der Sketch zum Gasuhr auslesen übersichtlich aufgeteilt in Tabs.
Gaszaehler.ino
// ****************************************************************
// Sketch Gaszähler Modular(Tab)
// created: Jens Fleischer, 2018-03-30
// last mod: Jens Fleischer, 2023-02-12
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// D2 = GPIO4 Anschluss Reedrelais vom GPIO4 auf GND
// 10k Pullup-Widerstand von VCC auf GPIO4
// Versorgung über USB
// Software: Esp8266 Arduino Core 2.6.0 - 3.1.1
// Getestet auf: Nodemcu
/******************************************************************
Copyright (c) 2018 Jens Fleischer. All rights reserved.
This file is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
*******************************************************************/
// Der WebServer Tab ist der Haupt Tab mit "setup" und "loop".
// #include <LittleFS.h> #include <ESP8266WebServer.h> müssen im Haupttab aufgerufen werden
// Die Funktionalität des ESP8266 Webservers ist erforderlich.
// Inklusive Arduino OTA-Updates (Erfordert freien Flash-Speicher )
/**************************************************************************************/
#include <ESP8266WebServer.h> // http://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/readme.html#server
#include <ArduinoOTA.h> // http://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html
#include <LittleFS.h> // http://arduino-esp8266.readthedocs.io/en/latest/filesystem.html
const byte inputPIN = D2; // Reedrelais
const byte HeartbeatLed = D4; // OnBoardLed Esp 12E
const byte CounterLed = D0; // OnBoardLed NodeMcu 1.0
unsigned long value, oldvalue;
bool ledz = HIGH, ledh = LOW; // Merker für ZählerLed AN/Aus , Merker für HeartbeatLed AN/Aus
unsigned long lastError; // Zeitpunkt des letzten Fehlers
ESP8266WebServer server(80);
void setup() {
Serial.begin(115200);
delay(100);
Serial.printf("\n\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
(__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());
pinMode(HeartbeatLed, OUTPUT);
pinMode(CounterLed, OUTPUT);
digitalWrite(HeartbeatLed, HIGH);
connectWifi(); // ruft die Funktion zum Verbinden mit dem Wlan auf
webpage(); // ruft die Funktion zum bereitstellen einer Webseite auf
Serial.println(LittleFS.begin() ? "LittleFS gestartet!" : "Sketch wurde mit \"FS:none\" kompilliert!\n");
server.begin();
Serial.println("HTTP Server gestartet!\n");
ArduinoOTA.onStart([]() { // Zählerstand speichern bevor OTA Update
save();
});
ArduinoOTA.begin();
File f = LittleFS.open("/value.txt", "r"); // Zählerstand beim Neustart aus Datei lesen
String str = f.readStringUntil('\n');
value = str.toInt();
oldvalue = value;
f.close();
}
void loop() {
static unsigned long letzterAufruf = 0;
ArduinoOTA.handle();
server.handleClient();
zaehlerauslesen(); // Funktionsaufruf
char buf[12];
snprintf(buf, sizeof(buf), "%li.%02li", value / 100, value % 100);
if (!thingspeak(buf)) {
lastError = millis() / 1000;
}
ledh ? digitalWrite(HeartbeatLed, millis() % 500 >= 250) : digitalWrite(HeartbeatLed, HIGH); // LED zeigt an das der Sketch läuft
unsigned long aktuelleMillis = millis();
if (aktuelleMillis - letzterAufruf >= 60000UL * 240 && value != oldvalue) { // Zählerstand speichern, aller 4 Stunden, wenn der Wert sich geändert hat.
save();
oldvalue = value;
letzterAufruf = aktuelleMillis;
}
}
void zaehlerauslesen() {
bool aktueller = 1;
static bool vorheriger = 1;
static unsigned long letzteMillis = 0;
unsigned long aktuelleMillis = millis();
if (aktuelleMillis - letzteMillis >= 1000) { // Das Reedrelais wird einmal pro Sekunde abgefragt
aktueller = digitalRead(inputPIN);
if (!aktueller && aktueller != vorheriger) {
value++;
}
vorheriger = aktueller;
letzteMillis = aktuelleMillis;
}
!ledz ? digitalWrite(CounterLed, HIGH) : !vorheriger ? digitalWrite(CounterLed, millis() % 500 >= 250) : digitalWrite(CounterLed, HIGH); // LED blinkt wenn Reedrelais geschlossen
}
void save() {
File f = LittleFS.open("/value.txt", "w");
f.printf("%li\n", value);
f.close();
}
In diesem Tab, deine Zugangsdaten vom Netzwerk eintragen.
Connect.ino
// ****************************************************************
// Sketch Esp8266 Connect STA Modular(Tab) mit optischer Anzeige
// created: Jens Fleischer, 2018-04-08
// last mod: Jens Fleischer, 2020-12-28
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.4.2 - 3.1.1
// Getestet auf: Nodemcu, Wemos D1 Mini Pro, Sonoff Dual
/******************************************************************
Copyright (c) 2018 Jens Fleischer. All rights reserved.
This file is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
*******************************************************************/
// Diese Version von Connect STA sollte als Tab eingebunden werden.
// #include <ESP8266WebServer.h> oder #include <ESP8266WiFi.h> muss im Haupttab aufgerufen werden
// Die Funktion "connectWifi();" muss im Setup eingebunden werden.
/**************************************************************************************/
//#define CONFIG // Einkommentieren wenn der ESP dem Router die IP mitteilen soll.
#define NO_SLEEP // Auskommentieren wenn der Nodemcu den deep sleep Modus nutzt.
const char* ssid = "Netzwerkname"; // << kann bis zu 32 Zeichen haben
const char* password = "PasswortvomNetzwerk"; // << mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen
#ifdef CONFIG
IPAddress staticIP(192, 168, 178, 99); // Statische IP des NodeMCU ESP8266
IPAddress gateway(192, 168, 178, 1); // IP-Adresse des Router
IPAddress subnet(255, 255, 255, 0); // Subnetzmaske des Netzwerkes
IPAddress dns(192, 168, 178, 1); // DNS Server
#endif
void connectWifi() { // Funktionsaufruf "connectWifi();" muss im Setup eingebunden werden.
byte i = 0;
//WiFi.disconnect(); // Nur erforderlich wenn Esp den AP Modus nicht verlassen will.
WiFi.persistent(false); // Auskommentieren wenn Netzwerkname und Passwort in den Flash geschrieben werden sollen.
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
#ifdef CONFIG
WiFi.config(staticIP, gateway, subnet, dns);
#endif
while (WiFi.status() != WL_CONNECTED) {
#ifdef NO_SLEEP
pinMode(LED_BUILTIN, OUTPUT); // OnBoardLed Nodemcu, Wemos D1 Mini Pro
digitalWrite(LED_BUILTIN, 0);
#endif
delay(500);
digitalWrite(LED_BUILTIN, 1);
delay(500);
Serial.printf(" %d sek\n", ++i);
if (i > 9) {
Serial.print("\nVerbindung zum AP fehlgeschlagen !\n\n");
ESP.restart();
}
}
Serial.println("\nVerbunden mit: " + WiFi.SSID());
Serial.println("Esp8266 IP: " + WiFi.localIP().toString());
}
HTML.ino
// ****************************************************************
// Sketch Gaszähler Webinterface Modular(Tab)
// created: Jens Fleischer, 2018-04-08
// last mod: Jens Fleischer, 2023-02-12
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.6.0 - 3.1.1
// Getestet auf: Nodemcu
/******************************************************************
Copyright (c) 2018 Jens Fleischer. All rights reserved.
This file is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
*******************************************************************/
// #include <ESP8266WebServer.h> muss im Haupttab aufgerufen werden.
// Die Funktionalität des ESP8266 Webservers ist erforderlich.
// Die Funktion "webpage();" muss im Setup eingebunden werden.
/**************************************************************************************/
void webpage() {
server.on("/", handleRoot);
server.on("/favicon.ico", handleIcon);
server.on("/status", handleStatus);
server.on("/ledh", []() {
ledh = !ledh;
handleStatus();
});
server.on("/ledz", []() {
ledz = !ledz;
handleStatus();
});
}
void handleStatus() {
if (server.arg(0).length() > 0 && server.arg(0).length() <= 7) {
value = server.arg(0).toInt();
save(); // Benutzer Eingabe in der Datei speichern
Serial.printf("Zählerstand vom Client: %ld\n", value);
}
char buf[42];
snprintf(buf, sizeof(buf), "[\"%05ld,%02ld9 m³\",\"%d\",\"%d\",\"%s\"]", value / 100, value % 100, ledh, ledz, errorTime().c_str());
server.send(200, "application/json", buf); // Zählerstand und Led Status an Html Seite senden
}
String errorTime() { // ermittelt die vergangene Zeit seit dem letztem Verbindungsfehler zu Thingspeak
if (lastError > 0) {
String Time = "";
uint8_t mm = (millis() / 1000 - lastError) / 60 % 60;
uint16_t hh = ((millis() / 1000 - lastError) / 60) / 60;
if (hh > 240) lastError = 0; // nach 10 Tagen ohne Fehler, wird die Fehleranzeige zurückgesetzt
if (hh < 10)Time += "0";
Time += (String)hh + ":";
if (mm < 10)Time += "0";
Time += (String)mm;
return Time;
}
return "0";
}
void handleRoot() { // Html Webseite, der Zählerstand wird aller 5 Sekunden mittels fetch.api aktuallisiert
String temp = "<!DOCTYPE HTML><html lang='de'><head><meta charset='UTF-8'><meta name='viewport' content='width=device-width, initial-scale=1'><title>Gaszähler</title><script>";
temp += "addEventListener('load',()=>{let h=document.querySelector('#ledh'),z=document.querySelector('#ledz');let i=document.querySelector('input'),n=document.querySelector('#note');";
temp += "document.querySelector('#grey').addEventListener('click',()=>t());z.addEventListener('click',()=>s('ledz'));h.addEventListener('click',()=>s('ledh'));i.addEventListener('blur',";
temp += "()=>{!i.checkValidity()?(n.innerHTML=i.validationMessage,n.classList.add('note')):s('status',i.value)});function t(){let x=document.getElementById('no');getComputedStyle(x).";
temp += "display==='none'?x.style.display='flex':x.style.display='none';n.innerHTML='';n.classList.remove('note');i.value=''}async function s(p='status',v){if(Number.isInteger(parseInt";
temp += "(v)))t();let r=await fetch(p,{method:'POST',body:v});let j=await r.json();document.querySelector('span').innerHTML=j[0];j[1]=='0'?(h.innerHTML='LED Off',h.classList.add('off')):";
temp += "(h.innerHTML='LED On',h.classList.remove('off'));j[2]=='0'?(z.innerHTML='LED Off',z.classList.add('off')):(z.innerHTML='LED On',z.classList.remove('off'));if(j[3]!='0') document.";
temp += "querySelector('#err').innerHTML='Sendefehler vor '+j[3]+' hh:mm'}s(),setInterval(s,5000)});</script><style>body{background-color:tan;font-size:1.1em}body,#grey,#no,#black{display";
temp += ":flex;flex-flow:column;align-items:center}#grey,#no{background-color:#c5c3c3;width:280px;height:150px;border:.3em solid #aeaeab;border-radius:.5em;box-shadow:5px 10px 5px #4e4d4d}";
temp += "#grey{cursor:pointer}#black{background-color:black;width:14em;border-radius:.2em}#red{border:.28em solid red;position:relative;width:3.8em;height:1.5em;left:1.5em}span{color:white";
temp += ";position:relative;left:.1em;letter-spacing:.2em;font-size:1.6em;font-weight:bold;top:4.55em;pointer-events:none;z-index:1}#no{display:none}.note{background-color:#fecdee;padding:";
temp += ".3em;border-radius:.5em;position:relative;top:-5.5em}input,#err{height:30px;margin-top:1em}.button{background-color:#75a27e;height:40px;width:120px;font-size:16px;box-shadow:5px ";
temp += "5px 5px #4e4d4d}.off{background-color:#cf848c}</style></head><body><span></span><div id='grey'><h1>Zählerstand</h1><div id='black'><div id='red'></div></div></div><div id='no'>";
temp += "<input placeholder=' Zählerstand eingeben' pattern='[0-9]{1,7}' title='Nur 1 bis 7 Ziffern sind erlaubt' required><div id='err'>Zähler - Led - Heartbeat </div><div><button id='";
temp += "ledz' class='button'></button><button id='ledh' class='button'></button></div></div><div id='note'></div></body></html>";
server.send(200, "text/html", temp);
}
void handleIcon() {
const static uint8_t favicon[] PROGMEM = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x08, 0x03, 0x00, 0x00, 0x00, 0x44, 0xA4, 0x8A,
0xC6, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 0x61,
0x05, 0x00, 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4D, 0x00, 0x00, 0x7A, 0x26, 0x00, 0x00, 0x80,
0x84, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0x80, 0xE8, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xEA,
0x60, 0x00, 0x00, 0x3A, 0x98, 0x00, 0x00, 0x17, 0x70, 0x9C, 0xBA, 0x51, 0x3C, 0x00, 0x00, 0x01,
0x50, 0x50, 0x4C, 0x54, 0x45, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB5, 0xAF, 0xAF, 0xBC, 0x9F, 0x9F, 0xC0, 0x93, 0x93,
0xC5, 0x87, 0x87, 0xC7, 0x83, 0x83, 0xC6, 0x86, 0x86, 0xC2, 0x8F, 0x8F, 0xBC, 0x9E, 0x9E, 0xB4,
0xB2, 0xB2, 0xC9, 0x7F, 0x7F, 0xDE, 0x4F, 0x4F, 0xEE, 0x27, 0x27, 0xFD, 0x04, 0x04, 0xFF, 0x00,
0x00, 0xFD, 0x05, 0x05, 0xF3, 0x1D, 0x1D, 0xE2, 0x45, 0x45, 0xCF, 0x72, 0x72, 0xBA, 0xA1, 0xA1,
0xB6, 0xAB, 0xAB, 0xD5, 0x62, 0x62, 0xF5, 0x18, 0x18, 0xFE, 0x02, 0x02, 0xE9, 0x33, 0x33, 0xCC,
0x77, 0x77, 0xB5, 0xAE, 0xAE, 0xC7, 0x84, 0x84, 0xF6, 0x15, 0x15, 0xCB, 0x7C, 0x7C, 0xD1, 0x6D,
0x6D, 0xCD, 0x77, 0x77, 0xFE, 0x03, 0x03, 0xEF, 0x24, 0x24, 0xE1, 0x46, 0x46, 0xDB, 0x55, 0x55,
0xD9, 0x5A, 0x5A, 0xDD, 0x4F, 0x4F, 0xE9, 0x34, 0x34, 0xF9, 0x0D, 0x0D, 0xC3, 0x8C, 0x8C, 0xFB,
0x08, 0x08, 0xD8, 0x5B, 0x5B, 0xBA, 0xA4, 0xA4, 0xB4, 0xAF, 0xAF, 0xCA, 0x7E, 0x7E, 0xE5, 0x3C,
0x3C, 0xFE, 0x04, 0x04, 0xB4, 0xB1, 0xB1, 0xF2, 0x1F, 0x1F, 0xF2, 0x20, 0x20, 0xBD, 0x9A, 0x9A,
0xBF, 0x96, 0x96, 0xCC, 0x78, 0x78, 0xBA, 0xA3, 0xA3, 0xCC, 0x79, 0x79, 0xF5, 0x17, 0x17, 0xC9,
0x80, 0x80, 0xE6, 0x3B, 0x3B, 0xFB, 0x09, 0x09, 0xF0, 0x22, 0x22, 0xC2, 0x90, 0x90, 0xCB, 0x79,
0x79, 0xC5, 0x88, 0x88, 0xBE, 0x9A, 0x9A, 0xD0, 0x6F, 0x6F, 0xD3, 0x67, 0x67, 0xD0, 0x70, 0x70,
0xC6, 0x85, 0x85, 0xC2, 0x8E, 0x8E, 0xDC, 0x53, 0x53, 0xB6, 0xAD, 0xAD, 0xFC, 0x07, 0x07, 0xDC,
0x54, 0x54, 0xDD, 0x51, 0x51, 0xE8, 0x35, 0x35, 0xCA, 0x7D, 0x7D, 0xD0, 0x6E, 0x6E, 0xF6, 0x16,
0x16, 0xF7, 0x14, 0x14, 0xBE, 0x98, 0x98, 0xFC, 0x08, 0x08, 0xDA, 0x56, 0x56, 0xDC, 0x52, 0x52,
0xDA, 0x58, 0x58, 0xD5, 0x63, 0x63, 0xD1, 0x6B, 0x6B, 0xD7, 0x5D, 0x5D, 0xB3, 0xB2, 0xB2, 0xF8,
0x12, 0x12, 0xF9, 0x0E, 0x0E, 0xF5, 0x16, 0x16, 0xDF, 0x4C, 0x4C, 0xBF, 0x98, 0x98, 0xB5, 0xAD,
0xAD, 0xCE, 0x74, 0x74, 0xFA, 0x0D, 0x0D, 0xEE, 0x28, 0x28, 0xE1, 0x48, 0x48, 0xCF, 0x71, 0x71,
0xBD, 0x9B, 0x9B, 0xBD, 0x9C, 0x9C, 0xC2, 0x91, 0x91, 0xC7, 0x85, 0x85, 0xC0, 0x96, 0x96, 0xB9,
0xA4, 0xA4, 0xFF, 0xFF, 0xFF, 0xD7, 0xC3, 0x74, 0x75, 0x00, 0x00, 0x00, 0x05, 0x74, 0x52, 0x4E,
0x53, 0xF0, 0xFC, 0xE2, 0xF2, 0xEE, 0x8D, 0xB1, 0xB7, 0x7D, 0x00, 0x00, 0x00, 0x01, 0x62, 0x4B,
0x47, 0x44, 0x6F, 0x55, 0x08, 0x61, 0x81, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00,
0x00, 0x03, 0x3A, 0x00, 0x00, 0x03, 0x3A, 0x01, 0x59, 0x83, 0x48, 0xD2, 0x00, 0x00, 0x00, 0x07,
0x74, 0x49, 0x4D, 0x45, 0x07, 0xE7, 0x02, 0x0B, 0x07, 0x0A, 0x0B, 0x02, 0x26, 0x72, 0x7C, 0x00,
0x00, 0x01, 0x29, 0x49, 0x44, 0x41, 0x54, 0x38, 0xCB, 0x63, 0x60, 0x60, 0xC5, 0x0B, 0x18, 0x19,
0x48, 0x54, 0xC0, 0xC6, 0xCE, 0xC1, 0xC9, 0xC5, 0xCD, 0xC3, 0xCB, 0x87, 0x4D, 0x01, 0x1F, 0xBF,
0x80, 0xA0, 0x90, 0x30, 0x04, 0x88, 0x88, 0x8A, 0x89, 0x4B, 0xA0, 0x2A, 0x90, 0x94, 0x92, 0x16,
0x46, 0x05, 0x32, 0xB2, 0x72, 0xF2, 0x08, 0x05, 0x0A, 0x8A, 0xC2, 0x58, 0x80, 0x12, 0x5C, 0x81,
0xB2, 0x8C, 0x30, 0x5E, 0x05, 0x2A, 0x70, 0x79, 0x55, 0x35, 0x75, 0x0D, 0x4D, 0x2D, 0x6D, 0x1D,
0x54, 0x05, 0xBA, 0x30, 0xB7, 0xE9, 0xE9, 0x1B, 0x40, 0x6C, 0x34, 0x34, 0x32, 0x36, 0x41, 0x28,
0x30, 0x35, 0x83, 0xCA, 0x9B, 0x5B, 0x20, 0xF9, 0xD8, 0x52, 0x16, 0xAE, 0xC0, 0x0A, 0x2A, 0x2F,
0x6D, 0x8D, 0x1A, 0x48, 0x36, 0xB6, 0x76, 0x10, 0x05, 0xF6, 0x50, 0x05, 0x76, 0x38, 0x42, 0x52,
0xDE, 0x01, 0x22, 0xEF, 0x88, 0x2B, 0xA8, 0x9D, 0xA0, 0x06, 0x68, 0xE2, 0x52, 0xC0, 0x0F, 0x55,
0xE0, 0x0C, 0x16, 0x71, 0x91, 0x43, 0x02, 0xAE, 0x60, 0x05, 0x6E, 0x50, 0x05, 0x2E, 0x60, 0x05,
0xB2, 0xC8, 0x01, 0xE5, 0x0E, 0x56, 0xE0, 0x01, 0xE5, 0x79, 0xE2, 0x52, 0x00, 0xB3, 0x42, 0x0E,
0x97, 0x02, 0x2F, 0x28, 0xCF, 0x1B, 0x97, 0x02, 0x1F, 0x5F, 0x08, 0xCF, 0x0C, 0xAC, 0xC0, 0xCD,
0x0F, 0x08, 0xFC, 0x51, 0x14, 0xB0, 0x06, 0x40, 0xB9, 0x81, 0x70, 0xCF, 0xF9, 0xA0, 0x2A, 0x08,
0x82, 0x72, 0x83, 0x25, 0x70, 0x28, 0x90, 0x0F, 0x81, 0x45, 0x56, 0x28, 0x76, 0x05, 0xAC, 0x4A,
0x30, 0x47, 0x85, 0x85, 0xB3, 0x63, 0x55, 0xC0, 0x1A, 0x81, 0x48, 0x88, 0x66, 0x62, 0x91, 0x51,
0xD1, 0x31, 0xE8, 0x0A, 0x62, 0x05, 0xB0, 0xA6, 0x38, 0x84, 0x02, 0x56, 0x56, 0xFE, 0x38, 0x02,
0x0A, 0x58, 0x0D, 0xBC, 0xE3, 0xD1, 0xA5, 0x13, 0x12, 0x93, 0x50, 0x32, 0x4E, 0x72, 0x8A, 0xBA,
0x19, 0x2C, 0xF1, 0xA6, 0xA6, 0xA5, 0x67, 0x64, 0x62, 0xCB, 0x7A, 0x3E, 0x59, 0xD9, 0x39, 0x5C,
0xBA, 0xB9, 0x79, 0xA4, 0x64, 0x5E, 0x26, 0x66, 0xBC, 0x80, 0x05, 0x00, 0x60, 0x24, 0x46, 0xAE,
0xA3, 0x6F, 0x16, 0xCA, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74, 0x65,
0x3A, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32, 0x30, 0x32, 0x33, 0x2D, 0x30, 0x32, 0x2D,
0x31, 0x31, 0x54, 0x30, 0x37, 0x3A, 0x31, 0x30, 0x3A, 0x31, 0x31, 0x2B, 0x30, 0x30, 0x3A, 0x30,
0x30, 0xBE, 0xBE, 0x45, 0x23, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64, 0x61, 0x74,
0x65, 0x3A, 0x6D, 0x6F, 0x64, 0x69, 0x66, 0x79, 0x00, 0x32, 0x30, 0x32, 0x33, 0x2D, 0x30, 0x32,
0x2D, 0x31, 0x31, 0x54, 0x30, 0x37, 0x3A, 0x31, 0x30, 0x3A, 0x31, 0x31, 0x2B, 0x30, 0x30, 0x3A,
0x30, 0x30, 0xCF, 0xE3, 0xFD, 0x9F, 0x00, 0x00, 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6F,
0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x00, 0x77, 0x77, 0x77, 0x2E, 0x69, 0x6E, 0x6B, 0x73, 0x63,
0x61, 0x70, 0x65, 0x2E, 0x6F, 0x72, 0x67, 0x9B, 0xEE, 0x3C, 0x1A, 0x00, 0x00, 0x00, 0x57, 0x7A,
0x54, 0x58, 0x74, 0x52, 0x61, 0x77, 0x20, 0x70, 0x72, 0x6F, 0x66, 0x69, 0x6C, 0x65, 0x20, 0x74,
0x79, 0x70, 0x65, 0x20, 0x69, 0x70, 0x74, 0x63, 0x00, 0x00, 0x78, 0x9C, 0xE3, 0xF2, 0x0C, 0x08,
0x71, 0x56, 0x28, 0x28, 0xCA, 0x4F, 0xCB, 0xCC, 0x49, 0xE5, 0x52, 0x00, 0x03, 0x23, 0x0B, 0x2E,
0x63, 0x0B, 0x13, 0x23, 0x13, 0x4B, 0x93, 0x14, 0x03, 0x13, 0x20, 0x44, 0x80, 0x34, 0xC3, 0x64,
0x03, 0x23, 0xB3, 0x54, 0x20, 0xCB, 0xD8, 0xD4, 0xC8, 0xC4, 0xCC, 0xC4, 0x1C, 0xC4, 0x07, 0xCB,
0x80, 0x48, 0xA0, 0x4A, 0x2E, 0x00, 0xEA, 0x17, 0x11, 0x74, 0xF2, 0x42, 0x35, 0x95, 0x00, 0x00,
0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82
};
server.send(200, "image/x-icon", favicon, sizeof(favicon)); // Icon an den Browser senden
}
Thingspeak.ino
// ****************************************************************
// Sketch Thingspeak Modular(Tab) (Antwort nicht blockierend)
// created: Jens Fleischer, 2018-04-08
// last mod: Jens Fleischer, 2018-05-05
// For more information visit: https://fipsok.de
// ****************************************************************
// Software: Esp8266 Arduino Core 2.4.2 -3.1.1
// Getestet auf: Nodemcu
/******************************************************************
Copyright (c) 2018 Jens Fleischer. All rights reserved.
This file is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
*******************************************************************/
// Diese Version von Thingspeak sollte als Tab eingebunden werden.
// #include <ESP8266WebServer.h> oder #include <ESP8266WiFi.h> muss im Haupttab aufgerufen werden
// Der Funktionsaufruf "thingspeak();" muss in loop eingebunden sein.
/**************************************************************************************/
WiFiClient client;
bool thingspeak(const char* value) {
static bool error = false, response = true;
const uint16_t httpPort = 80;
const char* host = "184.106.153.149";
const char* APIKEY = {"Geheimer ApiKey"}; // trage deinen ApiKey von https://thingspeak.com
const unsigned long interval = 1000UL * 300; // Interval in Sekunden einstellen
static unsigned long letzteMillis = 0 - interval / 2; // Sendebeginn einstellen ("- interval" = sofort, "0" = nach Ablauf von Interval)
const uint16_t timeout = 2000; // Zeitraum für Fehlerrückgabe in Millisekunden einstellen
const String path = (String)"&field1=" + value + "&field2=" + value; // "field1 bis 8" anpassen
/*************** Thinkspeak senden *********************/
unsigned long aktuelleMillis = millis();
if (aktuelleMillis - letzteMillis >= interval || error) { // senden im Interval und erneut im Fehlerfall
error = false;
letzteMillis = aktuelleMillis;
if (!client.connect(host, httpPort)) {
Serial.println("Thingspeak Verbindung fehlgeschlagen !");
error = true;
return false;
}
else {
client.printf("POST /update?key=%s%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", APIKEY, path.c_str(), host);
response = 0;
return true;
}
}
/************** Thinkspeak auf Anwort prüfen *****************/
if (!response) {
if (millis() - letzteMillis > timeout) {
Serial.println("Thingspeak Client Timeout !");
error = true;
return false;
}
if (client.available()) { // einlesen der Antwort
//Serial.printf("Thingspeak Antwort nach: %4ld ms\n", millis() - letzteMillis); // zeigt die Zeit bis zur Antwort --> passe den Timeout entsprechend an
String line = client.readStringUntil('\n');
if (line.startsWith("HTTP/1.1 200 OK")) { // wenn Antwort mit "HTTP/1.1 200 OK" beginnt war das Senden erfolgreich
client.stop();
response = true;
}
}
}
return true;
}
einfach eine Super Seite, ich habe bereits einiger deiner Beispiele mit einsetzen können.
Ich würde statt der Uhr gerne eine Stoppuhr umsetzen. Meine versuche waren bisher das Array der Uhrzeit anzeige umzubauen, daran scheitere ich aktuell aber noch... hast du einen Tipp für mich?
Gruß Jens
Antwort:
Bitte wende dich mit deinem Sketch an ein Arduino Forum.
Dort wird dir sicher geholfen.
Gruß Fips
Danke
Antwort: Schön das es klappt.
Gruß Fips
Hochladen des Sketches hat alles geklappt.
Ich verstehe aber noch nicht, wie man das Webinterface
aufruft.
Vielen Dank!
Antwort: Gib einfach die IP des Esp im Browser ein.
Gruß Fips
sehr tolles Projekt! Habe es auf die Nutzung von Interrupt abgewandelt. Damit ist bei mir der Zähler etwas stabiler.
Ich mache noch einen MQTT Tab dazu, um die Daten an meinen ioBroker zu schicken.
Ich werde das Ergebnis auch auf github stellen, wenn ich soweit bin.
Danke!
Martin
Antwort:
Bitte!
Gruß Fips
Cooles Projekt!
Habe mir einige Bestandteile daraus gemopst und in meins übernommen, da ich noch einen Zwischenchache benötige wenn kein WLAN da ist und das Ganze in eine InfluxDB schiebe und nicht nach ThinkSpeak.
Läuft bestens, nur in einem Punkt bin ich mir unsicher.
Wenn aus welchen Gründen auch immer meine InfluxDB nicht erreichbar ist, dauert es einige Sekunden bis HTTP abbricht und nen Fehler auswirft.
Wenn ich das korrekt sehe fängst Du das mit einem 2Sekunden Timeout ab in Deiner Thinkspeak.ino?
Aber in 2 Sekunden kann ja der Magnet vom Zähler am Reed vorbeigeflitzt sein, ohne das dies abgefragt wurde, oder übersehe ich da was?
Gruß
Stefan
Antwort:
So schnell läuft er bei mir nicht!
Sollte es bei dir zu knapp werden, ruf doch die Funktion "zaehlerauslesen()" zwischendurch auf.
Gruß Fips
'esp_delay' was not declared in this scope
'esp_suspend' was not declared in this scope
Antwort:
Mit welcher EspCoreVersion erhälst du den Fehler?
Gruß Fips
Danke, tolle Sache, vor allem mit dem Zwischenspeicher im ESP. Das ist ein Problem bei vielen anderen Lösungen. Allerdings wäre mir eine Datenübertragung z.B. per MQTT ins eigene Smart Home lieber. Das ist nicht zufällig angedacht?
Viele Grüße, Dieter
Antwort:
Bisher habe ich noch nie was mit MQTT gemacht, will aber nicht ausschließen zukünftig damit zu spielen.
Gruß Fips
es ist wirklich erstaunlich: Sketch geladen, ein paar Sekunden warten, und es funktioniert!
Alle Achtung, was du da programmiert hast!
Vielen Dank!
Antwort:
Freut mich, zu hören das es für dich unkompliziert war!
Gruß Fips
Würde mich interessieren.
Jürgen
Antwort:
Nicht das ich wüsste.
Gruß Fips
Da ich den Strom mit einer Brennstoffzelle herstelle würde ich den Gasverbrauch da gerne mit einfließen lassen.
Da ich den da genutzten vzlogger nicht für ESP gefunden habe hatte ich überlegt ob man das hier umbauen könnte um in den volkszaehler zu comitten?
Hat sowas schon wer versucht?