added macro _MODBUS_AVERAGE_TEMPERATURES, bug fixes

This commit is contained in:
Bruno Hütter 2020-12-04 10:02:48 +01:00
parent a71fc8e176
commit efa9fd8ea0
7 changed files with 51 additions and 40 deletions

View file

@ -20,24 +20,6 @@ bool timeStampOverflow = false; // true, wenn mehr als 0xFFF Zehntelsekunden ver
unsigned long timeStamp; unsigned long timeStamp;
u16 lastRefTime = 0xFFFF; 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) { void checkParamINT16(int16_t *source, int16_t *target, const int &std, const int &min, const int &max) {
_print("source: "); _print(*source); _print("source: "); _print(*source);
if (*source == _SENSOR_FAULT) { 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); _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) { void checkParamBool(u8 &p, const u8 &bitNr, u8 *p2=nullptr) {
u8 *p_ = (p2) ? p2 : &p; u8 *p_ = (p2) ? p2 : &p;
if (paramsChangedByUI) { if (paramsChangedByUI) {

View file

@ -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. 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. - ***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*** ***### 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). - 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 ;-) ).
***### 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) ***Frage:*** Ist die Mittelung der Temperatur wirklich nicht notwendig?
# Modbus # Modbus
@ -51,11 +51,9 @@ Verschiedenes: Ausgangszustände Ventile, Betriebsart Regler, Flags:
Messwerte: 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) - ***0x02***: Temperatur 1 - aktuelle Temperatur als INT16 in Hundertstel-°C
***### 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)***
- ***0x03***: Temperatur 2 (noch nicht genutzt gibt *0xFFFF* zurück) - ***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: gespeicherte Ereignisse:

View file

@ -9,18 +9,20 @@
#define _VERSION_NUMBER _VERSION_MICRO | (_VERSION_MINOR << 6) | (_VERSION_MAJOR << 12) #define _VERSION_NUMBER _VERSION_MICRO | (_VERSION_MINOR << 6) | (_VERSION_MAJOR << 12)
#define _VERSION_STRING "v0.0.1" #define _VERSION_STRING "v0.0.1"
#define _DEBUG 0 #define _DEBUG 1
#define _DEBUG_SENSORS 0 #define _DEBUG_SENSORS 0
#define _MODBUS 1 #define _MODBUS 1
// Das Ermitteln einer Durchschnittstemperatur braucht viel RAM und ist wahrscheinlich unnötig
#define _MODBUS_AVERAGE_TEMPERATURES 0
#if _DEBUG == 1 #if _DEBUG == 1
#define _print(x) Serial.print(x) #define _print(x) Serial.print(x)
#define _println(x) Serial.println(x) #define _println(x) Serial.println(x)
struct _printTimeStruct { struct __printTimeStruct {
_printTimeStruct(const char *text) : _text(text) { __printTimeStruct(const char *text) : _text(text) {
_t0 = millis(); _t0 = millis();
}; };
~_printTimeStruct() { ~__printTimeStruct() {
_print("Vergangene Millisekunden ["); _print(_text); _print("Vergangene Millisekunden ["); _print(_text);
_print("]: "); _println(millis() - _t0); _print("]: "); _println(millis() - _t0);
}; };
@ -28,7 +30,7 @@ struct _printTimeStruct {
u32 _t0; u32 _t0;
const char *_text; const char *_text;
}; };
#define _printtime(text) _printTimeStruct __printt(text) #define _printtime(text) __printTimeStruct __printt(text)
#if _DEBUG_SENSORS == 1 #if _DEBUG_SENSORS == 1
#define _prints(x) Serial.print(x) #define _prints(x) Serial.print(x)
#define _printsln(x) Serial.println(x) #define _printsln(x) Serial.println(x)

View file

@ -102,7 +102,11 @@ void Controller::process()
_printsln(); _printsln();
} }
#if _MODBUS == 1 #if _MODBUS == 1
#if _MODBUS_AVERAGE_TEMPERATURES == 1
_averageTemperature1(); _averageTemperature1();
#else
modbusData[_MODBUS_T1_INDEX] = _vals->t1;
#endif
#endif #endif
} else if (_requestConversion) { } else if (_requestConversion) {
_requestConversion = false; _requestConversion = false;
@ -220,18 +224,22 @@ void Controller::_setPValves(States state)
#if _MODBUS == 1 #if _MODBUS == 1
void Controller::resetAverageCounters() void Controller::resetAverageCounters()
{ {
_print("Setze Zähler zurück (_t1_c: "); _print("Setze Zähler zurück (");
_print(_t1_c); _print(", _t2_c: "); #if _MODBUS_AVERAGE_TEMPERATURES == 1
_print(_t2_c); _print(", _p_c: "); _print("_t1_c: "); _print(_t1_c);
_print(_p_c); _println(")"); _print(", _t2_c: "); _print(_t2_c);
_print(", ");
_t1_c = 0; _t1_c = 0;
_t2_c = 0; _t2_c = 0;
_p_c = 0;
_t1_of = false; _t1_of = false;
_t2_of = false; _t2_of = false;
#endif
_print("_p_c: "); _print(_p_c); _println(")");
_p_c = 0;
_p_of = false; _p_of = false;
} }
#if _MODBUS_AVERAGE_TEMPERATURES == 1
inline void Controller::_averageTemperature1() inline void Controller::_averageTemperature1()
{ {
int32_t total = 0; int32_t total = 0;
@ -265,6 +273,7 @@ inline void Controller::_averageTemperature2()
{ {
// noch nicht implementiert // noch nicht implementiert
} }
#endif // _MODBUS_AVERAGE_TEMPERATURES == 1
inline void Controller::_averagePressure() inline void Controller::_averagePressure()
{ {

View file

@ -9,11 +9,11 @@
#define _TEMP_CONVERSION_DELAY 800 #define _TEMP_CONVERSION_DELAY 800
#define _ANALOG_READ_DELAY 500 #define _ANALOG_READ_DELAY 500
// Maximal nötige Anzahl an Temperatur-Einträgen, bevor der interne 12 Bit Timer überläuft // 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 #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 // 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 #endif
// #define _T_ARR_LEN 255
// #define _P_ARR_LEN 255
class Controller class Controller
{ {
@ -29,12 +29,14 @@ private:
uint8_t _t1Pin; uint8_t _t1Pin;
uint8_t _t2Pin; uint8_t _t2Pin;
#if _MODBUS_AVERAGE_TEMPERATURES == 1
int16_t _t1_arr[_T_ARR_LEN]; // Array, aus dem der Durchschnittswert ermittelt wird 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 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 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 // 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 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 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 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 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 bool _p_of = false; // Flag, die anzeigt, ob das _p_arr-Array schon voll ist

View file

@ -14,7 +14,7 @@ Display::Display(
modbusParameters *modbus, modbusParameters *modbus,
PSensor *sensor, PSensor *sensor,
valveStates *vStates) valveStates *vStates)
: U8G2_ST7920_128X64_2_HW_SPI(U8G2_R0, cs) : U8G2_ST7920_128X64_F_HW_SPI(U8G2_R0, cs)
, btnNext(btnNext) , btnNext(btnNext)
, btnPrev(btnPrev) , btnPrev(btnPrev)
, btnSelect(btnSelect) , btnSelect(btnSelect)

View file

@ -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_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); 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: private: