/* ----------------------------------------------------------------------------------
LIBRARY
----------------------------------------------------------------------------------
*/
#include "QuickPID.h"
#include "SetPoint.h"
#include "TimedAction.h"
#include "Countimer.h"
#include "DHT.h"
#define DOOR_CH 0
#define DOOR_AP 1
#define HEATER 0
#define COOLER 1
#define HUMIDIFIER 0
#define DEHUMIDIFIER 1
#define AUTO 0
#define MAN 1
/* ----------------------------------------------------------------------------------
PINS
----------------------------------------------------------------------------------
*/
#define LIGHT_PIN 4
#define ALARM_PIN 5
#define FAN_PIN 6
#define M_HEATER_PIN 7
#define AUXHEATER_PIN 8
#define HEATERCOOLER_PIN 9
#define COOLER_PIN 10
#define HUMDEHUM_PIN 11
#define HUM_PIN 12
#define DEHUM_PIN 13
#define DHT1_PIN 2 // Digital pin connected to the DHT sensor
#define DHT2_PIN 3 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
/*----------------------------------------------------------------------------------
OPZIONI DEI REGOLATORI
----------------------------------------------------------------------------------
*/
enum eControlMode {AUTO_ALL, AUTO_H, AUTO_C, MANUAL_ALL};
eControlMode Tctrlmode=AUTO_ALL;
eControlMode Hctrlmode=AUTO_ALL;
/*----------------------------------------------------------------------------------
STRUTTURA PROFILO TEMPERATURE
----------------------------------------------------------------------------------
*/
constexpr uint8_t NUM_STEPS = 3; // Numero di Passi del profilo
uint8_t CounterSteps=0; // Contatore passi del Profilo
uint32_t totmills=0; // Totalizzatore Millisecondi
char _readabletime[10]; // Conversione Millisec in CHAR
struct autosteps {
uint32_t duration;
float tsp;
float hsp;
};
autosteps CntSteps[NUM_STEPS]
{
{15000, 28.0,68.0}, // {7200000, 28.0,67.0}; // 2h
{10000, 26.0,68.0}, // {28800000, 26.0,67.0}; // 8h
{12000, 25.5,65.0} // {14400000, 25.0,67.0}; // 4h
};
/*----------------------------------------------------------------------------------
STRUTTURA GESTIONE ALLARMI
----------------------------------------------------------------------------------
*/
struct dataAlarm
{
uint8_t idx;
bool State;
bool Ack;
char Desc[20];
};
constexpr uint8_t NUM_ALLARM=8;
dataAlarm data[NUM_ALLARM] //an array of 10 structs of type dataAlarm
{
{0, 0, 0, "BASSO LIV. VASCA"},
{1, 0, 0, "TIMEOUT"},
{2, 0, 0, "PORTA APERTA"},
{3, 0, 0, "BASSA TEMP. CAMERA"},
{4, 0, 0, "ALTA TEMP. CAMERA"},
{5, 0, 0, "BASSA UMID. CAMERA"},
{6, 0, 0, "ALTA UMID. CAMERA"},
{7, 0, 0, "FAULT SENSORI"}
};
/* ----------------------------------------------------------------------------------
SETTINGS PID
----------------------------------------------------------------------------------
*/
const unsigned long TwinSize = 2000;
const unsigned long HwinSize = 2000;
const uint8_t debounce = 50;
float InputT, OutMHeat, SPMHeat = 27, KpM = 5, KiM = 10, KdM = 1;
float OutAux, SPAux = 25.5, KpAux = 25, KiAux = 15, KdAux = 5;
float InputRh, OutRh, SPRh = 70, KpRh = 5, KiRh = 10, KdRh = 1;
unsigned long winTStartTime, nextTSwitchTime;
unsigned long winTAuxStartTime, nextTAuxSwitchTime;
unsigned long winHStartTime, nextHSwitchTime;
/* ----------------------------------------------------------------------------------
OUTPUT STATUS
----------------------------------------------------------------------------------
*/
bool mheaterout_S = false; // Comando Relay riscaldatore principale
bool auxheaterout_S = false; // Comando Relay riscaldatore ausiliario
bool coolerout_S=false; // Comando Relay Raffreddamento
bool humidout_S=false; // Comando Relay Umidificatore
bool dehumidout_S=false; // Comando Relay DeUmidificatore
bool heatcoolout_S=HEATER; // Comando Relay Riscaldamento-Raffreddamento
bool fanout_S=0; // Comando Relay Ventola
bool humdehumout_S=HUMIDIFIER; // Comando Relay Umidificatore-DeUmidificatore
bool lightout_S=0; // Comando Relay Lampada
bool AlarmOut_S=0; // Comando Relay Allarme
/* ----------------------------------------------------------------------------------
INPUT STATUS
----------------------------------------------------------------------------------
*/
bool WaterLevel=0; // Stato Ingresso Livellostato Acqua (NA)
bool DoorState=0; // Stato Ingresso Fine Corsa Porta Aperta (NA)
/* ----------------------------------------------------------------------------------
BOOLEAN VARIABLE STATUS
----------------------------------------------------------------------------------
*/
bool CounterState=MAN; // Programmatore Steps AUTO-MAN
bool OvertTimeState=0;
bool SensorState=0;
bool HeaterCoolerState=HEATER;
bool HumDeHumState=HUMIDIFIER;
/* ----------------------------------------------------------------------------------
ENABLER STATUS
----------------------------------------------------------------------------------
*/
bool AlarmEN=1;
bool MainHeaterEN=1;
bool AuxHeaterEN=1;
bool HumEN=1;
bool DeHumEN=1;
bool FanEN=1;
bool CoolerEN=1;
bool LightEN=1;
/* ----------------------------------------------------------------------------------
ANALOG VARIABLE
----------------------------------------------------------------------------------
*/
float tcamera=20.0; // Sensore PT100 in cella
float tambient=20.0; // Sensore PT100 Ambiente
float t1=20.0; // T da Sensore DHT22(1)
float t2=20.0; // T da Sensore DHT22(2)
float tavg=26.8; // Tavg=(T1+T2)/2
float h1=65.0; // T da Sensore DHT22(2)
float h2=65.0; // T da Sensore DHT22(2)
float havg=69.0; // RHavg=(T1+T2)/2
float AuxHeaterOffset= 1.5; // Offset tra SP Principale e AUX
/* ----------------------------------------------------------------------------------
OBJECT DECLARATION
----------------------------------------------------------------------------------
*/
Countimer tCounter; // OGGETTO COUNTER
DHT dht1(DHT1_PIN, DHTTYPE); // OGGETTO DHT SENSORE 1
DHT dht2(DHT2_PIN, DHTTYPE); // OGGETTO DHT SENSORE 2
SetPoint spHeatCool; // REGOLATORE HEATER/COOLER
SetPoint spHumDeHum; // REGOLATORE UMIDIFICATORE/DEUM.
TimedAction slowtask = TimedAction(1000,&Task1000); // Task SLOW (1 secondo)
TimedAction fasttask = TimedAction(100,&Task200);
TimedAction FANtask = TimedAction(30000,&TaskFAN); // Task VENTOLA (su condizione)
TimedAction Lighttask = TimedAction(60000,&TaskLIGHT); // Task LUCE (su condizione) AUTOSPEGNIMENTO 60sec.
QuickPID PIDM(&InputT, &OutMHeat, &SPMHeat, KpM, KiM, KdM,
PIDM.pMode::pOnError,
PIDM.dMode::dOnMeas,
PIDM.iAwMode::iAwClamp,
PIDM.Action::direct);
QuickPID PIDAux(&InputT, &OutAux, &SPAux, KpAux, KiAux, KdAux,
PIDAux.pMode::pOnError,
PIDAux.dMode::dOnMeas,
PIDAux.iAwMode::iAwClamp,
PIDAux.Action::direct);
QuickPID PIDRh(&InputRh, &OutRh, &SPRh, KpRh, KiRh, KdRh,
PIDRh.pMode::pOnError,
PIDRh.dMode::dOnMeas,
PIDRh.iAwMode::iAwClamp,
PIDRh.Action::direct);
float mapFloat(float value, float fromLow, float fromHigh, float toLow, float toHigh) {
return (value - fromLow) * (toHigh - toLow) / (fromHigh - fromLow) + toLow;
}
void setup() {
pinMode(LIGHT_PIN, OUTPUT); // LUCE
pinMode(ALARM_PIN, OUTPUT); // ALLARME
pinMode(M_HEATER_PIN, OUTPUT); // RISCALDATORE PRINCIPALE
pinMode(AUXHEATER_PIN, OUTPUT); // RISCALDATORE AUSILIARIO
pinMode(HEATERCOOLER_PIN, OUTPUT); // RISCALDAMENTO-RAFFRESCAMENTO
pinMode(COOLER_PIN, OUTPUT); // RAFFREDDAMENTO
pinMode(HUMDEHUM_PIN, OUTPUT); // UMIFICATORE-DEUMIFICATORE
pinMode(HUM_PIN, OUTPUT); // UMIFICATORE
pinMode(DEHUM_PIN, OUTPUT); // DEUMIDIFICATORE
pinMode(FAN_PIN, OUTPUT); // UMIDITY
pinMode(A0, INPUT_PULLUP); // TEMPERATURA
pinMode(A1, INPUT_PULLUP); // UMIDITA'
pinMode(A2, INPUT_PULLUP); // FINE CORSA PORTA CHIUSA
pinMode(A3, INPUT_PULLUP); // LIVELLOSTATO ACQUA
// --------------------- DA RIMUOVERE -----------------------
pinMode(A4, INPUT_PULLUP); // RESET ALARM
pinMode(A5, INPUT_PULLUP); // TIMER STEPS (AUTO/MAN)
pinMode(A6, INPUT_PULLUP); // START TIMER
pinMode(A7, INPUT_PULLUP); // STOP/RESET TIMER
// --------------------- DA RIMUOVERE -----------------------
/*----------------------------------------------------------------------------------
DHT22 inizializzazione CLASSE
----------------------------------------------------------------------------------
*/
dht1.begin(); // SENSORE 1 DHT22
dht2.begin(); // SENSORE 2 DHT22
/*----------------------------------------------------------------------------------
Counter inizializzazione CLASSE
----------------------------------------------------------------------------------
*/
CounterState=MAN;
tCounter.setCounter(0, 0, 10, tCounter.COUNT_UP, tCounterComplete);
tCounter.setInterval(onRunningCounter, 1000);
Lighttask.disable();
spHeatCool.begin(27.0,1.0,2.0);
spHeatCool.minvalue(0);
spHeatCool.maxvalue(50);
spHeatCool.attach(L_OUT, onLOutT); // Evento per 1° Soglia L
spHeatCool.attach(H_OUT, onHOutT); // Evento per 1° Soglia H
spHeatCool.attach(HH_EDGE, onHHTemp); // Evento per 2° Soglia HH
spHeatCool.attach(LL_EDGE, onLLTemp); // Evento per 2° Soglia LL
spHeatCool.attach(HHLL_Reset,ontHHLLReset); // Rientro Allarme HHLL
// ----------------------------------------------------------------------------------
// Setup REGOLATORE UMIDIFICATORE
// ----------------------------------------------------------------------------------
spHumDeHum.begin(70.0, 3,5);
spHumDeHum.minvalue(0);
spHumDeHum.maxvalue(100);
spHumDeHum.stepvalue(0.5);
spHumDeHum.attach(L_OUT, onLOutH); // Evento per 1° Soglia L
spHumDeHum.attach(H_OUT, onHOutH); // Evento per 1° Soglia H
spHumDeHum.attach(HH_EDGE, onHHRH); // Evento per 1° Soglia HH
spHumDeHum.attach(LL_EDGE, onLLRH); // Evento per 1° Soglia LL
spHumDeHum.attach(HHLL_Reset,onRhHHLLReset); // Rientro Allarme HHLL
//spHumDeHum.attach(OUT_CHANGE,onRHOutChange); // Evento MANUAL/AUTO SWITCH OUTPUT
PIDM.SetOutputLimits(0, TwinSize);
PIDM.SetSampleTimeUs(TwinSize * 1000);
PIDAux.SetOutputLimits(0, TwinSize);
PIDAux.SetSampleTimeUs(TwinSize * 1000);
setTcontrolmode(AUTO_ALL);
setHcontrolmode(AUTO_ALL);
PIDRh.SetOutputLimits(0, HwinSize);
PIDRh.SetSampleTimeUs(HwinSize * 1000);
PIDRh.SetMode(PIDRh.Control::automatic);
Serial.begin(9600);
}
void loop() {
fasttask.check(); //200ms
slowtask.check(); //1sec
FANtask.check(); //Ciclico
Lighttask.check(); //su richiesta
tCounter.run();
}
void Task200(){
bool doorsw;
bool waterLL;
unsigned long msNow = millis();
//tcamera=mapFloat(analogRead(A0) , 0, 1023, 0.0, 50.0);
//tambient=mapFloat(analogRead(A1) , 0, 1023, 0.0, 50.0);
InputT = mapFloat(analogRead(A0) , 0, 1023, 0.0, 50.0);
InputRh = mapFloat(analogRead(A1) , 0, 1023, 0.0, 100.0);
spHeatCool.update(InputT);
spHumDeHum.update(InputRh);
// USO ANALOGICO COME DIGITALE PER LO SW PORTA
if(analogRead(A2) <512) {doorsw=LOW;}
else {doorsw=HIGH;}
if(analogRead(A3) <512) {waterLL=LOW;}
else {waterLL=HIGH;}
if (WaterLevel != waterLL) {
WaterLevel=waterLL;
setHumid_S(humidout_S);
if (WaterLevel) { SetAlarm(0,1); CheckAlarm();}
else { SetAlarm(0,0); CheckAlarm();}
}
/* ---------------------------------------------------------------------------
------------------------------- RESET ALLARMI -----------------------------
---------------------------------------------------------------------------
*/
if(analogRead(A4) <512) {AckAlarms();}
/* ---------------------------------------------------------------------------
------------------------------- TIMER STEPS AUT/MAN -----------------------
---------------------------------------------------------------------------
*/
if(analogRead(A5) <512) {
if (CounterState==MAN) {CounterState=AUTO; Serial.println("AUTOTIMERSTEPS");}
else {CounterState=MAN;Serial.println("MANUALTIMER");}
}
/* ---------------------------------------------------------------------------
------------------------------ GESTIONE TIMER -----------------------------
---------------------------------------------------------------------------
*/
if(analogRead(A6) <512) {
if (CounterState==MAN) {
if (!tCounter.isCounterRunning()) {
tCounter.start(); Serial.println("Counter START");
}
else if (!tCounter.isStopped() && tCounter.isStarted()) {
tCounter.pause(); Serial.println("Counter PAUSA");
}
}
else if (CounterState==AUTO) {RunAutoProfile(0); }
}
if(analogRead(A7) <512) {
if (!tCounter.isCounterCompleted()) {
OvertTimeState=0;
tCounter.stop(); Serial.println("Counter STOP");}
}
/* ---------------------------------------------------------------------------
------------------------------ GESTIONE PORTA -----------------------------
---------------------------------------------------------------------------
*/
if ((DoorState == DOOR_CH) && (doorsw == DOOR_AP)) {
// DOOR NOW IS OPEN
Lighttask.disable();
SetLight(HIGH);
SetAlarm(2,1);
}
else if ((DoorState == DOOR_AP) && (doorsw == DOOR_CH)) {
//DOOR NOW IS CLOSE
SetAlarm(2,0);
Serial.println("DOOR is Close Light TURN-OFF In few seconds");
if (lightout_S==1) {
Lighttask.enable();
Lighttask.reset();
//SetLight(LOW);
}
}
// When Door state CHANGE refresh Relay State
if (DoorState!=doorsw) {
DoorState=doorsw;
setMainHeater_S(mheaterout_S);
setAuxHeater_S(auxheaterout_S);
SetFan(fanout_S);
setCooler_S(coolerout_S);
setHumid_S(humidout_S);
setDehum_S(dehumidout_S);
CheckAlarm();
}
if (PIDM.Compute()) winTStartTime = msNow;
if (msNow > nextTSwitchTime) {
nextTSwitchTime = msNow + debounce;
if (heatcoolout_S==HEATER){
if (!mheaterout_S && OutMHeat > (msNow - winTStartTime)) {setMainHeater_S(HIGH); }
else if (mheaterout_S && OutMHeat < (msNow - winTStartTime)) {setMainHeater_S(LOW); }
}
else if (heatcoolout_S==COOLER){
if (!coolerout_S && OutMHeat > (msNow - winTStartTime)) {setCooler_S(HIGH); }
else if (coolerout_S && OutMHeat < (msNow - winTStartTime)) {setCooler_S(LOW); }
}
}
if (PIDAux.Compute()) winTAuxStartTime = msNow;
if (msNow > nextTAuxSwitchTime) {
nextTAuxSwitchTime = msNow + debounce;
if (heatcoolout_S==HEATER){
if (!auxheaterout_S && OutAux > (msNow - winTAuxStartTime)) {setAuxHeater_S(HIGH); }
else if (auxheaterout_S && OutAux < (msNow - winTAuxStartTime)){setAuxHeater_S(LOW); }
}
}
if (PIDRh.Compute()) winHStartTime = msNow;
if (msNow > nextHSwitchTime) {
nextHSwitchTime = msNow + debounce;
if (humdehumout_S==HUMIDIFIER) {
if (!humidout_S && OutRh > (msNow - winHStartTime)) {setHumid_S(HIGH); }
else if (humidout_S && OutRh < (msNow - winHStartTime)) {setHumid_S(LOW); }
}
else if (humdehumout_S==DEHUMIDIFIER) {
if (!dehumidout_S && OutRh > (msNow - winHStartTime)) {setDehum_S(HIGH); }
else if (dehumidout_S && OutRh < (msNow - winHStartTime)) {setDehum_S(LOW); }
}
}
}
void Task1000(){
/*
h1 = dht1.readHumidity(); // read Umidity 1
t1 = dht1.readTemperature(); // read temperature 1
h2 = dht2.readHumidity(); // read Umidity 2
t2 = dht2.readTemperature(); // read temperature 2
// Check if any reads failed and exit early (to try again).
mySensor= isnan(h1) || isnan(t1) || isnan(h2) || isnan(t2)
if (SensorState != mySensor) {
if (mySensor==1) {
SensorState=mySensor;
SetAlarm(7,1);
CheckAlarm();
Serial.println(F("Failed to read from DHT sensor!"));
return;
}
else {
SensorState=mySensor;
SetAlarm(7,0));
CheckAlarm();
}
}
tavg=(t1+t2)/2;
havg=(h1+h2)/2;
InputT = tavg;
InputRh = havg;
*/
if (tCounter.isStopped()){
Serial.print("Sp:" + String(SPMHeat,1)+ " T:" + String(InputT,1) + " - OutM:" + String(OutMHeat,1) + " - OAux:" + String(OutAux,1));
Serial.println(" | spRh:" + String(SPRh,1) + " Rh:" + String(InputRh,1) + " - ORh:" + String(OutRh,1));
}
}
void TaskLIGHT(){
SetLight(LOW);
//Lighttask.disable(); Serial.println("LIGHT is OFF");
}
void TaskFAN(){
bool bFan=!fanout_S;
if (bFan==1) {FANtask.setInterval(30000);}
else {FANtask.setInterval(60000);}
SetFan(bFan);
}
void onRunningCounter()
{
if (!tCounter.isStopped()){
if (CounterState==AUTO) {
// AGGIORNA TIMER+STEP SE IN AUTOCOUNTER
Serial.print(timetoreadabletime(totmills+tCounter.getCurrentMills()));
Serial.print(" " + String(CounterSteps) + "°) ");
Serial.print("Sp:" + String(SPMHeat,1)+ " T:" + String(InputT,1) + " | OutM:" + String(OutMHeat,1) + " OAux:" + String(OutAux,1));
Serial.print(" | spRh:" + String(SPRh,1) + " Rh:" + String(InputRh,1) + " | ORh:" + String(OutRh,1) + "| T:");
Serial.print(tCounter.getCurrentTimeLeft());
Serial.print("-");
Serial.println(tCounter.getCurrentTime());
}
else {
// AGGIORNA TIMER SE IN MANUAL
if (OvertTimeState==1) {
Serial.print("Over (");
Serial.print(timetoreadabletime(totmills+tCounter.getCurrentMills()));
Serial.print(") ");
}
Serial.print("Sp:" + String(SPMHeat,1)+ " T:" + String(InputT,1) + " | OutM:" + String(OutMHeat,1) + " OAux:" + String(OutAux,1));
Serial.print(" | spRh:" + String(SPRh,1) + " Rh:" + String(InputRh,1) + " | ORh:" + String(OutRh,1) + "| T:");
Serial.print(tCounter.getCurrentTimeLeft());
Serial.print("-");
Serial.println(tCounter.getCurrentTime());
}
}
}
void tCounterComplete() {
if (CounterState==AUTO) {
totmills+=CntSteps[CounterSteps].duration;
CounterSteps++;
if (CounterSteps<NUM_STEPS){
RunAutoProfile(CounterSteps);
// AGGIORNAMENTO DISPLAY
// ...
}
else {
//FINITO I 3 STEPS AUTOMATICI
CounterState=MAN;
CounterSteps=0;
tCounter.stop();
OvertTimeState=1; // ATTIVA EXTRATIME
tCounter.setCounter(0,0,10); // TIMER MANUALE EXTRATEMPO SE IL L'ULTIMO STEP AUTO NON FOSSE SUFFICIENTE
tCounter.start(); // FA RIPARTIRE IL TIMER SE SCADUTO ULTIMO STEP
SetAlarm(1,1);
CheckAlarm();
}
}
else if (CounterState=MAN)
{
SetAlarm(1,1);
CheckAlarm();
}
}
void RunAutoProfile(uint8_t step)
{
if (step==0) {
totmills=0;
OvertTimeState=0;
CounterSteps=0;
}
SPMHeat=CntSteps[step].tsp;
SPAux=SPMHeat-AuxHeaterOffset;
SPRh=CntSteps[step].hsp;
tCounter.setCounter(CntSteps[step].duration);
spHeatCool.threshold(SPMHeat);
spHumDeHum.threshold(SPRh);
// AGGIORNAMENTO DISPLAY
// ...
if (!tCounter.isCounterRunning()) {tCounter.start();}
}
char* timetoreadabletime(uint32_t millisec) {
//uint16_t milliseconds = millisec % 1000; // ms remaining when converted to seconds
uint16_t allSeconds = millisec / 1000; // convert millseconds to seconds
uint16_t hours = allSeconds / 36000; // convert millseconds to hours
uint16_t secondsRemaining = allSeconds % 36000; // milliseconds left over
uint8_t minutes = secondsRemaining / 60 ; // convert milliseconds left over to minutes
uint8_t seconds = secondsRemaining % 60; // milliseconds left over
sprintf(_readabletime, "%02d:%02d:%02d", hours, minutes, seconds);
return _readabletime;
}
void onLOutT() {
PIDM.SetControllerDirection(PIDM.Action::direct);
if (heatcoolout_S != HEATER) {PIDM.Reset();}
heatcoolout_S = HEATER;
setCooler_S(LOW);
digitalWrite(HEATERCOOLER_PIN, LOW);
}
void onHOutT() {
PIDM.SetControllerDirection(PIDM.Action::reverse);
if (heatcoolout_S != COOLER) {PIDM.Reset();PIDAux.Reset();}
heatcoolout_S = COOLER;
setMainHeater_S(LOW);
setAuxHeater_S(LOW);
digitalWrite(HEATERCOOLER_PIN, HIGH);
}
void onLLTemp() {SetAlarm(3,1); CheckAlarm(); }
void onHHTemp() {
FANtask.disable();
SetFan(1);
SetAlarm(4,1); CheckAlarm();
}
void ontHHLLReset() {Serial.println("Reset T HHLL");
FANtask.enable();
SetAlarm(3,0); SetAlarm(4,0);
CheckAlarm();
}
void setTcontrolmode(eControlMode value) {
Tctrlmode=value;
switch (value)
{
case AUTO_ALL:
heatcoolout_S = HEATER;
spHeatCool.SetAUTOMATIC();
PIDM.SetMode(PIDM.Control::automatic);
PIDAux.SetMode(PIDAux.Control::automatic);
break;
case AUTO_H:
PIDM.SetMode(PIDM.Control::automatic);
PIDAux.SetMode(PIDAux.Control::automatic);
PIDM.SetControllerDirection(PIDM.Action::direct);
heatcoolout_S = HEATER;
spHeatCool.SetMANUAL_ON();
//digitalWrite(HEATERCOOLER_PIN, LOW);
break;
case AUTO_C:
PIDM.SetMode(PIDM.Control::automatic);
PIDM.SetControllerDirection(PIDM.Action::reverse);
PIDAux.SetMode(PIDAux.Control::manual);
heatcoolout_S = COOLER;
spHeatCool.SetMANUAL_OFF();
//digitalWrite(HEATERCOOLER_PIN, HIGH);
break;
case MANUAL_ALL:
PIDM.SetMode(PIDM.Control::manual);
PIDAux.SetMode(PIDAux.Control::manual);
heatcoolout_S = HEATER;
spHeatCool.SetMANUAL_ON();
break;
default: break;
}
PIDM.Reset();
PIDAux.Reset();
}
void onLOutH() {
PIDRh.SetControllerDirection(PIDRh.Action::direct);
if (humdehumout_S != HUMIDIFIER) {PIDRh.Reset(); }
humdehumout_S = HUMIDIFIER;
setDehum_S(LOW);
digitalWrite(HUMDEHUM_PIN, LOW);
}
void onHOutH() {
PIDRh.SetControllerDirection(PIDRh.Action::reverse);
if (humdehumout_S != DEHUMIDIFIER) {PIDRh.Reset(); }
humdehumout_S = DEHUMIDIFIER;
setHumid_S(LOW);
digitalWrite(HUMDEHUM_PIN, HIGH);
}
void onLLRH() {SetAlarm(5,1);CheckAlarm();}
void onHHRH() {SetAlarm(6,1);CheckAlarm();}
void onRhHHLLReset() {Serial.println("Reset Rh HHLL");
SetAlarm(5,0); SetAlarm(6,0);
CheckAlarm();
}
void setHcontrolmode(eControlMode value) {
Hctrlmode=value;
switch (value)
{
case AUTO_ALL:
humdehumout_S = HUMIDIFIER;
spHumDeHum.SetAUTOMATIC();
PIDRh.SetMode(PIDRh.Control::automatic);
break;
case AUTO_H:
PIDRh.SetMode(PIDRh.Control::automatic);
PIDRh.SetControllerDirection(PIDRh.Action::direct);
humdehumout_S = HUMIDIFIER;
spHumDeHum.SetMANUAL_ON();
//digitalWrite(HUMDEHUM_PIN, LOW);
break;
case AUTO_C:
PIDRh.SetMode(PIDRh.Control::automatic);
PIDRh.SetControllerDirection(PIDRh.Action::reverse);
humdehumout_S = DEHUMIDIFIER;
spHumDeHum.SetMANUAL_OFF();
//digitalWrite(HUMDEHUM_PIN, HIGH);
break;
case MANUAL_ALL:
PIDRh.SetMode(PIDRh.Control::manual);
humdehumout_S = HUMIDIFIER;
spHumDeHum.SetMANUAL_ON();
//digitalWrite(HUMDEHUM_PIN, LOW);
break;
default: break;
}
PIDRh.Reset();
}
void setMainHeater_S(bool value) {
mheaterout_S = value && MainHeaterEN && (heatcoolout_S == HEATER);
digitalWrite(M_HEATER_PIN, mheaterout_S && (DoorState==DOOR_CH));
}
void setAuxHeater_S(bool value) {
auxheaterout_S = value && AuxHeaterEN && (heatcoolout_S == HEATER);
digitalWrite(AUXHEATER_PIN, auxheaterout_S && (DoorState==DOOR_CH));
}
void setCooler_S(bool value) {
coolerout_S = value && CoolerEN && (heatcoolout_S == COOLER);
digitalWrite(COOLER_PIN, coolerout_S && (DoorState==DOOR_CH));
}
void setHumid_S(bool value) {
humidout_S = value && HumEN && (humdehumout_S == HUMIDIFIER);
digitalWrite(HUM_PIN, humidout_S && (DoorState==DOOR_CH) && !WaterLevel);
}
void setDehum_S(bool value) {
dehumidout_S = value && DeHumEN && (humdehumout_S == DEHUMIDIFIER);
digitalWrite(DEHUM_PIN, dehumidout_S && (DoorState==DOOR_CH));
}
/* ---------------------------------------------------------------------------
-------------------------------- FAN START -------------------------------
---------------------------------------------------------------------------
*/
void SetFan(bool value) {
fanout_S=value && FanEN ;
digitalWrite(FAN_PIN, fanout_S && (DoorState==DOOR_CH));
// SET ICON ON DISPLAY
// ....
}
/* ---------------------------------------------------------------------------
------------------------------- LIGHT START ------------------------------
---------------------------------------------------------------------------
*/
void SetLight(bool value) {
if ((lightout_S=!value) && lightout_S) {Lighttask.disable();}
lightout_S=value && LightEN;
digitalWrite(LIGHT_PIN, lightout_S || DoorState==DOOR_AP);
// SET ICON ON DISPLAY
// ....
}
/* ---------------------------------------------------------------------------
------------------------------- ALARM START ------------------------------
---------------------------------------------------------------------------
*/
void SetAlarm(uint8_t idx, bool value){
bool bAlarm=0;
data[idx].State=value;
if (value==1) {data[idx].Ack=value;}
// SET ICON ON DISPLAY
// ....
}
void CheckAlarm(){
bool bAlarm=0;
for (uint8_t i = 0; i < NUM_ALLARM; i = i + 1) {
bAlarm=bAlarm || data[i].State || data[i].Ack;
if (data[i].State && data[i].Ack) {Serial.println(data[i].Desc);}
}
if (AlarmOut_S!=bAlarm) {
AlarmOut_S=bAlarm;
digitalWrite(ALARM_PIN, (AlarmOut_S || (DoorState==DOOR_AP)) && AlarmEN);
}
// SET ICON ON DISPLAY
// ....
}
void AckAlarms(){
for (byte i = 0; i < NUM_ALLARM; i = i + 1) {
if (data[i].Ack){data[i].Ack=0;}
}
AlarmOut_S=LOW;
digitalWrite(ALARM_PIN, AlarmOut_S);
/* BUZZER
SET ICON ON DISPLAY
....
*/
}