diff --git a/DreherTankController.ino b/DreherTankController.ino index 9b02d1d..131be73 100644 --- a/DreherTankController.ino +++ b/DreherTankController.ino @@ -20,24 +20,6 @@ bool timeStampOverflow = false; // true, wenn mehr als 0xFFF Zehntelsekunden ver unsigned long timeStamp; u16 lastRefTime = 0xFFFF; -#if _MODBUS == 1 -#include "src/modbus/ModbusRTUSlave.h" - -u8 modbusStates[1]; // Bit0: tEn, Bit1: pInc, Bit2: pDec, Bit3: cEn -u8 modbusValves[1]; // Bit0: Temp1, Bit1: Temp2, Bit2: Druck -// 0: Event-Counter, 1: high: modbusValves[0], low: modbusStates[0], 2...4: Temp 1, 2, Druck, ab5: gespeicherte Schaltvorgänge -u16 modbusData[_REGS_INFRONTOF_EVENTS + _MODBUS_MAX_EVENTS]; // Main Input Registers -u16 modbusMiscReadable[2]; // Version, Kühlzonen -u16 modbusSetpoints[6]; // Temp1, 2, Druck jeweils Sollwert + Hysterese -u16 modbusRefTime[1]; // setzt bei Änderung Event-Counter und -Timer zurück - -u8 &states = modbusStates[0]; -u8 &valves = modbusValves[0]; -u16 &eventCounter = modbusData[0]; -u16 &refTime = modbusRefTime[0]; - -ModbusRTUSlave mb(&Serial1, 2); - void checkParamINT16(int16_t *source, int16_t *target, const int &std, const int &min, const int &max) { _print("source: "); _print(*source); if (*source == _SENSOR_FAULT) { @@ -88,6 +70,24 @@ void checkParamUINT8(u8 *source, u8 *target, const u8 &std) { _print(", target: "); _print(*target); _print(", source: "); _println(*source); } +#if _MODBUS == 1 +#include "src/modbus/ModbusRTUSlave.h" + +u8 modbusStates[1]; // Bit0: tEn, Bit1: pInc, Bit2: pDec, Bit3: cEn +u8 modbusValves[1]; // Bit0: Temp1, Bit1: Temp2, Bit2: Druck +// 0: Event-Counter, 1: high: modbusValves[0], low: modbusStates[0], 2...4: Temp 1, 2, Druck, ab5: gespeicherte Schaltvorgänge +u16 modbusData[_REGS_INFRONTOF_EVENTS + _MODBUS_MAX_EVENTS]; // Main Input Registers +u16 modbusMiscReadable[2]; // Version, Kühlzonen +u16 modbusSetpoints[6]; // Temp1, 2, Druck jeweils Sollwert + Hysterese +u16 modbusRefTime[1]; // setzt bei Änderung Event-Counter und -Timer zurück + +u8 &states = modbusStates[0]; +u8 &valves = modbusValves[0]; +u16 &eventCounter = modbusData[0]; +u16 &refTime = modbusRefTime[0]; + +ModbusRTUSlave mb(&Serial1, 2); + void checkParamBool(u8 &p, const u8 &bitNr, u8 *p2=nullptr) { u8 *p_ = (p2) ? p2 : &p; if (paramsChangedByUI) { diff --git a/README.md b/README.md index 50803b8..6f183f3 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ Experimentelle Firmware für einen Tankregler, der die Temperatur und den Druck Das Programm ist für den Atmega2560 (Arduino Mega 2560) geschrieben. -## Probleme +## Probleme, offene Fragen - ***Großes Problem:*** Während des Gedrückthaltens einer Menütaste am Regler blockiert das Programm fast (nur noch ca. 10 Loops / Sekunde). In diesem Fall funktioiert Modbus nicht mehr. ***### TODO - Das liegt an der Zeit, die gebraucht wird, um das Display zu beschreiben (70 - 100+ ms). Wenn praktisch dauernd das Display neu beschrieben wird, bleibt einfach keine Zeit für was anderes -- SCHNELL EINE LÖSUNG FINDEN*** -- Solange nur ein Kühlkreis implementiert ist, lässt sich das maximale Abfrageintervall (siehe Modbus-Holding-Register 0xC0; wenn _TEMP_CONVERSION_DELAY und _ANALOG_READ_DELAY nicht reduziert werden (800 bzw. 500 ms)) auf dem Wert des internen 12 Bit Timers halten (409,6 Sekunden), da der RAM wegen den Arrays zur Messwert-Mittelung schon jetzt gerade so ausreicht (Bei einem Test waren **nur noch 874 Bytes** für lokale Variablen über). -***### Temperatur-Mittelung wieder entfernen, da die Temperaturschwankungen BEI WEITEM nicht so stark sind wie die des Drucks?*** (Da der Drucksensor in einer Leitung außerhalb des Tanks sitzt, schwankt der Druck extrem beim Schalten der Druckventile) +- Der Durchschnittswert der Temperatur wird nicht mehr gebildet (außer das Macro _MODBUS_AVERAGE_TEMPERATURES ist 1 - dafür reicht der RAM aber eh nicht ;-) ). +***Frage:*** Ist die Mittelung der Temperatur wirklich nicht notwendig? # Modbus @@ -51,11 +51,9 @@ Verschiedenes: Ausgangszustände Ventile, Betriebsart Regler, Flags: Messwerte: -- ***0x02***: Temperatur 1 (Durchschnittswert zwischen 2 Abfragen als INT16 in Hundertstel-°C – max ?? Minuten, einzeln vorkommende Sensorfehler werden ignoriert, bei häufigeren Fehlern wird *0xFFFF* zurückgegeben) -***### TODO – Durchschnittswerte ermitteln (aktuell nur letzter Wert – ganz schlecht beim Druck, da dieser extrem bei den Schaltvorgängen schwankt)*** -***### TODO – maximale Zeit ermitteln (auch für Druck)*** +- ***0x02***: Temperatur 1 - aktuelle Temperatur als INT16 in Hundertstel-°C - ***0x03***: Temperatur 2 (noch nicht genutzt – gibt *0xFFFF* zurück) -- ***0x04***: Druck (siehe Temperatur) +- ***0x04***: Druck (Durchschnittswert zwischen 2 Abfragen (der letzten 409,6 Sekunden bzw. der letzten Referenzierung - siehe Holding-Register ***0xC0***) als INT16 in Hundertstel-Bar, einzeln vorkommende Sensorfehler werden ignoriert, bei häufigeren Fehlern wird *0xFFFF* zurückgegeben) gespeicherte Ereignisse: diff --git a/src/common.h b/src/common.h index b755bcf..afd4f93 100644 --- a/src/common.h +++ b/src/common.h @@ -9,18 +9,20 @@ #define _VERSION_NUMBER _VERSION_MICRO | (_VERSION_MINOR << 6) | (_VERSION_MAJOR << 12) #define _VERSION_STRING "v0.0.1" -#define _DEBUG 0 +#define _DEBUG 1 #define _DEBUG_SENSORS 0 #define _MODBUS 1 +// Das Ermitteln einer Durchschnittstemperatur braucht viel RAM und ist wahrscheinlich unnötig +#define _MODBUS_AVERAGE_TEMPERATURES 0 #if _DEBUG == 1 #define _print(x) Serial.print(x) #define _println(x) Serial.println(x) -struct _printTimeStruct { - _printTimeStruct(const char *text) : _text(text) { +struct __printTimeStruct { + __printTimeStruct(const char *text) : _text(text) { _t0 = millis(); }; - ~_printTimeStruct() { + ~__printTimeStruct() { _print("Vergangene Millisekunden ["); _print(_text); _print("]: "); _println(millis() - _t0); }; @@ -28,7 +30,7 @@ struct _printTimeStruct { u32 _t0; const char *_text; }; -#define _printtime(text) _printTimeStruct __printt(text) +#define _printtime(text) __printTimeStruct __printt(text) #if _DEBUG_SENSORS == 1 #define _prints(x) Serial.print(x) #define _printsln(x) Serial.println(x) diff --git a/src/controller/controller.cpp b/src/controller/controller.cpp index 659e5ac..326c17e 100644 --- a/src/controller/controller.cpp +++ b/src/controller/controller.cpp @@ -102,7 +102,11 @@ void Controller::process() _printsln(); } #if _MODBUS == 1 +#if _MODBUS_AVERAGE_TEMPERATURES == 1 _averageTemperature1(); +#else + modbusData[_MODBUS_T1_INDEX] = _vals->t1; +#endif #endif } else if (_requestConversion) { _requestConversion = false; @@ -220,18 +224,22 @@ void Controller::_setPValves(States state) #if _MODBUS == 1 void Controller::resetAverageCounters() { - _print("Setze Zähler zurück (_t1_c: "); - _print(_t1_c); _print(", _t2_c: "); - _print(_t2_c); _print(", _p_c: "); - _print(_p_c); _println(")"); + _print("Setze Zähler zurück ("); +#if _MODBUS_AVERAGE_TEMPERATURES == 1 + _print("_t1_c: "); _print(_t1_c); + _print(", _t2_c: "); _print(_t2_c); + _print(", "); _t1_c = 0; _t2_c = 0; - _p_c = 0; _t1_of = false; _t2_of = false; +#endif + _print("_p_c: "); _print(_p_c); _println(")"); + _p_c = 0; _p_of = false; } +#if _MODBUS_AVERAGE_TEMPERATURES == 1 inline void Controller::_averageTemperature1() { int32_t total = 0; @@ -265,6 +273,7 @@ inline void Controller::_averageTemperature2() { // noch nicht implementiert } +#endif // _MODBUS_AVERAGE_TEMPERATURES == 1 inline void Controller::_averagePressure() { diff --git a/src/controller/controller.h b/src/controller/controller.h index df3226b..a19db70 100644 --- a/src/controller/controller.h +++ b/src/controller/controller.h @@ -9,11 +9,11 @@ #define _TEMP_CONVERSION_DELAY 800 #define _ANALOG_READ_DELAY 500 // Maximal nötige Anzahl an Temperatur-Einträgen, bevor der interne 12 Bit Timer überläuft +#define _P_ARR_LEN (409600 / _ANALOG_READ_DELAY) + 1 +#if _MODBUS_AVERAGE_TEMPERATURES == 1 #define _T_ARR_LEN (409600 / _TEMP_CONVERSION_DELAY) + 1 // Maximal nötige Anzahl an Druck-Einträgen, bevor der interne 12 Bit Timer überläuft -#define _P_ARR_LEN (409600 / _ANALOG_READ_DELAY) + 1 -// #define _T_ARR_LEN 255 -// #define _P_ARR_LEN 255 +#endif class Controller { @@ -29,12 +29,14 @@ private: uint8_t _t1Pin; uint8_t _t2Pin; +#if _MODBUS_AVERAGE_TEMPERATURES == 1 int16_t _t1_arr[_T_ARR_LEN]; // Array, aus dem der Durchschnittswert ermittelt wird u16 _t1_c = 0; // Anzahl der Einträge, aus denen der Durchschnitt gebildet wird bool _t1_of = false; // Flag, die anzeigt, ob das _t1_arr-Array schon voll ist // int16_t _t2_arr[_T_ARR_LEN]; // Array, aus dem der Durchschnittswert ermittelt wird u16 _t2_c = 0; // Anzahl der Einträge, aus denen der Durchschnitt gebildet wird bool _t2_of = false; // Flag, die anzeigt, ob das _t2_arr-Array schon voll ist +#endif int16_t _p_arr[_P_ARR_LEN]; // Array, aus dem der Durchschnittswert ermittelt wird u16 _p_c = 0; // Anzahl der Einträge, aus denen der Durchschnitt gebildet wird bool _p_of = false; // Flag, die anzeigt, ob das _p_arr-Array schon voll ist diff --git a/src/display/display.cpp b/src/display/display.cpp index e4ebbc2..e78a274 100644 --- a/src/display/display.cpp +++ b/src/display/display.cpp @@ -14,7 +14,7 @@ Display::Display( modbusParameters *modbus, PSensor *sensor, valveStates *vStates) - : U8G2_ST7920_128X64_2_HW_SPI(U8G2_R0, cs) + : U8G2_ST7920_128X64_F_HW_SPI(U8G2_R0, cs) , btnNext(btnNext) , btnPrev(btnPrev) , btnSelect(btnSelect) diff --git a/src/display/display.h b/src/display/display.h index b0850b0..e0382ff 100644 --- a/src/display/display.h +++ b/src/display/display.h @@ -77,7 +77,7 @@ extern "C" uint8_t my_UserInterfaceSelectionList(u8g2_t *u8g2, const char *title // extern "C" void my_UserInterfaceInputValue(u8g2_t *u8g2, const char *title, const char *pre, uint8_t value, uint8_t digits, const char *post); extern "C" void my_UserInterfaceInputValueString(u8g2_t *u8g2, const char *title, const char *sub, const char *text); -class Display : public U8G2_ST7920_128X64_2_HW_SPI +class Display : public U8G2_ST7920_128X64_F_HW_SPI { private: