#include "common.h" #include extern Display display; extern u32 currMillis; extern u16 zones; static void checkParamINT16(int16_t *source, int16_t *target, const int &std, const int &min, const int &max) { _printf("source: "); _print(*source); if (*source == _SENSOR_FAULT) { *source = *target = std; } else if (*source > max) { *source = *target = max; } else if (*source < min) { *source = *target = min; } else if (*source == min || *source == max) { *target = *source; } else { u8 mod = *source % 5; _printf(", modulo: "); _print(mod); if (mod == 0) *target = *source; else { int tempVal = *source - mod; _printf(", tempVal: "); _print(tempVal); if (mod > 2) { // runde auf den nächsten 5er Schritt bzw. setze auf max if ((tempVal + 5) > max) { *source = *target = max; _printf(" ... auf max setzen"); } else { *source = *target = tempVal + 5; _printf(" ... aufrunden"); } } else { // runde auf den vorigen 5er Schritt bzw. setze auf min if (tempVal < min) { *source = *target = min; _printf(" ... auf min setzen"); } else { *source = *target = tempVal; _printf(" ... abrunden"); } } } } _printf(", target: "); _print(*target); _printf(", source: "); _println(*source); } static void checkParamUINT8(u8 *source, u8 *target, const u8 &std) { _printf("checkParamUINT8 source vorher: "); _print(*source); if (*source > 1) { *source = *target = std; } else { *target = *source; } _printf(", target: "); _print(*target); _printf(", source: "); _println(*source); } #if _MODBUS == 1 #include "modbus/ModbusRTUSlave.h" u8 modbusCoils[1]; // Bit0: tEn, 1: pInc, 2: pDec, 3: cEn, 4: akustisch, 5: optisch, 6: t-off-if-error, 7: p-off-if-error u8 modbusValves[1]; // Bit0: Temp1, Bit1: Temp2, Bit2: Druck // 0: Event-Counter, 1: high: modbusValves[0], low: modbusCoils[0], 2...4: Temp 1, 2, Druck, ab5: gespeicherte Schaltvorgänge u16 modbusData[_REGS_INFRONTOF_EVENTS + _MODBUS_MAX_EVENTS]; u16 modbusMiscReadable[21]; // Version, Kühlzonen, Anzahl PowerOns, Konstanten // Anzahl der gespeicherten Alarme + gespeicherte Alarme u16 modbusAlarms[1 + (_MAX_FAULTS * 3)]; // Löschen von einzelnen/allen Alarmen u16 modbusDelAlarms[2]; // modbusCoils[0], Temp1, 2, Druck jeweils Sollwert + Hysterese, T+Error, T-Error, P+-Error u16 modbusHolding[10]; u16 modbusRefTime[1]; // setzt bei Änderung Event-Counter und -Timer zurück u16 &eventCounter = modbusData[0]; u16 &refTime = modbusRefTime[0]; extern ModbusRTUSlave mb; static void setBitInRegisters(u8 bitNr, u8 val) { _print("Setze Register "); _print(bitNr); _print(" auf "); _println(val); bitWrite(modbusCoils[0], bitNr, val); bitWrite(modbusData[1], bitNr, val); bitWrite(modbusHolding[0], bitNr, val); } static void setBitInRegisters(u8 bitNr, u8 val, Parameters &p, FaultSettings &fs) { setBitInRegisters(bitNr, val); switch(bitNr) { case 0: // Temperaturregelung p.tEn = val; break; case 1: // Drucksteigerung p.pInc = val; break; case 2: // Druckabfall p.pDec = val; break; case 3: // Regler aktiv p.cEn = val; break; case 4: // akustisches Warnsignal fs.acoustic = val; break; case 5: // optisches Warnsignal fs.optical = val; break; case 6: // Temperaturregelung im Fehlerfall fs.tOnIfError = val; break; case 7: // Druckregelung im Fehlerfall fs.pOnIfError = val; break; } } void beginModbus() { mb.begin(modbusParams.address, modbusParams.baudrate); mb.waitWithAnswerMicroS = modbusParams.delay * 100; // 1/10 ms -> us } void setupModbus(const u16 &powerOnCount) { bool modbusFail = false; if (!mb.addDiscreteInputArea(0xD0, modbusValves, 1)) modbusFail = true; if (!modbusFail && !mb.addHoldingRegisterArea(0xA0, modbusHolding, 10)) modbusFail = true; if (!modbusFail && !mb.addCoilArea(0xB0, modbusCoils, 1)) modbusFail = true; if (!modbusFail && !mb.addHoldingRegisterArea(0xC0, modbusRefTime, 1)) modbusFail = true; if (!modbusFail && !mb.addInputRegisterArea(0x00, modbusData, _REGS_INFRONTOF_EVENTS + _MODBUS_MAX_EVENTS)) modbusFail = true; if (!modbusFail && !mb.addInputRegisterArea(0x0100, modbusAlarms, 1 + (_MAX_FAULTS * 3))) modbusFail = true; if (!modbusFail && !mb.addHoldingRegisterArea(0x0200, modbusDelAlarms, 2)) modbusFail = true; if (!modbusFail && !mb.addInputRegisterArea(0x0F00, modbusMiscReadable, 21)) modbusFail = true; if (modbusFail) { display.modbusProblem(); while(1); } modbusData[0] = 0; // EventCounter modbusData[1] |= 0x8000; // setze das MSB. Das Bit wird durch setzen von modbusRefTime[0] zurückgesetzt modbusData[2] = _SENSOR_FAULT; // Temp1 in 100stel-°C modbusData[3] = _SENSOR_FAULT; // Temp2 in 100stel-°C, noch nicht implementiert modbusData[4] = _SENSOR_FAULT; // Druck in 100stel bar modbusData[5] = 0; // Zehntelsekunden seit Reglerstart / letzter Referenzierung modbusAlarms[0] = 0; // Alarm-Counter modbusDelAlarms[0] = 0; // Löschen eines Alarms anhand einer ID modbusDelAlarms[1] = 0; // Alle inaktiven Alarme löschen modbusMiscReadable[0] = _VERSION_NUMBER; modbusMiscReadable[1] = zones; modbusMiscReadable[2] = powerOnCount; modbusMiscReadable[3] = _STD_T_EN; bitWrite(modbusMiscReadable[3], 1, _STD_P_EN_INC); bitWrite(modbusMiscReadable[3], 2, _STD_P_EN_DEC); bitWrite(modbusMiscReadable[3], 3, _STD_C_EN); bitWrite(modbusMiscReadable[3], 4, _STD_FAULTS_ACOUSTIC); bitWrite(modbusMiscReadable[3], 5, _STD_FAULTS_OPTICAL); bitWrite(modbusMiscReadable[3], 6, _STD_FAULTS_T_ON); bitWrite(modbusMiscReadable[3], 7, _STD_FAULTS_P_ON); modbusMiscReadable[4] = _STD_TEMP_SETPOINT; modbusMiscReadable[5] = _STD_TEMP_HYSTERESIS; modbusMiscReadable[6] = _STD_P_SETPOINT; modbusMiscReadable[7] = _STD_P_HYSTERESIS; modbusMiscReadable[8] = _STD_FAULTS_T_R_RATE; modbusMiscReadable[9] = _STD_FAULTS_T_F_RATE; modbusMiscReadable[10] = _STD_FAULTS_P_RATE; modbusMiscReadable[11] = _MIN_TEMP_SETPOINT; modbusMiscReadable[12] = _MAX_TEMP_SETPOINT; modbusMiscReadable[13] = _MIN_TEMP_HYSTERESIS; modbusMiscReadable[14] = _MAX_TEMP_HYSTERESIS; modbusMiscReadable[15] = _MIN_P_SETPOINT; modbusMiscReadable[16] = _MAX_P_SETPOINT; modbusMiscReadable[17] = _MIN_P_HYSTERESIS; modbusMiscReadable[18] = _MAX_P_HYSTERESIS; modbusMiscReadable[19] = _MIN_FAULTS_RATE; modbusMiscReadable[20] = _MAX_FAULTS_RATE; modbusRefTime[0] = 0xFFFF; beginModbus(); } void modbusCallbackCoil(u16 reg, bool val) { Parameters p; FaultSettings fs; if ((reg >= 0xB0) && (reg <= 0xB7)) { setBitInRegisters(reg - 0xB0, val, p, fs); } setParams(p, false); setFaultSettings(fs, false); } u16 modbusCallbackRegister(u16 reg, u16 val) { Parameters p; FaultSettings fs; switch(reg) { case 0xA0: // Bit 0...7: siehe Coils (Bit 0: 0xB0) for (u8 i=0; i<8; i++) { u8 bitVal = bitRead(val, i); if (bitVal != bitRead(modbusHolding[0], i)) { setBitInRegisters(i, bitVal, p, fs); } } break; case 0xA1: // Temperatur 1 Sollwert checkParamINT16((int16_t*)&val, &p.ts1, _STD_TEMP_SETPOINT, _MIN_TEMP_SETPOINT, _MAX_TEMP_SETPOINT); val = p.ts1; break; case 0xA2: // Temperatur 1 Hysterese checkParamINT16((int16_t*)&val, &p.th1, _STD_TEMP_HYSTERESIS, _MIN_TEMP_HYSTERESIS, _MAX_TEMP_HYSTERESIS); val = p.th1; break; case 0xA3: // Temperatur 2 Sollwert (noch nicht implementiert – Wert wird ignoriert) case 0xA4: // Temperatur 2 Hysterese (noch nicht implementiert – Wert wird ignoriert) break; case 0xA5: // Druck Sollwert checkParamINT16((int16_t*)&val, &p.ps, _STD_P_SETPOINT, _MIN_P_SETPOINT, _MAX_P_SETPOINT); val = p.ps; break; case 0xA6: // Druck Hysterese checkParamINT16((int16_t*)&val, &p.ph, _STD_P_HYSTERESIS, _MIN_P_HYSTERESIS, _MAX_P_HYSTERESIS); val = p.ph; break; case 0xA7: // Temperatur-Steigerungsrate (Hundertstel-°C / 1 Stunde) checkParamINT16((int16_t*)&val, &fs.tMinRRate, _STD_FAULTS_T_R_RATE, _MIN_FAULTS_RATE, _MAX_FAULTS_RATE); val = fs.tMinRRate; break; case 0xA8: // Temperatur-Abfallrate (Hundertstel-°C / 1 Stunde) checkParamINT16((int16_t*)&val, &fs.tMinFRate, _STD_FAULTS_T_F_RATE, _MIN_FAULTS_RATE, _MAX_FAULTS_RATE); val = fs.tMinFRate; break; case 0xA9: // Druckrate (Steigerung und Abfall - Hundertstel-Bar / 10 Sekunden) checkParamINT16((int16_t*)&val, &fs.pMinRate, _STD_FAULTS_P_RATE, _MIN_FAULTS_RATE, _MAX_FAULTS_RATE); val = fs.pMinRate; break; } setParams(p, false); setFaultSettings(fs, false); return val; } #endif // _MODBUS == 1 void getParams() { Parameters p; EEPROM.get(_EEPROM_TEMP_SETPOINT, p.ts1); EEPROM.get(_EEPROM_TEMP_HYSTERESIS, p.th1); EEPROM.get(_EEPROM_P_SETPOINT, p.ps); EEPROM.get(_EEPROM_P_HYSTERESIS, p.ph); EEPROM.get(_EEPROM_P_EN_INC, p.pInc); EEPROM.get(_EEPROM_P_EN_DEC, p.pDec); EEPROM.get(_EEPROM_T_EN, p.tEn); EEPROM.get(_EEPROM_CONTROL_EN, p.cEn); _printlnf("getParams() vor Validierung:"); _printf(" Temperatur Sollwert: "); _println(p.ts1); _printf(" Temperatur Hysterese: "); _println(p.th1); _printf(" Druck Sollwert: "); _println(p.ps); _printf(" Druck Hysterese: "); _println(p.ph); _printf(" Temp-Regelung aktiv: "); _println(p.tEn); _printf(" Drucksteigerung aktiv: "); _println(p.pInc); _printf(" Druckabfall aktiv: "); _println(p.pDec); _printf(" Regler aktiv: "); _println(p.cEn); _printf("ts1 - UI -> Modbus - "); checkParamINT16(&p.ts1, ¶ms.ts1, _STD_TEMP_SETPOINT, _MIN_TEMP_SETPOINT, _MAX_TEMP_SETPOINT); modbusHolding[1] = params.ts1; _printf("th1 - UI -> Modbus - "); checkParamINT16(&p.th1, ¶ms.th1, _STD_TEMP_HYSTERESIS, _MIN_TEMP_HYSTERESIS, _MAX_TEMP_HYSTERESIS); modbusHolding[2] = params.th1; _printf("ps - UI -> Modbus - "); checkParamINT16(&p.ps, ¶ms.ps, _STD_P_SETPOINT, _MIN_P_SETPOINT, _MAX_P_SETPOINT); modbusHolding[5] = params.ps; _printf("ph - UI -> Modbus - "); checkParamINT16(&p.ph, ¶ms.ph, _STD_P_HYSTERESIS, _MIN_P_HYSTERESIS, _MAX_P_HYSTERESIS); modbusHolding[6] = params.ph; _printf("tEn - "); checkParamUINT8(&p.tEn, ¶ms.tEn, _STD_T_EN); setBitInRegisters(0, params.tEn); _printf("pInc - "); checkParamUINT8(&p.pInc, ¶ms.pInc, _STD_P_EN_INC); setBitInRegisters(1, params.pInc); _printf("pDec - "); checkParamUINT8(&p.pDec, ¶ms.pDec, _STD_P_EN_DEC); setBitInRegisters(2, params.pDec); _printf("cEn - "); checkParamUINT8(&p.cEn, ¶ms.cEn, _STD_C_EN); setBitInRegisters(3, params.cEn); _printlnf("getParams() nach Validierung:"); _printf(" Temperatur Sollwert: "); _println(params.ts1); _printf(" Temperatur Hysterese: "); _println(params.th1); _printf(" Druck Sollwert: "); _println(params.ps); _printf(" Druck Hysterese: "); _println(params.ph); _printf(" Temp-Regelung aktiv: "); _println(params.tEn); _printf(" Drucksteigerung aktiv: "); _println(params.pInc); _printf(" Druckabfall aktiv: "); _println(params.pDec); _printf(" Regler aktiv: "); _println(params.cEn); } void setParams(Parameters &p, bool writeModbusRegister) { if (p.ts1 != _SENSOR_FAULT) { _printf("ts1 alt: "); _print(params.ts1); _printf(", neu: "); _println(p.ts1); checkParamINT16(&p.ts1, ¶ms.ts1, _STD_TEMP_SETPOINT, _MIN_TEMP_SETPOINT, _MAX_TEMP_SETPOINT); EEPROM.put(_EEPROM_TEMP_SETPOINT, params.ts1); if (writeModbusRegister) modbusHolding[1] = params.ts1; } if (p.th1 != _SENSOR_FAULT) { _printf("th1 alt: "); _print(params.th1); _printf(", neu: "); _println(p.th1); checkParamINT16(&p.th1, ¶ms.th1, _STD_TEMP_HYSTERESIS, _MIN_TEMP_HYSTERESIS, _MAX_TEMP_HYSTERESIS); EEPROM.put(_EEPROM_TEMP_HYSTERESIS, params.th1); if (writeModbusRegister) modbusHolding[2] = params.th1; } if (p.ps != _SENSOR_FAULT) { _printf("ps alt: "); _print(params.ps); _printf(", neu: "); _println(p.ps); checkParamINT16(&p.ps, ¶ms.ps, _STD_P_SETPOINT, _MIN_P_SETPOINT, _MAX_P_SETPOINT); EEPROM.put(_EEPROM_P_SETPOINT, params.ps); if (writeModbusRegister) modbusHolding[5] = params.ps; } if (p.ph != _SENSOR_FAULT) { _printf("ph alt: "); _print(params.ph); _printf(", neu: "); _println(p.ph); checkParamINT16(&p.ph, ¶ms.ph, _STD_P_HYSTERESIS, _MIN_P_HYSTERESIS, _MAX_P_HYSTERESIS); EEPROM.put(_EEPROM_P_HYSTERESIS, params.ph); if (writeModbusRegister) modbusHolding[6] = params.ph; } if (p.pInc < 2) { _printf("pInc alt: "); _print(params.pInc); _printf(", neu: "); _println(p.pInc); params.pInc = p.pInc; EEPROM.put(_EEPROM_P_EN_INC, params.pInc); if (writeModbusRegister) setBitInRegisters(1, params.pInc); } if (p.pDec < 2) { _printf("pDec alt: "); _print(params.pDec); _printf(", neu: "); _println(p.pDec); params.pDec = p.pDec; EEPROM.put(_EEPROM_P_EN_DEC, params.pDec); if (writeModbusRegister) setBitInRegisters(2, params.pDec); } if (p.tEn < 2) { _printf("tEn alt: "); _print(params.tEn); _printf(", neu: "); _println(p.tEn); params.tEn = p.tEn; EEPROM.put(_EEPROM_T_EN, params.tEn); if (writeModbusRegister) setBitInRegisters(0, params.tEn); } if (p.cEn < 2) { _printf("cEn alt: "); _print(params.cEn); _printf(", neu: "); _println(p.cEn); params.cEn = p.cEn; EEPROM.put(_EEPROM_CONTROL_EN, params.cEn); if (writeModbusRegister) setBitInRegisters(3, params.cEn); } } void getModbusParams() { uint8_t addr = EEPROM.read(_EEPROM_MODBUS_ADDRESS); if (addr < _MODBUS_ADDR_MIN || addr > _MODBUS_ADDR_MAX) modbusParams.address = _MODBUS_ADDR_MIN; else modbusParams.address = addr; uint32_t baudrate; EEPROM.get(_EEPROM_MODBUS_BAUDRATE, baudrate); switch (baudrate) { case 115200: break; case 57600: break; case 38400: break; case 19200: break; case 9600: break; case 4800: break; case 2400: break; case 1200: break; case 300: break; default: baudrate = 9600; } modbusParams.baudrate = baudrate; uint8_t delay_ = EEPROM.read(_EEPROM_MODBUS_DELAY); if (delay_ < _MODBUS_DELAY_MIN) modbusParams.delay = _MODBUS_DELAY_MIN; else if (delay_ > _MODBUS_DELAY_MAX) modbusParams.delay = _MODBUS_DELAY_MAX; else modbusParams.delay = delay_; } void setModbusParams(const ModbusParameters &p) { bool changed = false; if (p.address <= _MODBUS_ADDR_MAX) { EEPROM.put(_EEPROM_MODBUS_ADDRESS, p.address); modbusParams.address = p.address; changed = true; } if (p.baudrate != _MODBUS_INVALID_BAUDRATE) { EEPROM.put(_EEPROM_MODBUS_BAUDRATE, p.baudrate); modbusParams.baudrate = p.baudrate; changed = true; } if (p.delay <= _MODBUS_DELAY_MAX) { EEPROM.put(_EEPROM_MODBUS_DELAY, p.delay); modbusParams.delay = p.delay; changed = true; } if (changed) { #if _MODBUS == 1 beginModbus(); #endif } } void getPSensor() { uint8_t val; EEPROM.get(_EEPROM_P_SENSOR, val); switch (val) { case SMC_1_5V_0_5BAR: pSensor = SMC_1_5V_0_5BAR; break; case GEMS_0_5V_0_6BAR: pSensor = GEMS_0_5V_0_6BAR; break; default: pSensor = SMC_1_5V_0_5BAR; EEPROM.put(_EEPROM_P_SENSOR, pSensor); } return pSensor; } void setPSensor(const PSensor &sensor) { EEPROM.put(_EEPROM_P_SENSOR, sensor); pSensor = sensor; } void getFaultSettings() { FaultSettings settings; EEPROM.get(_EEPROM_FAULTS_ACOUSTIC, settings.acoustic); EEPROM.get(_EEPROM_FAULTS_OPTICAL, settings.optical); EEPROM.get(_EEPROM_FAULTS_T_ON, settings.tOnIfError); EEPROM.get(_EEPROM_FAULTS_P_ON, settings.pOnIfError); EEPROM.get(_EEPROM_FAULTS_T_R_RATE, settings.tMinRRate); EEPROM.get(_EEPROM_FAULTS_T_F_RATE, settings.tMinFRate); EEPROM.get(_EEPROM_FAULTS_P_RATE, settings.pMinRate); _printlnf("getFaultSettings() vor Validierung:"); _printf(" akustisches Signal: "); _println(settings.acoustic); _printf(" optisches Signal : "); _println(settings.optical); _printf(" t on if error : "); _println(settings.tOnIfError); _printf(" p on if error : "); _println(settings.pOnIfError); _printf(" t min rise rate : "); _println(settings.tMinRRate); _printf(" t min fall rate : "); _println(settings.tMinFRate); _printf(" p min r/f rate : "); _println(settings.pMinRate); if (settings.acoustic < 2) { faultSettings.acoustic = settings.acoustic; } else { faultSettings.acoustic = _STD_FAULTS_ACOUSTIC; } setBitInRegisters(4, faultSettings.acoustic); if (settings.optical < 2) { faultSettings.optical = settings.optical; } else { faultSettings.optical = _STD_FAULTS_OPTICAL; } setBitInRegisters(5, faultSettings.optical); if (settings.tOnIfError < 2) { faultSettings.tOnIfError = settings.tOnIfError; } else { faultSettings.tOnIfError = _STD_FAULTS_T_ON; } setBitInRegisters(6, faultSettings.tOnIfError); if (settings.pOnIfError < 2) { faultSettings.pOnIfError = settings.pOnIfError; } else { faultSettings.pOnIfError = _STD_FAULTS_P_ON; } setBitInRegisters(7, faultSettings.pOnIfError); if (settings.tMinRRate == 0x8000) { faultSettings.tMinRRate = _STD_FAULTS_T_R_RATE; } else if (settings.tMinRRate < _MIN_FAULTS_RATE) { faultSettings.tMinRRate = _MIN_FAULTS_RATE; } else if (settings.tMinRRate > _MAX_FAULTS_RATE) { faultSettings.tMinRRate = _MAX_FAULTS_RATE; } else { faultSettings.tMinRRate = settings.tMinRRate; } modbusHolding[7] = faultSettings.tMinRRate; if (settings.tMinFRate == 0x8000) { faultSettings.tMinFRate = _STD_FAULTS_T_F_RATE; } else if (settings.tMinFRate < _MIN_FAULTS_RATE) { faultSettings.tMinFRate = _MIN_FAULTS_RATE; } else if (settings.tMinFRate > _MAX_FAULTS_RATE) { faultSettings.tMinFRate = _MAX_FAULTS_RATE; } else { faultSettings.tMinFRate = settings.tMinFRate; } modbusHolding[8] = faultSettings.tMinFRate; if (settings.pMinRate == 0x8000) { faultSettings.pMinRate = _STD_FAULTS_P_RATE; } else if (settings.pMinRate < _MIN_FAULTS_RATE) { faultSettings.pMinRate = _MIN_FAULTS_RATE; } else if (settings.pMinRate > _MAX_FAULTS_RATE) { faultSettings.pMinRate = _MAX_FAULTS_RATE; } else { faultSettings.pMinRate = settings.pMinRate; } modbusHolding[9] = faultSettings.pMinRate; _printlnf("getFaultSettings() nach Validierung:"); _printf(" akustisches Signal: "); _println(faultSettings.acoustic); _printf(" optisches Signal : "); _println(faultSettings.optical); _printf(" t on if error : "); _println(faultSettings.tOnIfError); _printf(" p on if error : "); _println(faultSettings.pOnIfError); _printf(" t min rise rate : "); _println(faultSettings.tMinRRate); _printf(" t min fall rate : "); _println(faultSettings.tMinFRate); _printf(" p min r/f rate : "); _println(faultSettings.pMinRate); } void setFaultSettings(const FaultSettings &settings, bool writeModbusRegister) { if (settings.acoustic < 2 && settings.acoustic != faultSettings.acoustic) { _printf("faultSettings.acoustic alt: "); _print(faultSettings.acoustic); _printf(", neu: "); _println(settings.acoustic); faultSettings.acoustic = settings.acoustic; EEPROM.put(_EEPROM_FAULTS_ACOUSTIC, settings.acoustic); if (writeModbusRegister) setBitInRegisters(4, settings.acoustic); } if (settings.optical < 2 && settings.optical != faultSettings.optical) { _printf("faultSettings.optical alt: "); _print(faultSettings.optical); _printf(", neu: "); _println(settings.optical); faultSettings.optical = settings.optical; EEPROM.put(_EEPROM_FAULTS_OPTICAL, settings.optical); if (writeModbusRegister) setBitInRegisters(5, settings.optical); } if (settings.tOnIfError < 2 && settings.tOnIfError != faultSettings.tOnIfError) { _printf("faultSettings.tOnIfError alt: "); _print(faultSettings.tOnIfError); _printf(", neu: "); _println(settings.tOnIfError); faultSettings.tOnIfError = settings.tOnIfError; EEPROM.put(_EEPROM_FAULTS_T_ON, settings.tOnIfError); if (writeModbusRegister) setBitInRegisters(6, settings.tOnIfError); } if (settings.pOnIfError < 2 && settings.pOnIfError != faultSettings.pOnIfError) { _printf("faultSettings.pOnIfError alt: "); _print(faultSettings.pOnIfError); _printf(", neu: "); _println(settings.pOnIfError); faultSettings.pOnIfError = settings.pOnIfError; EEPROM.put(_EEPROM_FAULTS_P_ON, settings.pOnIfError); if (writeModbusRegister) setBitInRegisters(7, settings.pOnIfError); } if (settings.tMinRRate != 0x8000 && settings.tMinRRate != faultSettings.tMinRRate) { if (settings.tMinRRate < _MIN_FAULTS_RATE) { faultSettings.tMinRRate == _MIN_FAULTS_RATE; EEPROM.put(_EEPROM_FAULTS_T_R_RATE, _MIN_FAULTS_RATE); } else if (settings.tMinRRate > _MAX_FAULTS_RATE) { faultSettings.tMinRRate == _MAX_FAULTS_RATE; EEPROM.put(_EEPROM_FAULTS_T_R_RATE, _MAX_FAULTS_RATE); } else { faultSettings.tMinRRate == settings.tMinRRate; EEPROM.put(_EEPROM_FAULTS_T_R_RATE, settings.tMinRRate); } if (writeModbusRegister) modbusHolding[7] = settings.tMinRRate; _printf("faultSettings.tMinRRate alt: "); _print(faultSettings.tMinRRate); _printf(", neu: "); _println(settings.tMinRRate); } if (settings.tMinFRate != 0x8000 && settings.tMinFRate != faultSettings.tMinFRate) { if (settings.tMinFRate < _MIN_FAULTS_RATE) { faultSettings.tMinFRate == _MIN_FAULTS_RATE; EEPROM.put(_EEPROM_FAULTS_T_F_RATE, _MIN_FAULTS_RATE); } else if (settings.tMinFRate > _MAX_FAULTS_RATE) { faultSettings.tMinFRate == _MAX_FAULTS_RATE; EEPROM.put(_EEPROM_FAULTS_T_F_RATE, _MAX_FAULTS_RATE); } else { faultSettings.tMinFRate == settings.tMinFRate; EEPROM.put(_EEPROM_FAULTS_T_F_RATE, settings.tMinFRate); } if (writeModbusRegister) modbusHolding[8] = settings.tMinFRate; _printf("faultSettings.tMinFRate alt: "); _print(faultSettings.tMinFRate); _printf(", neu: "); _println(settings.tMinFRate); } if (settings.pMinRate != 0x8000 && settings.pMinRate != faultSettings.pMinRate) { if (settings.pMinRate < _MIN_FAULTS_RATE) { faultSettings.pMinRate == _MIN_FAULTS_RATE; EEPROM.put(_EEPROM_FAULTS_P_RATE, _MIN_FAULTS_RATE); } else if (settings.pMinRate > _MAX_FAULTS_RATE) { faultSettings.pMinRate == _MAX_FAULTS_RATE; EEPROM.put(_EEPROM_FAULTS_P_RATE, _MAX_FAULTS_RATE); } else { faultSettings.pMinRate == settings.pMinRate; EEPROM.put(_EEPROM_FAULTS_P_RATE, settings.pMinRate); } if (writeModbusRegister) modbusHolding[9] = settings.pMinRate; _printf("faultSettings.pMinRate alt: "); _print(faultSettings.pMinRate); _printf(", neu: "); _println(settings.pMinRate); } } bool readPwrBtn() { const uint8_t debounceDelay = 20; static unsigned long lastDebounceTime; static bool lastBounceState; static bool steadyState; bool currentState = !digitalRead(BTN_PWR); if (currentState != lastBounceState) { lastDebounceTime = currMillis; lastBounceState = currentState; } if ((currMillis - lastDebounceTime) > debounceDelay) steadyState = currentState; if (steadyState && (currMillis - lastDebounceTime) > 3000) display.reset(); return steadyState; }