684 lines
19 KiB
C++
684 lines
19 KiB
C++
#include "faults.h"
|
|
#include "../types.h"
|
|
#include "../mystrings/mystrings.h"
|
|
#include "../macros.h"
|
|
#include <EEPROM.h>
|
|
|
|
extern u32 currMillis;
|
|
extern u16 zones;
|
|
extern u16 modbusAlarms[];
|
|
|
|
const u16 EEPROM_FAULTS[] = {
|
|
_EEPROM_FAULT_1, _EEPROM_FAULT_2, _EEPROM_FAULT_3,_EEPROM_FAULT_4, _EEPROM_FAULT_5,
|
|
_EEPROM_FAULT_6, _EEPROM_FAULT_7, _EEPROM_FAULT_8, _EEPROM_FAULT_9, _EEPROM_FAULT_10,
|
|
_EEPROM_FAULT_11, _EEPROM_FAULT_12, _EEPROM_FAULT_13, _EEPROM_FAULT_14, _EEPROM_FAULT_15,
|
|
_EEPROM_FAULT_16, _EEPROM_FAULT_17, _EEPROM_FAULT_18, _EEPROM_FAULT_19, _EEPROM_FAULT_20,
|
|
_EEPROM_FAULT_21, _EEPROM_FAULT_22, _EEPROM_FAULT_23, _EEPROM_FAULT_24, _EEPROM_FAULT_25,
|
|
_EEPROM_FAULT_26, _EEPROM_FAULT_27, _EEPROM_FAULT_28, _EEPROM_FAULT_29, _EEPROM_FAULT_30
|
|
};
|
|
|
|
Fault::Fault()
|
|
: code(invalidCode)
|
|
, active(false)
|
|
{
|
|
}
|
|
|
|
Fault::Fault(FaultCode fcode, const u16 id_)
|
|
: code(fcode)
|
|
, id(id_)
|
|
, counterActivated(0)
|
|
, counterDeactivated(0)
|
|
{
|
|
timeActivated = currMillis;
|
|
}
|
|
|
|
Fault::Fault(const Fault &other)
|
|
{
|
|
id = other.id;
|
|
code = other.code;
|
|
timeActivated = other.timeActivated;
|
|
timeDeactivated = other.timeDeactivated;
|
|
timeActivatedOverflow = other.timeActivatedOverflow;
|
|
timeDeactivatedOverflow = other.timeDeactivatedOverflow;
|
|
active = other.active;
|
|
counterActivated = other.counterActivated;
|
|
counterDeactivated = other.counterDeactivated;
|
|
_of1 = other._of1;
|
|
_of2 = other._of2;
|
|
}
|
|
|
|
Fault::Fault(const SavedFault &other)
|
|
{
|
|
id = other.id;
|
|
code = other.code;
|
|
active = other.active;
|
|
counterActivated = other.counterActivated + 1;
|
|
if (other.deactivated) {
|
|
timeDeactivated = 0;
|
|
counterDeactivated = other.counterDeactivated + 1;
|
|
} else {
|
|
counterDeactivated = 0;
|
|
}
|
|
}
|
|
|
|
static char __buff_1[30];
|
|
|
|
const char* Fault::title()
|
|
{
|
|
switch(code) {
|
|
case t1TooHi:
|
|
(zones > 1) ? getMyStr200(STR_T1_TOO_HI) : getMyStr200(STR_T_TOO_HI);
|
|
break;
|
|
case t1TooLo:
|
|
(zones > 1) ? getMyStr200(STR_T1_TOO_LO) : getMyStr200(STR_T_TOO_LO);
|
|
break;
|
|
case t2TooHi:
|
|
getMyStr200(STR_T2_TOO_HI);
|
|
break;
|
|
case t2TooLo:
|
|
getMyStr200(STR_T2_TOO_LO);
|
|
break;
|
|
case pTooHi:
|
|
getMyStr200(STR_P_TOO_HI);
|
|
break;
|
|
case pTooLo:
|
|
getMyStr200(STR_P_TOO_LO);
|
|
break;
|
|
case t1Invalid:
|
|
case t2Invalid:
|
|
getMyStr200(STR_T_FAIL);
|
|
break;
|
|
case pInvalid:
|
|
getMyStr200(STR_P_FAIL);
|
|
break;
|
|
default:
|
|
getMyStr200(STR_UNKNOWN_ERROR);
|
|
}
|
|
if (active) {
|
|
strcpy(__buff_1, "*");
|
|
strcat(__buff_1, charBuffer200);
|
|
return __buff_1;
|
|
}
|
|
return charBuffer200;
|
|
}
|
|
|
|
const char* Fault::activatedText()
|
|
{
|
|
const u32 diff = currMillis - timeActivated;
|
|
u16 result;
|
|
if (counterActivated) {
|
|
sprintf(__buff_1, getMyStr200(STR_UNKNOWN_ACTIVATED), counterActivated);
|
|
} else if (timeActivatedOverflow) {
|
|
return getMyStr200(STR_GT_7_WEEKS_1);
|
|
} else if (diff < 100000) { // < 100 Sekunden
|
|
result = diff / 1000;
|
|
sprintf(__buff_1, getMyStr200(STR_F_SECONDS_1), result);
|
|
} else if (diff < 6000000) { // < 100 Minuten
|
|
result = diff / 60000;
|
|
sprintf(__buff_1, getMyStr200(STR_F_MINUTES_1), result);
|
|
} else if (diff < 172800000) { // < 48 Stunden
|
|
result = diff / 3600000;
|
|
sprintf(__buff_1, getMyStr200(STR_F_HOURS_1), result);
|
|
} else { // Tage
|
|
result = diff / 86400000;
|
|
sprintf(__buff_1, getMyStr200(STR_F_DAYS_1), result);
|
|
}
|
|
return __buff_1;
|
|
}
|
|
|
|
const char* Fault::deactivatedText()
|
|
{
|
|
const u32 diff = currMillis - timeDeactivated;
|
|
u16 result;
|
|
if (timeDeactivatedOverflow) {
|
|
return getMyStr200(STR_GT_7_WEEKS_2);
|
|
} else if (counterDeactivated) {
|
|
sprintf(__buff_1, getMyStr200(STR_UNKNOWN_DEACTIVAED), counterDeactivated);
|
|
} else if (timeDeactivated == 0xFFFFFFFF) { // wurde nie deaktiviert
|
|
sprintf(__buff_1, (active) ? getMyStr200(STR_NEVER_DEACTIVATED_ACTIVE) : getMyStr200(STR_NEVER_DEACTIVATED_INACTIVE));
|
|
} else if (diff < 100000) { // < 100 Sekunden
|
|
result = diff / 1000;
|
|
sprintf(__buff_1, getMyStr200(STR_F_SECONDS_2), result);
|
|
} else if (diff < 6000000) { // < 100 Minuten
|
|
result = diff / 60000;
|
|
sprintf(__buff_1, getMyStr200(STR_F_MINUTES_2), result);
|
|
} else if (diff < 172800000) { // < 48 Stunden
|
|
result = diff / 3600000;
|
|
sprintf(__buff_1, getMyStr200(STR_F_HOURS_2), result);
|
|
} else { // Tage
|
|
result = diff / 86400000;
|
|
sprintf(__buff_1, getMyStr200(STR_F_DAYS_2), result);
|
|
}
|
|
return __buff_1;
|
|
}
|
|
|
|
void Fault::process()
|
|
{
|
|
if (!counterActivated) {
|
|
if (!_of1 && currMillis < timeActivated)
|
|
_of1 = true;
|
|
else if (!timeActivatedOverflow && _of1 && currMillis > timeActivated)
|
|
timeActivatedOverflow = true;
|
|
if (!active && !_of2 && currMillis < timeDeactivated)
|
|
_of2 = true;
|
|
else if (!timeDeactivatedOverflow && _of2 && currMillis > timeDeactivated)
|
|
timeDeactivatedOverflow = true;
|
|
}
|
|
}
|
|
|
|
|
|
FaultSettings faultSettings;
|
|
|
|
FaultList::FaultList()
|
|
{
|
|
EEPROM.get(_EEPROM_FAULT_LAST_ID, _lastID);
|
|
if (_lastID == 0xFFFF)
|
|
_lastID = 0;
|
|
uint8_t count = EEPROM.read(_EEPROM_FAULT_COUNT);
|
|
_size = (count > _MAX_FAULTS) ? 0 : count;
|
|
for (u8 i=0; i<_size; i++) {
|
|
SavedFault savedFault;
|
|
u16 id, reg_1, reg_2;
|
|
EEPROM.get(EEPROM_FAULTS[i], id);
|
|
EEPROM.get(EEPROM_FAULTS[i] + 2, reg_1);
|
|
EEPROM.get(EEPROM_FAULTS[i] + 4, reg_2);
|
|
u8 rawCode = reg_1 >> 12;
|
|
if (reg_2 >> 14 || rawCode > 9 || id == 0 || id == 0xFFFF) {
|
|
// unter einer dieser Bedingungen wären die Daten nicht gültig
|
|
savedFault.id = 0;
|
|
savedFault.code = invalidCode;
|
|
savedFault.active = false;
|
|
savedFault.deactivated = true;
|
|
savedFault.counterActivated = 0;
|
|
savedFault.counterDeactivated = 0;
|
|
} else {
|
|
savedFault.id = id;
|
|
savedFault.counterActivated = reg_1 & 0xFFF;
|
|
savedFault.counterDeactivated = reg_2 & 0xFFF;
|
|
savedFault.active = bitRead(reg_2, 12);
|
|
savedFault.deactivated = bitRead(reg_2, 13);
|
|
switch (rawCode) {
|
|
case t1TooHi:
|
|
savedFault.code = t1TooHi;
|
|
if (savedFault.active) {
|
|
_lastActiveT1Fault = savedFault.code;
|
|
_t1Active = true;
|
|
}
|
|
break;
|
|
case t1TooLo:
|
|
savedFault.code = t1TooLo;
|
|
if (savedFault.active) {
|
|
_lastActiveT1Fault = savedFault.code;
|
|
_t1Active = true;
|
|
}
|
|
break;
|
|
case t1Invalid:
|
|
savedFault.code = t1Invalid;
|
|
if (savedFault.active) {
|
|
_lastActiveT1Fault = savedFault.code;
|
|
_t1Active = true;
|
|
}
|
|
break;
|
|
case t2TooHi:
|
|
savedFault.code = t2TooHi;
|
|
if (savedFault.active) {
|
|
_lastActiveT2Fault = savedFault.code;
|
|
_t2Active = true;
|
|
}
|
|
break;
|
|
case t2TooLo:
|
|
savedFault.code = t2TooLo;
|
|
if (savedFault.active) {
|
|
_lastActiveT2Fault = savedFault.code;
|
|
_t2Active = true;
|
|
}
|
|
break;
|
|
case t2Invalid:
|
|
savedFault.code = t2Invalid;
|
|
if (savedFault.active) {
|
|
_lastActiveT2Fault = savedFault.code;
|
|
_t2Active = true;
|
|
}
|
|
break;
|
|
case pTooHi:
|
|
savedFault.code = pTooHi;
|
|
if (savedFault.active) {
|
|
_lastActivePFault = savedFault.code;
|
|
_pActive = true;
|
|
}
|
|
break;
|
|
case pTooLo:
|
|
savedFault.code = pTooLo;
|
|
if (savedFault.active) {
|
|
_lastActivePFault = savedFault.code;
|
|
_pActive = true;
|
|
}
|
|
break;
|
|
case pInvalid:
|
|
savedFault.code = pInvalid;
|
|
if (savedFault.active) {
|
|
_lastActivePFault = savedFault.code;
|
|
_pActive = true;
|
|
}
|
|
break;
|
|
default:
|
|
savedFault.code = invalidCode;
|
|
}
|
|
}
|
|
_list[i] = savedFault;
|
|
_save(i);
|
|
#if _MODBUS == 1
|
|
_setModbusAlarm(_list[i], i, true);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void FaultList::process()
|
|
{
|
|
FaultState s = noFault;
|
|
for (u8 i=0; i<_size; i++) {
|
|
Fault &f = _list[i];
|
|
f.process();
|
|
bool wasActive = f.active;
|
|
switch (f.code) {
|
|
case t1TooHi:
|
|
case t1TooLo:
|
|
case t1Invalid:
|
|
_test(f, _t1Active, _lastActiveT1Fault);
|
|
break;
|
|
case t2TooHi:
|
|
case t2TooLo:
|
|
case t2Invalid:
|
|
_test(f, _t2Active, _lastActiveT2Fault);
|
|
break;
|
|
case pTooHi:
|
|
case pTooLo:
|
|
case pInvalid:
|
|
_test(f, _pActive, _lastActivePFault);
|
|
}
|
|
switch (s) {
|
|
case inactiveFault:
|
|
if (f.active)
|
|
s = activeFault;
|
|
break;
|
|
case activeFault:
|
|
break;
|
|
default: // noFault
|
|
s = (f.active) ? activeFault : inactiveFault;
|
|
}
|
|
if (f.active != wasActive) {
|
|
// _printf("save in process(): ");
|
|
_save(i);
|
|
}
|
|
#if _MODBUS == 1
|
|
_setModbusAlarm(f, i, false);
|
|
#endif
|
|
}
|
|
_state = s;
|
|
}
|
|
|
|
bool FaultList::check(FaultCode code, int16_t val=0)
|
|
{
|
|
if (_size >= _MAX_FAULTS)
|
|
return false;
|
|
switch (code) {
|
|
case t1TooHi:
|
|
if (code == _lastActiveT1Fault || currMillis - _lastT1Idle < _CHECK_T_FAULT_INTERVAL
|
|
|| faultSettings.tMinFRate < _compT1 - vals.t1)
|
|
return false;
|
|
_t1Active = true;
|
|
_lastActiveT1Fault = code;
|
|
break;
|
|
case t1TooLo:
|
|
if (code == _lastActiveT1Fault || currMillis - _lastT1Idle < _CHECK_T_FAULT_INTERVAL
|
|
|| faultSettings.tMinFRate < vals.t1 - _compT1)
|
|
return false;
|
|
_t1Active = true;
|
|
_lastActiveT1Fault = code;
|
|
break;
|
|
case t1Invalid:
|
|
if (code == _lastActiveT1Fault || currMillis - _lastT1Idle < _CHECK_T_FAULT_INTERVAL)
|
|
return false;
|
|
_t1Active = true;
|
|
_lastActiveT1Fault = code;
|
|
break;
|
|
case t2TooHi:
|
|
if (code == _lastActiveT2Fault || currMillis - _lastT2Idle < _CHECK_T_FAULT_INTERVAL
|
|
|| faultSettings.tMinFRate < _compT2 - vals.t2)
|
|
return false;
|
|
_t2Active = true;
|
|
_lastActiveT2Fault = code;
|
|
break;
|
|
case t2TooLo:
|
|
if (code == _lastActiveT2Fault || currMillis - _lastT2Idle < _CHECK_T_FAULT_INTERVAL
|
|
|| faultSettings.tMinFRate < vals.t2 - _compT2)
|
|
return false;
|
|
_t2Active = true;
|
|
_lastActiveT2Fault = code;
|
|
break;
|
|
case t2Invalid:
|
|
if (code == _lastActiveT2Fault || currMillis - _lastT2Idle < _CHECK_T_FAULT_INTERVAL)
|
|
return false;
|
|
_t2Active = true;
|
|
_lastActiveT2Fault = code;
|
|
break;
|
|
case pTooHi:
|
|
if (code == _lastActivePFault || currMillis - _lastPIdle < _CHECK_P_FAULT_INTERVAL
|
|
|| faultSettings.pMinRate < _compP - val)
|
|
return false;
|
|
_pActive = true;
|
|
_lastActivePFault = code;
|
|
break;
|
|
case pTooLo:
|
|
if (code == _lastActivePFault || currMillis - _lastPIdle < _CHECK_P_FAULT_INTERVAL
|
|
|| faultSettings.pMinRate < val - _compP)
|
|
return false;
|
|
_pActive = true;
|
|
_lastActivePFault = code;
|
|
break;
|
|
case pInvalid:
|
|
if (code == _lastActivePFault || currMillis - _lastPIdle < _CHECK_P_FAULT_INTERVAL)
|
|
return false;
|
|
_pActive = true;
|
|
_lastActivePFault = code;
|
|
break;
|
|
}
|
|
_lastID++;
|
|
if (_lastID == 0xFFFF || _lastID == 0)
|
|
_lastID = 1;
|
|
Fault f(code, _lastID);
|
|
// _printf("Nächste Alarm-ID: "); _println(_lastID);
|
|
_list[_size] = f;
|
|
// _printf("save in check(): ");
|
|
_save(_size);
|
|
_saveLastID();
|
|
_size++;
|
|
_saveSize();
|
|
#if _MODBUS == 1
|
|
_setModbusAlarm(f, _size - 1, true);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
u8 FaultList::count()
|
|
{
|
|
return _size;
|
|
}
|
|
|
|
Fault* FaultList::first()
|
|
{
|
|
if (_size)
|
|
return &_list[0];
|
|
return nullptr;
|
|
}
|
|
|
|
Fault* FaultList::last()
|
|
{
|
|
if (_size)
|
|
return &_list[_size-1];
|
|
return nullptr;
|
|
}
|
|
|
|
Fault* FaultList::at(const u8 position)
|
|
{
|
|
if (position < _size)
|
|
return &_list[position];
|
|
return nullptr;
|
|
}
|
|
|
|
bool FaultList::removeID(const u16 id)
|
|
{
|
|
for (u8 i=0; i<_size; i++) {
|
|
if (_list[i].id == id) {
|
|
return removeOne(i);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool FaultList::removeOne(const u8 position)
|
|
{
|
|
if (position < _size) {
|
|
if (_list[position].active)
|
|
return false; // aktiver Fehler soll nicht gelöscht werden!
|
|
u8 i;
|
|
for (i=position; i<_size; i++) {
|
|
if (i < _MAX_FAULTS - 1)
|
|
_list[i] = _list[i + 1];
|
|
}
|
|
_size--;
|
|
#if _MODBUS == 1
|
|
if (!_size)
|
|
// normalerweise wird der Alarm-Counter in _setModbusAlarm() gesetzt,
|
|
// aber wenn _size == 0, muss der Counter extra zurückgesetzt werden
|
|
modbusAlarms[0] = 0;
|
|
#endif
|
|
if (!_removeAllActive) {
|
|
for (i=0; i<_size; i++)
|
|
_save(i);
|
|
_saveSize();
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool FaultList::removeAll()
|
|
{
|
|
bool atLeastOneRemoved = false;
|
|
if (!_size) {
|
|
return false;
|
|
} else if (_state != activeFault) {
|
|
_size = 0;
|
|
_saveSize();
|
|
atLeastOneRemoved = true;
|
|
#if _MODBUS == 1
|
|
// normalerweise wird der Alarm-Counter in _setModbusAlarm() gesetzt,
|
|
// aber wenn _size == 0, muss der Counter extra zurückgesetzt werden
|
|
modbusAlarms[0] = 0;
|
|
#endif
|
|
} else {
|
|
_removeAllActive = true;
|
|
bool finished = false;
|
|
u8 i;
|
|
while (!finished) {
|
|
for (i=0; i<_size; i++) {
|
|
if (!_list[i].active) { // aktiver Fehler soll nicht gelöscht werden!
|
|
removeOne(i);
|
|
atLeastOneRemoved = true;
|
|
break;
|
|
}
|
|
if (i >= _size - 1)
|
|
finished = true;
|
|
}
|
|
}
|
|
for (i=0; i<_size; i++)
|
|
_save(i);
|
|
_saveSize();
|
|
_removeAllActive = false;
|
|
}
|
|
return atLeastOneRemoved;
|
|
}
|
|
|
|
FaultState FaultList::state()
|
|
{
|
|
return _state;
|
|
}
|
|
|
|
void FaultList::t1Idle() {
|
|
static bool firstRun = true;
|
|
if (!_t1Active) {
|
|
return;
|
|
}
|
|
if (firstRun) {
|
|
// Um beim ersten Idle einen ev. gespeicherten Code nicht zurückzusetzen
|
|
firstRun = false;
|
|
return;
|
|
}
|
|
_t1Active = false;
|
|
_lastActiveT1Fault = invalidCode;
|
|
}
|
|
|
|
void FaultList::t1Idle(const int16_t val)
|
|
{
|
|
_compT1 = val;
|
|
_lastT1Idle = currMillis;
|
|
t1Idle();
|
|
}
|
|
|
|
void FaultList::t2Idle() {
|
|
static bool firstRun = true;
|
|
if (!_t2Active) {
|
|
return;
|
|
}
|
|
if (firstRun) {
|
|
// Um beim ersten Idle einen ev. gespeicherten Code nicht zurückzusetzen
|
|
firstRun = false;
|
|
return;
|
|
}
|
|
_t2Active = false;
|
|
_lastActiveT2Fault = invalidCode;
|
|
}
|
|
|
|
void FaultList::t2Idle(const int16_t val)
|
|
{
|
|
_compT2 = val;
|
|
_lastT2Idle = currMillis;
|
|
t2Idle();
|
|
}
|
|
|
|
void FaultList::pIdle() {
|
|
static bool firstRun = true;
|
|
if (!_pActive) {
|
|
return;
|
|
}
|
|
if (firstRun) {
|
|
// Um beim ersten Idle einen ev. gespeicherten Code nicht zurückzusetzen
|
|
firstRun = false;
|
|
return;
|
|
}
|
|
_pActive = false;
|
|
_lastActivePFault = invalidCode;
|
|
}
|
|
|
|
void FaultList::pIdle(const int16_t val)
|
|
{
|
|
_compP = val;
|
|
_lastPIdle = currMillis;
|
|
pIdle();
|
|
}
|
|
|
|
const char* FaultList::menu()
|
|
{
|
|
if (_size) {
|
|
_str = "";
|
|
for (u8 i=0; i<_size; i++) {
|
|
_str += _list[i].title();
|
|
if (i < _size - 1)
|
|
_str += '\n';
|
|
}
|
|
return _str.c_str();
|
|
} else {
|
|
return getMyStr503(STR_NO_ERROR);
|
|
}
|
|
}
|
|
|
|
bool FaultList::tActive()
|
|
{
|
|
return _t1Active || _t2Active;
|
|
}
|
|
|
|
bool FaultList::pActive()
|
|
{
|
|
return _pActive;
|
|
}
|
|
|
|
void FaultList::_save(const u8 index)
|
|
{
|
|
// _printf("Speichere Index "); _print(index);
|
|
if (index <= _size) {
|
|
u16 reg_1 = _list[index].counterActivated;
|
|
u16 reg_2 = _list[index].counterDeactivated;
|
|
reg_1 |= _list[index].code << 12; // setze Bit 12...15
|
|
if (_list[index].active)
|
|
reg_2 |= 0x1000; // Setze Bit 12
|
|
if (_list[index].timeDeactivated != 0xFFFFFFFF)
|
|
reg_2 |= 0x2000; // Setze Bit 13
|
|
EEPROM.put(EEPROM_FAULTS[index], _list[index].id);
|
|
EEPROM.put(EEPROM_FAULTS[index] + 2, reg_1);
|
|
EEPROM.put(EEPROM_FAULTS[index] + 4, reg_2);
|
|
// _printf(", code = "); _print(_list[index].code);
|
|
// _printf(", active = "); _print(_list[index].active);
|
|
}
|
|
// _println();
|
|
}
|
|
|
|
void FaultList::_saveSize()
|
|
{
|
|
EEPROM.update(_EEPROM_FAULT_COUNT, _size);
|
|
}
|
|
|
|
void FaultList::_saveLastID()
|
|
{
|
|
EEPROM.put(_EEPROM_FAULT_LAST_ID, _lastID);
|
|
}
|
|
|
|
void FaultList::_test(Fault &f, const bool &groupActive, const FaultCode &lastActiveFault)
|
|
{
|
|
if (f.active && !groupActive) {
|
|
f.timeDeactivated =
|
|
(currMillis == 0xFFFFFFFF) ? 0xFFFFFFFE :
|
|
(currMillis == 0) ? 1 : currMillis;
|
|
f.active = false;
|
|
} else if (f.code != lastActiveFault)
|
|
f.active = false;
|
|
}
|
|
|
|
#if _MODBUS == 1
|
|
void FaultList::_setModbusAlarm(const Fault &fault, const u8 index, const bool new_)
|
|
{
|
|
u16 reg_1 = 0;
|
|
u16 reg_2 = 0;
|
|
u16 timestamp = modbusData[5] & 0xFFF;
|
|
if (fault.counterActivated) {
|
|
reg_1 = fault.counterActivated;
|
|
reg_2 = 0x1000; // Bit 12 setzen
|
|
} else if (fault.timeActivatedOverflow) {
|
|
reg_1 = 0xFFF;
|
|
reg_2 = 0x2000; // Bit 13 setzen
|
|
} else {
|
|
reg_1 = timestamp;
|
|
}
|
|
reg_1 |= fault.code << 12;
|
|
if (fault.counterDeactivated) {
|
|
reg_2 |= fault.counterDeactivated;
|
|
reg_2 |= 0x4000; // Bit 14 setzen
|
|
} else if (fault.timeDeactivatedOverflow) {
|
|
reg_2 |= 0xFFF;
|
|
reg_2 |= 0x8000; // Bit 15 setzen
|
|
} else if (fault.timeDeactivated == 0xFFFFFFFF) {
|
|
// wurde nie deaktiviert
|
|
if (!fault.active) {
|
|
// Der Alarm wurde nicht deaktiviert, sondern von einem neuen Alarm abgelöst
|
|
reg_2 |= 1;
|
|
} // else: nichts tun, die 12 MSBs von reg_2 bleiben 0
|
|
} else {
|
|
// Die Werte 0 und 1 sind reserviert, also muss der Wert hier min. 2 sein
|
|
reg_2 |= (timestamp > 1) ? timestamp : 2;
|
|
}
|
|
modbusAlarms[0] = _size;
|
|
modbusAlarms[index * 3 + 1] = fault.id;
|
|
modbusAlarms[index * 3 + 2] = reg_1;
|
|
modbusAlarms[index * 3 + 3] = reg_2;
|
|
if (new_) {
|
|
// Bit 12 gibt an, ob ein neuer Fehler aufgetreten ist - setzen
|
|
bitSet(modbusData[1], 12);
|
|
}
|
|
// _printf("alarm reg 1 (index "); _print(index*3+1); _printf("): "); _println(fault.id);
|
|
// _printf("alarm reg 2 (index "); _print(index*3+2); _printf("): "); _println(reg_1);
|
|
// _printf("alarm reg 3 (index "); _print(index*3+3); _printf("): "); _println(reg_2);
|
|
}
|
|
#endif
|
|
|
|
FaultList faults;
|