DreherTankController/src/controller/controller.cpp

298 lines
9.2 KiB
C++

#include "controller.h"
Controller::Controller(const uint8_t pAnalaogPin,
const uint8_t oneWirePin,
parameters *p,
values *v,
Display *d,
PSensor *s,
valveStates *vStates,
const uint8_t t1Pin,
const uint8_t t2Pin,
const uint8_t pRisePin,
const uint8_t pFallPin)
: _aPin(pAnalaogPin)
, _oneWire(oneWirePin)
, _params(p)
, _vals(v)
, _display(d)
, _pSensor(s)
, _vStates(vStates)
, _prPin(pRisePin)
, _pfPin(pFallPin)
, _t1Pin(t1Pin)
, _t2Pin(t2Pin)
, _dallas(&_oneWire)
{
pinMode(_prPin, OUTPUT);
pinMode(_pfPin, OUTPUT);
pinMode(_t1Pin, OUTPUT);
pinMode(_t2Pin, OUTPUT);
digitalWrite(_prPin, 0);
digitalWrite(_pfPin, 0);
digitalWrite(_t1Pin, 0);
digitalWrite(_t2Pin, 0);
_vStates->pInc = false;
_vStates->pDec = false;
_vStates->t1 = false;
}
void Controller::init(bool startup=false)
{
_dallas.begin();
_dallas.setWaitForConversion(false);
const uint8_t maxDevices = 1;
uint8_t deviceCount = _dallas.getDS18Count();
if (deviceCount > maxDevices) {
_display->tooMuchOneWireDevicesDetected(deviceCount, maxDevices);
} else if (!deviceCount) {
_display->noOneWireDevicesDetected();
} else {
_initOk = true;
_dallas.getAddress(_tempAddr1, 0);
_dallas.setResolution(12);
if (!startup)
_display->oneWireDevicesDetected(deviceCount);
}
}
void Controller::process()
{
if (_initOk && millis() - _lastConversion > _TEMP_CONVERSION_DELAY) {
_lastConversion = millis();
_requestConversion = true;
float temp = _dallas.getTempC(_tempAddr1);
if (temp == DEVICE_DISCONNECTED_C)
_vals->t1 = _SENSOR_FAULT;
else
_vals->t1 = temp * 100;
_prints("Temp: "); _prints(_vals->t1);
if (_vals->t1 != _SENSOR_FAULT && _params->tEn && _params->cEn) {
switch (_tState) {
case stateIdle:
_printsln(", case stateIdle");
if (_vals->t1 < _params->ts1 - _params->th1) {
_setT1Valve(0, stateRising);
_prints(" -> rising");
} else if (_vals->t1 > _params->ts1 + _params->th1) {
_setT1Valve(1, stateFalling);
_prints(" -> falling");
}
_printsln();
break;
case stateRising:
_prints(", case stateRising");
if (_vals->t1 > _params->ts1 + _params->th1) {
_setT1Valve(1, stateIdle);
_prints(" -> idle");
}
_printsln();
break;
case stateFalling:
_prints(", case stateFalling");
if (_vals->t1 < _params->ts1 - _params->th1) {
_setT1Valve(0, stateIdle);
_prints(" -> idle");
}
_printsln();
break;
}
} else {
_setT1Valve(0, stateIdle);
_printsln();
}
#if _MODBUS == 1
_averageTemperature1();
#endif
} else if (_requestConversion) {
_requestConversion = false;
_dallas.requestTemperatures();
}
if (millis() - _lastAnalogRead > _ANALOG_READ_DELAY) {
_lastAnalogRead = millis();
_rawP = analogRead(_aPin);
_prints("_rawP: "); _prints(_rawP);
switch (*_pSensor) {
case SMC_1_5V_0_5BAR:
float p = (float) _rawP / 2.046f; // 1023 / 5 * 100 (0-5 1/100 bar)
p = (p - 1) * 1.25f; // 1...5 V Sensor
_prints(" (Gems), p: "); _prints(p);
if (p < -0.5f) // Sensor ist definitiv nicht angeschlossen
_vals->p = _SENSOR_FAULT;
else if (p < 0) // Bei kleiner Toleranz ein bisschen schwindeln ;-)
_vals->p = 0;
else
_vals->p = p;
break;
case GEMS_0_5V_0_6BAR:
_vals->p = (float) _rawP / 1.705f; // 1023 / 6 * 100 (0-5 1/100 bar)
_prints(" (Gems), p: "); _prints(_vals->p);
}
#if _MODBUS == 1
_averagePressure();
#endif
if (_vals->p != _SENSOR_FAULT && _params->cEn) {
switch (_pState) {
case stateIdle:
_prints(", case stateIdle");
if (_vals->p < _params->ps - _params->ph) {
if (_params->pInc) {
_printsln(" -> stateRising");
_setPValves(stateRising);
} else {
_printsln();
_setPValves(stateIdle);
}
} else if (_vals->p > _params->ps + _params->ph) {
if (_params->pDec) {
_printsln(" -> stateFalling");
_setPValves(stateFalling);
} else {
_printsln();
_setPValves(stateIdle);
}
} else _printsln();
break;
case stateRising:
_prints(", case stateRising");
if ((_params->pInc && _vals->p > _params->ps) || !_params->pInc) {
_prints(" -> stateIdle");
_setPValves(stateIdle);
}
_printsln();
break;
case stateFalling:
_prints(", case stateFalling");
if ((_params->pDec && _vals->p < _params->ps) || !_params->pDec) {
_prints(" -> stateIdle");
_setPValves(stateIdle);
}
_printsln();
break;
}
} else {
_printsln();
_setPValves(stateIdle);
}
_prints("_vStates->pInc: "); _prints(_vStates->pInc);
_prints(", _vStates->pDec: "); _printsln(_vStates->pDec);
}
}
void Controller::_setT1Valve(uint8_t val, States state)
{
_tState = state;
digitalWrite(_t1Pin, val);
_vStates->t1 = val;
_setModbusValve(_MODBUS_VALVE_T1_INDEX, val);
}
void Controller::_setPValves(States state)
{
_pState = state;
switch (state) {
case stateRising:
digitalWrite(_prPin, 1);
_vStates->pInc = true;
_setModbusValve(_MODBUS_VALVE_PR_INDEX, 1);
digitalWrite(_pfPin, 0);
_vStates->pDec = false;
_setModbusValve(_MODBUS_VALVE_PF_INDEX, 0);
break;
case stateFalling:
digitalWrite(_pfPin, 1);
_vStates->pDec = true;
_setModbusValve(_MODBUS_VALVE_PF_INDEX, 1);
digitalWrite(_prPin, 0);
_vStates->pInc = false;
_setModbusValve(_MODBUS_VALVE_PR_INDEX, 0);
break;
default: // idle valves
digitalWrite(_pfPin, 0);
_vStates->pDec = false;
_setModbusValve(_MODBUS_VALVE_PF_INDEX, 0);
digitalWrite(_prPin, 0);
_vStates->pInc = false;
_setModbusValve(_MODBUS_VALVE_PR_INDEX, 0);
}
}
#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(")");
_t1_c = 0;
_t2_c = 0;
_p_c = 0;
_t1_of = false;
_t2_of = false;
_p_of = false;
}
inline void Controller::_averageTemperature1()
{
int32_t total = 0;
int16_t result = _SENSOR_FAULT;
u8 valid = 0;
u8 invalid = 0;
if (_t1_c >= _T_ARR_LEN) {
_t1_c = 0;
_t1_of = true;
}
// Falls das Array schon voll ist, wird es wieder vom Anfang befüllt
_t1_arr[_t1_c++] = _vals->t1;
// Dabei läuft die for-Schleife dann über alle Einträge, ansonsten nur bis zum aktuellen
u16 loopTill = (_t1_of) ? _T_ARR_LEN : _t1_c;
for (u16 i=0; i<loopTill; i++) {
if (_t1_arr[i] != _SENSOR_FAULT) {
total += _t1_arr[i];
valid++;
} else {
invalid++;
}
}
if (valid >= invalid) {
result = total / valid;
}
modbusData[_MODBUS_T1_INDEX] = result;
// _setModbusValue(_MODBUS_T1_INDEX, result);
}
inline void Controller::_averageTemperature2()
{
// noch nicht implementiert
}
inline void Controller::_averagePressure()
{
int32_t total = 0;
int16_t result = _SENSOR_FAULT;
u8 valid = 0;
u8 invalid = 0;
if (_p_c >= _P_ARR_LEN) {
_p_c = 0;
_p_of = true;
}
// Falls das Array schon voll ist, wird es wieder vom Anfang befüllt
_p_arr[_p_c++] = _vals->p;
// Dabei läuft die for-Schleife dann über alle Einträge, ansonsten nur bis zum aktuellen
u16 loopTill = (_p_of) ? _P_ARR_LEN : _p_c;
for (u16 i=0; i<_p_c; i++) {
if (_p_arr[i] != _SENSOR_FAULT) {
total += _p_arr[i];
valid++;
} else {
invalid++;
}
}
if (valid >= invalid) {
result = total / valid;
}
modbusData[_MODBUS_P_INDEX] = result;
// _setModbusValue(_MODBUS_P_INDEX, result);
}
#endif // _MODBUS == 1