Hallo,
ich habe ein kleines Programm auf einem ESP8266 am laufen um meinen Zähler per Lesekopf auszulesen (SML Protokoll)
Im Prinzip funktioniert alles Wunderbar. Es läuft auch mehrere Stunden. Plötzliche werden aber keine Daten mehr übermittelt. Die Hauptschleife läuft weiter. Der Webserver ist auch weiterhin erreichbar. Es werden aber keine Daten mehr an (in diesem Fall Thingspeak) übermittelt.
Ich vermute ganz Stark das es durch einen Fehler irgendeine Variable, Counter, etc nicht mehr zurücksetze und deswegen alles stehen bleibt. Ich Suche nun schon seit 3 Tagen und kann nichts finden.
Kurz zur Erläuterung: In der mainloop werden nur die einzelnen Fälle durchgespielt. Je nach aktivem Fall.
- Es wird aus den Daten der Seriellen Schnittstelle nach der Startsequenz des SML Protokoll gesucht.
- Es wird nach der Endsquenz gesucht.
3/4. Es werden die gewollten Daten aus dem Inhalt rausgefischt - Die Daten werden übergeben, verarbeitet, wie auch immer.
Der Zähler sendet ungefähr jede Sekunde. Deswegen der Counter mit den 120 damit nicht bei jedem Durchlauf, sondern ungefähr alle 2 Minuten Daten übermittelt werden.
Im Optimalfall werden die Daten AB der Startsequenz bis zur Endsequenz gespeichert. Ein Punkt wäre: wenn er nach dem er eine Startsequenz gefunden hat nicht direkt eine Endsequenz findet, läuft die Suche nach der Endsequenz nochmal durch. Die läuft so lange bis er eben eine gefunden hat. Irgendwann passiert das ja. Was dabei eben eintritt ist, das das array sml message solange befüllt wird BIS eben eine Endsequenz gefunden wurde. Was wiederum dazu führt das Daten unter umständen doppelt vorhanden sind. In meinen Augen aber kein Problem. Es kann eben beider Abfrage der Werte in Schritt 3 bzw 4 dazu führen, dass er Werte von vor 30 sekunden hat und nicht der aktuellen. Wäre aber vollkommen egal. Dürfte ja keinen Fehler im Programmablauf verursachen oder?
Das wäre aber auch das Einzige was vllt verbessert werden kann in Form von wieder auf Case 0 setzen wenn zwar eine Startsequenz gefunden wurde aber nicht unmittelbar danach eine Endsequenz.
Hier mal der Code.
#include <SoftwareSerial.h>
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
#include <WebSerial.h>
#include <Arduino_JSON.h>
#include <ThingSpeak.h>
SoftwareSerial sSerial(5, 4);
#define LED 2
AsyncWebServer server(80);
const char* ssid = "";
const char* password = "";
void recvMsg(uint8_t* data, size_t len) {
WebSerial.println("Received Data...");
String d = "";
for (int i = 0; i < len; i++) {
d += char(data[i]);
}
WebSerial.println(d);
if (d == "ON") {
digitalWrite(LED, LOW);
}
if (d == "OFF") {
digitalWrite(LED, HIGH);
}
}
byte inByte; //byte to store the serial buffer
byte smlMessage[1000]; //byte to store the parsed message
const byte startSequence[] = { 0x1B, 0x1B, 0x1B, 0x1B, 0x01, 0x01, 0x01, 0x01 }; //start sequence of SML protocol
const byte stopSequence[] = { 0x1B, 0x1B, 0x1B, 0x1B, 0x1A }; //end sequence of SML protocol
const byte powerSequence[] = { 0x07, 0x01, 0x00, 0x10, 0x07, 0x00, 0xFF, 0x01, 0x01, 0x62, 0x1B, 0x52, 0xFE, 0x55 }; //sequence preceeding the current "Wirkleistung" value (4 Bytes)
const byte consumptionSequence[] = { 0x07, 0x01, 0x00, 0x01, 0x08, 0x00, 0xFF, 0x64, 0x01, 0x01, 0x80, 0x01, 0x62, 0x1E, 0x52, 0xFB, 0x69 }; //sequence predeecing the current "Gesamtverbrauch" value (8 Bytes)
int smlIndex; //index counter within smlMessage array
int startIndex; //start index for start sequence search
int stopIndex; //start index for stop sequence search
static int stage; //index to maneuver through cases
byte power[4]; //array that holds the extracted 4 byte "Wirkleistung" value
byte consumption[8]; //array that holds the extracted 8 byte "Gesamtverbrauch" value
int currentpower; //variable to hold translated "Wirkleistung" value
int currentconsumption; //variable to hold translated "Gesamtverbrauch" value
int takt_send = 0;
unsigned long myChannelNumber = 123123;
const char * myWriteAPIKey = "123123";
WiFiClient client;
void setup() {
sSerial.begin(9600); // baud softwareserial
Serial.begin(9600); // baud serial
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.printf("WiFi Failed!\n");
return;
}
Serial.println("IP Address: ");
Serial.println(WiFi.localIP());
server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
request->send(200, "text/plain", "Webserver running...");
});
AsyncElegantOTA.begin(&server);
WebSerial.begin(&server);
WebSerial.msgCallback(recvMsg);
server.begin();
ThingSpeak.begin(client);
Serial.println("Startet");
}
void loop() {
switch (stage) {
case 0:
findStartSequence(); // look for start sequence
break;
case 1:
findStopSequence(); // look for stop sequence
break;
case 2:
findPowerSequence(); //look for power sequence and extract
break;
case 3:
findConsumptionSequence(); //look for consumption sequence and exctract
break;
case 4:
publishMessage(); // do something with the result
break;
}
}
void findStartSequence() {
while (sSerial.available()) {
inByte = sSerial.read(); //read serial buffer into array
if (inByte == startSequence[startIndex]) {
smlMessage[startIndex] = inByte;
startIndex++;
if (startIndex == sizeof(startSequence)) {
//WebSerial.println("Match found");
stage = 1;
smlIndex = startIndex;
startIndex = 0;
}
} else {
startIndex = 0;
}
}
}
void findStopSequence() {
while (sSerial.available()) {
inByte = sSerial.read();
smlMessage[smlIndex] = inByte;
smlIndex++;
if (inByte == stopSequence[stopIndex]) {
stopIndex++;
if (stopIndex == sizeof(stopSequence)) {
stage = 2;
stopIndex = 0;
}
} else {
stopIndex = 0;
}
}
}
void findPowerSequence() {
byte temp;
startIndex = 0;
for (int x = 0; x < sizeof(smlMessage); x++) {
temp = smlMessage[x];
if (temp == powerSequence[startIndex]) {
startIndex++;
if (startIndex == sizeof(powerSequence)) {
for (int y = 0; y < 4; y++) {
power[y] = smlMessage[x + y + 1];
}
stage = 3; // go to stage 3
startIndex = 0;
}
} else {
startIndex = 0;
}
}
currentpower = (power[0] << 24 | power[1] << 16 | power[2] << 8 | power[3]); //merge 4 bytes into single variable to calculate power value
currentpower = currentpower / 100;
}
void findConsumptionSequence() {
byte temp;
startIndex = 0;
for (int x = 0; x < sizeof(smlMessage); x++) {
temp = smlMessage[x];
if (temp == consumptionSequence[startIndex]) {
startIndex++;
if (startIndex == sizeof(consumptionSequence)) {
for (int y = 0; y < 8; y++) {
//hier muss für die folgenden 8 Bytes hoch gezählt werden
consumption[y] = smlMessage[x + y + 1];
}
stage = 4;
startIndex = 0;
}
} else {
startIndex = 0;
}
}
currentconsumption = (consumption[0] << 56 | consumption[1] << 48 | consumption[2] << 40 | consumption[32] | consumption[4] << 24 | consumption[5] << 16 | consumption[6] << 8 | consumption[7]); //combine and turn 8 bytes into one variable
}
void publishMessage() {
if (takt_send < 120) {
takt_send++;
} else {
if (WiFi.status() == WL_CONNECTED) {
int x = ThingSpeak.writeField(myChannelNumber, 2, currentpower, myWriteAPIKey);
WebSerial.println("SEND");
} else {
Serial.println("WiFi Disconnected");
takt_send = 0;
}
takt_send = 0;
}
memset(smlMessage, 0, sizeof(smlMessage));
memset(power, 0, sizeof(power));
memset(consumption, 0, sizeof(consumption));
//reset case
smlIndex = 0;
stage = 0; // start over
}