Moin,
mein erstes Programm für Einspeisungssteuerung läuft soweit erstmal.
ABER nach nicht genau definierter Zeit ( ca. 1-3 Std. Laufzeit meist ) bekommt die Variable pwr Werte die VIEL zu hoch sind.
Die Schleife läuft aber weiter ( sieht man an den Dioden am RX485 - der Wert ändert sich aber nicht wieder auf das Reale - die Checksumme habe ich noch ignoriert weil ich die Berechnung noch nicht begriffen habe - das sollte aber ja nicht das Problem sein weil ein falscher Wert beim nächsten Schleifendurchlauf ja wieder geändert würde - und wenn der Fehler auftritt bleibt die Variable pwr statisch auf dem einmal entstandenen Falschwert )
pwr ist die aktuell bezogene Energie vom Netz, ausgelesen mit einem DS100-00B über RS485
Das geht dann über zweiten RS485 Adapter an den Soyosource.
Probleme gibts noch das die Variable pwr - bei Der funktioniert nicht die Abfrage auf die Art pwr < 0 - um auf Negativ zu prüfen ( wenn der pwr-Wert durch das BKW ins negative geht ).
Das habe ich dadurch prov. gelöst das ich das HighByte der 32 Bit Variable auf 0xFF prüfe - weil das ist der Fall wenn pwr negativ ist - und so groß wird pwr eh nie.
Um mich an den Fehler ranzutasten habe ich die Anzeige im LCD Display - tritt der Fehler auf wird die Ausgabe der Leistung extrem hoch ( unrealistisch ) und bleibt auf diesem unrealistischen Wert.
Dazu lasse ich mir die Laufzeit des Programms im Display anzeigen um die typ. Zeit bis zum Fehler anzeigen zu lassen.
Dann habe ich alle Variablendefinitionen aus der Hauptschleife rausgenommen ( ohne Verbesserung - Idee war -> frisst er sonst mehr Speicher ?
Und es ist jetzt eine Abfrage drin die bei Überschreitung des Wertes pwr > 10kW einen Reset auslöst - was gerade in der Praxis passierte ( Runtime 75 Minuten ) - der Reset geht ja schnell - die Funktion ist so schon mal gegeben.
Wo ist mein Fehler ( Variablen aufklaren - Speicherprobleme - Bufferüberlauf ?!? )
Die Berechnung von pwr aus den 4 Bytes ist sicher noch nicht toll gelöst - funktioniert aber.
Die Variable wtts übernimmt den Wert von pwr bevor die geändert wird, pwr geht aber an das Display zum Monitoring - im Fehlerfall müsste wtts aber ja den selben falschen Wert haben wie pwr.
Proc: ESP32_DevKitV3
Die HardwareSerial nutze ich nicht da das mit der OnboardDiode Probleme gab und Baud eh niedrig ist ( sein kann ).
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "driver/uart.h"
#include <SoftwareSerial.h>
//Variablen definieren
int pwr;
int DATEN[8]; //Array definieren
uint16_t wtts; //unsigned Variable für Watt-senden def.
char incomingByte1;
char incomingByte2;
char incomingByte3;
char incomingByte4;
char incomingByte5;
char incomingByte6;
char incomingByte7;
char incomingByte8;
char incomingByte9;
uint16_t CS;
uint8_t i;
int runtime;
LiquidCrystal_I2C lcd(0x3F,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
SoftwareSerial mySerial(6, 7); //rx tx
SoftwareSerial SoyoSerial(2, 3); //rx tx
void setup()
{
Serial.begin(9600);
mySerial.begin(9600, SWSERIAL_8N1);
SoyoSerial.begin(4800, SWSERIAL_8N1);
Wire.begin(SDA, SCL);
lcd.init(); // initialize the lcd
lcd.backlight();
lcd.clear();
}
void loop()
{
pwr = 0;
// Datenabfrage senden
DATEN[0] = 0x01; // ModbusAdresse ?
DATEN[1] = 0x04;
DATEN[2] = 0x04;
DATEN[3] = 0x20; //Combined_Aktive_Power
DATEN[4] = 0x00;
DATEN[5] = 0x02;
DATEN[6] = 0x71;
DATEN[7] = 0x31;
for(uint8_t i=0; i<8; i++) {
mySerial.write(DATEN[i]);
}
if (mySerial.available()> 0) {
// wait a bit for the entire message to arrive
delay(100);
// clear the screen
lcd.clear();
lcd.setCursor(0, 0);
incomingByte1=mySerial.read(); // 1.Byte einlesen & verwerfen
incomingByte1 = incomingByte1; //Dummynutzung der Variable
incomingByte2=mySerial.read(); // 2.Byte einlesen & verwerfen
incomingByte2 = incomingByte2; //Dummynutzung der Variable
incomingByte3=mySerial.read(); // 3.Byte einlesen & verwerfen
incomingByte3 = incomingByte3; //Dummynutzung der Variable
incomingByte4=mySerial.read();
pwr = (pwr+incomingByte4*16777216); // Highest Byte - pwr zusammenbauen
incomingByte5=mySerial.read();
pwr = (pwr+incomingByte5*65536); // 2.Highest Byte
incomingByte6=mySerial.read();
pwr = (pwr+incomingByte6*256); // 2.Lowest Byte
incomingByte7=mySerial.read();
pwr = (pwr+incomingByte7); // Lowest Byte
// ab hier CS auslesen und verwerfen - Serial_Input frei machen
incomingByte8=mySerial.read(); // 8.Byte ( CS ? ) einlesen & verwerfen
incomingByte8 = incomingByte8; //Dummynutzung der Variable
incomingByte9=mySerial.read(); // 9.Byte ( CS ? ) einlesen & verwerfen
incomingByte9 = incomingByte9; //Dummynutzung der Variable
wtts = pwr; //Zahl "retten"
if (wtts > 700) wtts = 700; //Obergrenze
//Abfrage des Highbytes der 32Bit Zahl vom Zähler
if (incomingByte4 >= 255) wtts = 0; //bei Ueberfluss keine Einspeisung
//wenn diese 255/0xFF ist kann man vom negativen Wert ausgehen
if (incomingByte4 >= 255) {
lcd.print("\xF5");
lcd.print("bereinspeisung:");
pwr=pwr*-1; //setze positiv für Anzeige
} else
lcd.print("Bedarf: ");
if (pwr > 10000) ESP.restart();
lcd.setCursor(0, 1);
lcd.print(pwr);
lcd.print(" W RT=");
runtime = millis();
runtime = runtime / 60000;
lcd.print (runtime);
lcd.print(" Min");
//Daten an den Soyo senden:
CS = 264;
DATEN[0] = 0x24;
DATEN[1] = 0x56;
DATEN[2] = 0x00;
DATEN[3] = 0x21;
DATEN[4] = (wtts & 0xFF00)>>8;
DATEN[5] = (wtts & 0x00FF);
DATEN[6] = 0x80;
CS = CS - DATEN[4] - DATEN[5];
if(CS > 0xFF) CS = 8;
DATEN[7] = CS;
for(i=0; i<8; i++) {
SoyoSerial.write(DATEN[i]); // .print ??
}
}
delay(900); // 0.9 Sekunden warten = 1 sec. Intervall
}