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;
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) {

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.
## 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:

View File

@ -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)

View File

@ -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()
{

View File

@ -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

View File

@ -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)

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_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: