// STATIE DE EPURARE CU BAZINE IBC
/* ^
. CONDUCTE PVC |
. _______________________________________________|__________________
. | ___________________|_______________ |
. | | | | |
| | __|_____|__ | __|_____|__ | | | |
| | | | | | | | | | | | | | |
| BAZIN 0 | | BAZIN 1 | | | | BAZIN 2 | | |
| | | | | | | | | |
| NU ARE POMPE | | POMPE | | | | POMPE | | |
| | | | | | EVACUARE EXT. | | |
| | | AERARE EVACUARE B2 | | AERARE RECIRCULARE B1/B0 |
|______________________| |______________________| |__________________________|
*/
/********* ATENTIE !!! **********/
// Ca Debouncer pt plutitori se utilizeza CI MAX6818
// Pinul A0 este senzorul de nivel din BAZIN 1
// Pinul A1 este senzorul de nivel din BAZIN 2
// Pinul A2 este senzorul de prea plin BAZIN 2
// Pinul A3 sunt senzorii de prea gol din BAZIN 1 si BAZIN 2
// Pinul pcf8575 P05 comanda electrovana cu trei căi
// Pinul pcf8575 P04 este pompa de evacuare in exrterior
// Pinul pcf8575 P03 este pompa de evacuare in BAZIN 2 dupa ce s-a evacuat in exterior BAZIN 2 si se utilizeaza si la recirculare
// Pinul pcf8575 P02 este pompa de evacuare in BAZIN 0 si se utilizeaza doar la recirculare
// Pinul pcf8575 P01 este pompa de aerare Bazin 2
// Pinul pcf8575 P00 este pompa de aerare BAZIN 1
// Pinul D3 citeste senzorii de temperatura DS18B20 din fiecare bazin si din incinta
// Transmisia wireles este programata direct in IDE pt asigurare comunicatie Master - Slave
// emisia se relizeaza in functia loop la o secundă iar receptia tot in functia loop continu
// BAZIN 0 - separator grasimi si fermentare anaeroba
// BAZIN 1 si BAZIN 2 fermentare aeroba si au nevoie de casa bacteriilor (un grilaj de plastic + resturi teava PPR)
// BAZIN 0 descarca hidraulic-gravitational in BAZIN 1
// prea plinul in BAZIN 1 se realizeaza hidraulic
// legatura intre bazine este facuta pe principiul vaselor comunicante
// daca nu functioneaza pompele de evacuare, evacuarea exterioara se face natural cu
// conditia ca iesirea in exterior sa fie mai jos decat intrarea canalizarii in BAZIN 0
// rezultand o fosa septica clasica
// pompele pentru setarile de mai jos au aproximativ 100 litri / minut la 1m inaltime adica 6 mc/h, valoarea reala se determina experimental
// daca pompele au debite diferite timpii de pornire evacuare si recirculare sunt diferiti
// trebuind modificate variabilele pentru pompele de EVACUARE si RECIRCULARE
// pompa standard la care se raporteaza timpii de functionare este de 6 mc/h la 5m inaltime
// cantitatea maxima evacuata este stabilita prin plutitorii de nivel minim care intrerup pompele fara comanda din partea controlerului
// daca se opreste curentul sau apare o resetare fizica controlerul revine la valorile stocate in EEPROM
#include <LiquidCrystal.h>
#include <EEPROM.h>
//#include <SerialTransfer.h>
#include <EasyTransfer.h>//transmite pe hardware serial o structura de maxim 255 octeti
//#include <util/atomic.h>
#include <PCF8575.h>//PCF8575_library Renzo Mischianti
// senzori de temperatura
#include <OneWire.h>
#include <DallasTemperature.h>
#include <NonBlockingDallas.h>
#define RS 12
#define EN 11
#define D4 10
#define D5 9
#define D6 8
#define D7 7
LiquidCrystal lcd (RS, EN, D4, D5, D6, D7);
#define PCF8575_ADDRESS 0x20
PCF8575 pcf8575(PCF8575_ADDRESS);
//SerialTransfer HC12_Transfer;
EasyTransfer HC12_Transfer_TX_LCD;
EasyTransfer HC12_Transfer_TX_POMPA_Set;
EasyTransfer HC12_Transfer_RX_POMPA_Set;
//senzor temperatura
#define ONE_WIRE_BUS 13 // PIN of the Maxim DS18B20 temperature(s) sensor(s)
#define TIME_INTERVAL 1500 // Time interval among sensor readings [milliseconds]
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature dallasTemp(&oneWire);
NonBlockingDallas temperatureSensors(&dallasTemp);
//Stabilire pini butoane
#define PIN_BUTON_SETUP 6 // Pin digital 6
#define PIN_BUTON_TIMP_PLUS 5 // Pin digital 5
#define PIN_BUTON_TIMP_MINUS 4 // Pin digital 4
// Pin Buzzer
#define PIN_BUZZER 13 // Pin digital 13
// Variabile Meniu
char Meniu = -1; // valoarea -1 indica faptul ca nu ne aflam in meniu,
// valoarea 0 ne aflam in meniul INFO si HELP,
// restul valorilor gestioneaza afisarea meniurilor
char subMeniuAERARE = -1;
char subMeniuEVACUARE = -1;
char subMeniuRECIRCULARE = -1;
char subMeniuFLOCULANT = -1;
char subMeniuRESET_FABRICA = -1;
char subMeniuBazin_1_AERARE = -1;
char subMeniuBazin_2_AERARE = -1;
//variabila initializare ciclu cu modificarile efectuate in SETUP
bool init_SETUP = false;
// Variabile pentru intreruperea ISR() Timp
bool volatile flag_Timer1 = false;//variabila care arata ca a aparut intreruperea Timer1
//unsigned long durata = 0;//masoara timpul fara precizie de cand a fost pornit conroler-ul
//aproximativ 136 de ani dupa care trebuie resetata
unsigned long timp_Vacanta = 0;// variabila care masoara timpul pentru a verifica daca a avut loc
// evacuarea in exterior in 48 de ore timp care reprezinta minim doua
// cicluri complete de epurare prin care se determina faptul ca
// statia nu este folosita, nu are aport de apa noua pt epurare.
// aceasta variabila stabileste cand se recircula din Bazin 2
// in Bazin 0 pentru improspatare apa
long alarma_Evacuare = -1;// calculeaza timpul de la apariatia alarmei provocata
// de blocarea senzorului de nivel din Bazin 1 astfel
// încat sa fie evitata evacuarea in exterior repetitiv
// la fiecare 15 secunde care reprezinta intarzierea
// de pornire a evacuarii
// acesta variabila este resetata la inceputul evacuarii
#define INTERVAL_VACANTA 180//172800 //in secunde - implicit 48 ore si reprezinta perioada la care se declanseaza vacanta
byte vacanta = 1; // reduce timpul de aerare si creste timpul de linistire aerare si perioada recirculare pt economie de energie
// recircula o data la 24 de ore 100 litri din bazin 2 in bazin 0 pentru eliminarea
// mirosurilor, denitrificare si defosforizare
// este resetata in etapa de evacuare
// Variabile care stocheaza pinul care a generat intreruperea ISR()
// pentru pinii IMPUT_PULLUP setati pe GND care genereaza inreruperea
// pinul A0 plutitor Bazin 1 - adica bazinul 1 sa umplut si incepe etapa de evacuare in exterior apa epurata din bazin 2
// pinul A1 plutitor Bazin 2 - adica opreste evacuarea din bazin 1 in bazinul 2
// pinul A2 plutitor prea plin - cota de avarie bazin 2 si porneste evacuarea 50 litri si
// poate emite o avarie pe afisaj pompa evacuare bazin 2 stricata
bool nivel_B1_Pin_A0 = false; //plutitor nivel BAZIN 1 declanseaza evacuarea
bool nivel_B2_Pin_A1 = false; //plutitor nivel BAZIN 2 opreste umplerea bazinului 2
bool prea_plin_B2_Pin_A2 = false; //plutitor prea plin BAZIN 2 evacueaza 100 litri in exterior
#define INTARZIERE_PLUTITOR 15 // implicit 15 secunde generata pentru a adauga un surplus
// de apa de 25 litri astfel incat plutitorul sa stea inundat
bool surplus_Evacuare = false; // stabileste daca a fost eliminata apa in surplus la evacuare
// fata de limit de nivel - acest surplus exita intodeauna minim 25 litri
// pentru stabilitatea contactului plutitorului sau daca in timpul linistirii
// functioneaza prea plinul hidraulic si creste nivelul
byte intarziere_Pin_A0 = 0; // aceaste intarzieri sunt necesare pentru ca sa fie preluata
byte intarziere_Pin_A1 = 0; // distanta de contact a plutitorilor, eliminarea semnalelor
//byte intarziere_Pin_A2 = 0; // false si a semnalelor accidentale datorita efectului de val
// intarzierea este de aproximativ 15 sec. sau 25 litri,
// evenimentele declansate de plutitori apar dupa expirarea
// acestei perioade cu conditia ca plutitorul sa fie in contact
// Variabile pompe
// ATENTIE ! - sa nu se schimbe pozitia variabilelor in "struct POMPE"
// struct __attribute__((packed)) POMPE // Aceasta structura contine variabilele pentru pompe 6 mc/h si va fi transmisa
// { // wireles catre controlerul MASTER prin HC-12 433 MHz de catre SLAVE
// byte Bazin_1_Aerare = 90;// 60; // implicit 90 de secunde min 30 sec - max 240 sec pas 10 sec
// int Bazin_1_Linistire = 900;// 60; // implicit 900 de secunde min 300 sec - max 3600 sec pas 300 sec
// byte Bazin_2_Aerare = 90;//60; // implicit 90 de secunde min 30 sec - max 240 sec pas 10 sec
// int Bazin_2_Linistire = 900;//60; // implicit 900 de secunde min 300 sec - max 3600 sec pas 300 sec
// int PornireEvacuare = 180;//20; // implicit 180 de secunde min 180 sec - max 300 sec pas 10 sec - maxim 300 secunde / max 500 litri - pompa trebuie sa aiba un debit = 6 mc/h
// int LinistireEvacuare = 1800;//9; // implicit 1800 de secunde min 300 sec - max 3600 sec pas 300 sec - este folosita pentru Evacuare si Recirculare pompa 6 mc/h
// byte PornireRecirculare = 60;//30; // implicit 60 de secunde min 15 sec - max 120 sec pas 5 sec - recircula 100 litri la debitul pompelor de 6 mc/h
// byte AsteptareRecirculare = 1; // implicit 4 ore min 3 ore max 8 ore pas 1 ora - max 18 ore in secunde min 21600 - max 64800
// };
struct __attribute__((packed)) POMPE // Aceasta structura contine variabilele pentru pompe 6 mc/h si va fi transmisa
{ // wireles catre controlerul MASTER prin HC-12 433 MHz de catre SLAVE
byte Bazin_1_Aerare = 60; // implicit 90 de secunde min 30 sec - max 240 sec pas 10 sec
int Bazin_1_Linistire = 60; // implicit 900 de secunde min 300 sec - max 3600 sec pas 300 sec
byte Bazin_2_Aerare = 60; // implicit 90 de secunde min 30 sec - max 240 sec pas 10 sec
int Bazin_2_Linistire = 60; // implicit 900 de secunde min 300 sec - max 3600 sec pas 300 sec
int PornireEvacuare = 20; // implicit 180 de secunde min 180 sec - max 300 sec pas 10 sec - maxim 300 secunde / max 500 litri - pompa trebuie sa aiba un debit = 6 mc/h
int LinistireEvacuare = 20; // implicit 1800 de secunde min 300 sec - max 3600 sec pas 300 sec - este folosita pentru Evacuare si Recirculare pompa 6 mc/h
byte PornireRecirculare = 30; // implicit 60 de secunde min 15 sec - max 120 sec pas 5 sec - recircula 100 litri la debitul pompelor de 6 mc/h
byte AsteptareRecirculare = 1; // implicit 4 ore min 3 ore max 8 ore pas 1 ora - max 18 ore in secunde min 21600 - max 64800
float PompaPeristaltica_B1 = 10; // implicit 10 mililitri, minim 0 mililitri - maxim 20 mililitri pt pompa utilizata
float PompaPeristaltica_B2 = 5; // implicit 5 mililitri, minim 0 mililitri - maxim 20 mililitri pt pompa utilizata
};
struct POMPE POMPA;
struct POMPE POMPA_Set;
int PornireEvacuareInBazin2 = POMPA.PornireEvacuare + INTARZIERE_PLUTITOR; //maxim 360 secunde / max 600 litri - pompa trebuie sa aiba un debit = 6 mc/h
int LinistireREC = POMPA.LinistireEvacuare; //timpul de linistire inainte de Recirculare
#define EVACUARE_PREA_PLIN 10 // implicit 30 sec - 50 de litri pt. pompa 6 mc/h si reprezinta timpul necesar
// evacuarii unei parti din prea plin pana cand se finalizeaza etapa de evacure
// volum de prea plin Bazin 2 = 100 litri
unsigned int ORA_Recirculare = 0; // este utilizata pentru recirculare, masoara o ora pentru a decrementa Recirculare.CL
#define NR_SEC_ORA 20 //constanta care contine nr de secunde dintr-o ora adica 3600
// aceasta structura este operata in interiorul functiei call_ISR_Timer()
struct Timer_Releu // aceasta structura este un constructor pentru a putea fi initializata ca mai jos
{
Timer_Releu ( int op, int cl, bool ss) :
OP {op}, CL {cl}, SS {ss} {}
int OP = 0; //" OPEN "timpul in secunde pt. care RELEUL este normal deschis NO
int CL = 0; //" CLOSE "timpul in in secunde pt. care RELEUL este normal inchis NC
bool SS = false; //" START - STOP " - 0 opreste , 1 porneste un eveniment (actioneaza un releu)
//dupa actiunea STOP/START trebuie reinitializati timpii OP, CL, LP
};
// initializez variabilele pentru relee pompe
struct Timer_Releu AerareB1 = {POMPA.Bazin_1_Aerare, POMPA.Bazin_1_Linistire, true };
struct Timer_Releu AerareB2 = {POMPA.Bazin_2_Aerare, POMPA.Bazin_2_Linistire, true };
struct Timer_Releu Recirculare = {POMPA.PornireRecirculare, POMPA.AsteptareRecirculare , true };
struct Timer_Releu Evacuare = {POMPA.PornireEvacuare, POMPA.LinistireEvacuare, false };
// Structura pentru afisarea ETAPEI / STARII pe LCD si transmitere date wireles prin HC-12
struct __attribute__((packed)) LCD20x4 // Aceasta structura contine textul afisat pe
{ // fiecare linie a afisajului LCD20x4
String Line0 = " "; // Aceasta structura va fi transmisa wireles
String Line1 = " "; // catre controlerul SLAVE prin HC-12 433 MHz
String Line2 = " "; // pt afisare pe SLAVE in inmp real
String Line3 = " "; // transmiterea datelor se efectueaza in functia StareCiclu
byte Alarma[6] = {0, 0, 0, 0, 0, 0}; // stocheaza nr. de aparitii a alarmelor si numara pana la max. 255 de aparatii
// si este transmisa wireles prin HC-12
float Temperatura[5] = {0, 0, 0, 0, 0}; // stocheaza temperatura din Bazin 0, Bazin 1, Bazin 2, incapere, exterior
} LCD;
char alarma = 0; // stabileste tipul de alarma si ia valori
// 1 si 2 pt prea plin BAZIN 2
// 3 cand plutitorul de nivel maxim din BAZIN 2 este blocat sau pompa
// de evacuare in exterior este arsa
// 4 senzor nivel defect sau murdar si nu cupleaza in Bazin 1 sau pompa de
// evacuare in Bazin 2 este arsa
// 5 cand pompa de evacuare este arsa sau senzor de prea plin defect sau murdar/lipit
// 6 cand cel putin un bazin este sub nivelul de minim si este permanenta - adica prea gol si nu se porneste nicio pompa
// alarmele se elimina prin resetare alarma chiar daca senzorii de nivel revin la normal
// si practic pompele nu sunt arse
// resetarea alarmei se realizeaza prin resetare fizica a microcontroleru-lui
// momentan microcontrolerul nu poate determina daca o anumita pompa este arsa fizic
// alarmele se bazeaza doar pe starea senzorilor de nivel
bool dozareFLOCULANT = false;// variabila care devine true cand se termina umplerea bazin 2 dupa evacuare pentru a introduce floculant
byte timpDozareFLOCULANT = 0;// timpul care stabileste cat floculant se dozeza - 90 ml/min
// max 255 secude sau 4.25 min
// se va verifica fizic cu pompa peristaltica in functiune
#define DEBIT_POMPA_PERISTALTICA 90 // 90 ml/min - se determina fizic pe pompa peristaltica
char info_help = 0;// var. pt afisare info despre temperatura si alarme sau help afisand textul alarmei
/************************ FUNCTII SENZOR TEMPERATURA DS18B20 ********************************/
//Invoked ONLY when the temperature changes between two VALID sensor readings. "valid" parameter will be removed in a feature version
void handleTemperatureChange(int deviceIndex, int32_t temperatureRAW)
{
for (size_t i = 0; i < temperatureSensors.getSensorsCount(); i++)
{
LCD.Temperatura[i] = temperatureSensors.getTemperatureC(i);
Serial.println(LCD.Temperatura[i]);
// Serial.print(F("[Sensor index="));
// Serial.print(i);
// Serial.println(F("]"));
// Serial.print(F(" * Print all temperatures formats by using index | RAW="));
// Serial.print(temperatureSensors.getTemperatureRAW(i));
// Serial.print(F(" °C="));
// Serial.print(temperatureSensors.getTemperatureC(i));
// Serial.print(F(" °F="));
// Serial.println(temperatureSensors.getTemperatureF(i));
}
//Serial.println("==============================================================");
}// end handleTemperatureChange()
/************************ FUNCTII TRANSMITERE WIRELES PRIN HC12 *****************************/
// Aceste functii TX_HC12 si RX_HC12 primesc si transmit date catre slave - adica in casa
// se foloseste biblioteca EasyTRansfer deoarece stie sa transmita structuri si array
// face si un CRC de verificare a datelor primite
// se vor transmite :
// - structura LCD20x4
// se receptioneaza variabilla :
// - POMPA_Set
inline void tx_HC12 (const byte& tip) // transmitere date
{
// EasyTRansfer poate trimite o singura structura de maxim 255 octeti
// tip 1 - transmite struct LCD
// tip 2 - transmite POMPA_Set
///////////////////////////////////////// Send buffer
switch (tip)
{
case 1:
HC12_Transfer_TX_LCD.sendData();// este folosit in functia loop
break;
case 2:
HC12_Transfer_TX_POMPA_Set.sendData();// este folosit in functia Scrie_Citeste_EEPROM
break; // cand se seteaza master pt a transmite la slave
}
}// end TX_HC12
inline void rx_HC12 () // receptionare date
{
// use this variable to keep track of how many
// bytes we've processed from the receive buffer
if (HC12_Transfer_RX_POMPA_Set.receiveData())
{
init_SETUP = true;
Scrie_Citeste_EEPROM(2);// ATENTIE MARE !!! se arde memoria
// prima data te joci cu variabila sa fi
// sigur ca transmisia se realizeaza o singura data
}
} // end RX_HC12
/*********************** FUNCTII PENTRU INTRERUPERILE ISR() *********************************/
/************ FUNCTIE CARE AFISEAZA ALTERNANT STARE/ALARM IN CAZUL APARITIEI ALARMEI *************/
inline String Stare_Alarma ()
{
// in cazul aparitiei unei alarme se va afisa alternant STARE/ALARM
// si activez led si buzzer pe pin D13 (PB5) care sa atentioneze ca
// a aparut cel putin o alarma
unsigned long tmp = 0;
static bool stare_Alarma = false;
//String tmpSTR ="";
for (uint8_t i = 0; i <= 5; i++) { tmp += LCD.Alarma[i]; }
if (tmp == 0 ) {pcf8575.digitalWrite( 8, HIGH); return(vacanta == 1 ? F("STARE ") : F("VEGHE "));}
else if (tmp != 0 && stare_Alarma == false) {stare_Alarma = true; pcf8575.digitalWrite( 8, HIGH); return (vacanta == 1 ? F("STARE ") : F("VEGHE "));}
else if (tmp != 0 && stare_Alarma == true) {stare_Alarma = false; pcf8575.digitalWrite( 8, LOW); return (F("ALARMA"));}
} //End Stare_Alarma
/******************* FUNCTIE ALARME *************************/
// acesta functie scrie variabila LCD cu textul necesar afisarii alarmelor
//
void Alarme (char& tipAlarma)
{
String tmp = "";
switch (tipAlarma)
{
case 1: //PREA PLIN BAZIN 2
LCD.Line0 = F("(A1) ALARM PREAPLIN "); //strcpy(LCD.Line0 , tmp.c_str());
LCD.Line1 = F(" Verifica evacuarea."); //strcpy(LCD.Line1 , tmp.c_str());
LCD.Line2 = F(" Debit mare, peste "); //strcpy(LCD.Line2 , tmp.c_str());
LCD.Line3 = F(" 20 litri / min. "); //strcpy(LCD.Line3 , tmp.c_str());
break;
case 2: //PREA PLIN BAZIN 2
LCD.Line0 = F("(A2) ALARM PREAPLIN "); //strcpy(LCD.Line0 , tmp.c_str());
LCD.Line1 = F("Pompa Evac.P2.2 arsa"); //strcpy(LCD.Line1 , tmp.c_str());
LCD.Line2 = F("sau plutitor prea - "); //strcpy(LCD.Line2 , tmp.c_str());
LCD.Line3 = F("plin BAZIN 2 blocat."); //strcpy(LCD.Line3 , tmp.c_str());
break;
case 3: //EVACUARE
LCD.Line0 = F("(A3) ALARM EVACUARE "); //strcpy(LCD.Line0 , tmp.c_str());
LCD.Line1 = F("Pompa de evacuare in"); //strcpy(LCD.Line1 , tmp.c_str());
LCD.Line2 = F("exterior P2.2 arsa. "); //strcpy(LCD.Line2 , tmp.c_str());
LCD.Line3 = F("Senzor nivel blocat."); //strcpy(LCD.Line3 , tmp.c_str());
break;
case 4: //EVACUARE
LCD.Line0 = F("(A4)ALARM UMPLERE B2"); ////strcpy(LCD.Line0 , tmp.c_str());
LCD.Line1 = F("Senzorii de nivel "); //strcpy(LCD.Line1 , tmp.c_str());
LCD.Line2 = F("defecti sau murdari/"); //strcpy(LCD.Line2 , tmp.c_str());
LCD.Line3 = F("P1.2 umplere B2 arsa"); //strcpy(LCD.Line3 , tmp.c_str());
break;
case 5: //EVACUARE
LCD.Line0 = F("(A5) ALARM EVACUARE "); ////strcpy(LCD.Line0 , tmp.c_str());
LCD.Line1 = F(" ATENTIE ! "); //strcpy(LCD.Line1 , tmp.c_str());
LCD.Line2 = F("Pompa de evacuare in"); //strcpy(LCD.Line2 , tmp.c_str());
LCD.Line3 = F("exterior P2.2 arsa. "); //strcpy(LCD.Line3 , tmp.c_str());
break;
case 6: //PREA GOL
LCD.Line0 = F("(A6) ALARM PREA-GOL "); ////strcpy(LCD.Line0 , tmp.c_str());
LCD.Line1 = F(" ATENTIE ! "); //strcpy(LCD.Line1 , tmp.c_str());
LCD.Line2 = F(" NIVELUL APEI ESTE "); //strcpy(LCD.Line2 , tmp.c_str());
LCD.Line3 = F(" SUB COTA ADMISA "); //strcpy(LCD.Line3 , tmp.c_str());
break;
}
}
/************************* FUNCTIE AFISARE STARE CICLU **************************************/
// Acesta functie afiseaza etapa in care se afla statia de epurare
void StareCiclu ( uint8_t etapa = 0)
{
if (Meniu == 0) return;
//struct LCD20x4 LCD;
String INDENT = F("> ");
String SPATII_2 = F(" ");
String SPATII_4 = F(" ");
String SEC = F("sec");
String LINISTIRE = F("Linistire ");
String EVACUARE = F("Evacuare ");
String UMPLERE = F("Umplere ");
String AMESTEC = F("Amestec ");
String tmp = "";
static byte timpAfisareAlarma = 0; // afisaza alarma timp de 10 sec la aparitia acesteia dupa care o reseteza
// pentru a nu bloca afisajul afisindu-se in continuare STAREA in care se afla statia
tmp = Stare_Alarma();
//-----------------------------------------------------------------
if ((timpAfisareAlarma == 10) && (alarma > 2 && alarma < 6)) // afisez alarma tip 3, 4 si 5 timp de 10 sec. de la apariția acesteia dupa care se reseteaza
{ // evenimentele privind nr aparitiei alarmelor sunt stocate in variabila LCD.Alarma[0-5]
alarma = 0; timpAfisareAlarma = 0;
}
else if ((alarma > 2) && (alarma < 6)) {timpAfisareAlarma++; }
// Serial.print(alarma);
// Serial.print("-----");
// Serial.println(timpAfisareAlarma);
if ( alarma ) etapa = 4;
//------------------------------------------------------------------
if (Meniu > 0) etapa = 5; // nu se afiseaza etapa deoarece se seteaza Mcu MASTER
// este folosit numai pentru transmitere si afisare pe
// Mcu SLAVE faptul ca MASTER se afla in SETUP
switch (etapa)
{
case 1: //EVACUARE
//if ( alarma ) break;
tmp += F("<< EVACUARE >>");
LCD.Line0 = tmp; //strcpy(LCD.Line0 , tmp.c_str());
tmp = String(Evacuare.CL); tmp += SPATII_4;
if(Evacuare.CL > 0) tmp = (INDENT + LINISTIRE + tmp.substring(0,5) + SEC);
else tmp = (SPATII_2 + LINISTIRE + tmp.substring(0,5) + SEC);
LCD.Line1 = tmp; //strcpy(LCD.Line1, tmp.c_str());
tmp = String(Evacuare.OP) + SPATII_4;
if(Evacuare.OP > 0 && Evacuare.CL == 0) tmp = (INDENT + EVACUARE + tmp.substring(0,5) + SEC);
else tmp = (SPATII_2 + EVACUARE + tmp.substring(0,5) + SEC);
LCD.Line2 = tmp; //strcpy(LCD.Line2, tmp.c_str());
tmp = String(PornireEvacuareInBazin2) +SPATII_4;
if(PornireEvacuareInBazin2 > 0 && Evacuare.OP == 0) tmp = (INDENT + UMPLERE + tmp.substring(0,5) + SEC);
else tmp = (SPATII_2 + UMPLERE + tmp.substring(0,5) + SEC);
LCD.Line3 = tmp; //strcpy(LCD.Line3, tmp.c_str());
break;
case 2: //RECIRCULARE
//if ( alarma ) break;
tmp += F("<< RECIRCUL >>");
LCD.Line0 = tmp; //strcpy(LCD.Line0 , tmp.c_str());
tmp = String(LinistireREC) + SPATII_4 ;
if(LinistireREC > 0) tmp = (INDENT + LINISTIRE + tmp.substring(0,5) + SEC);
else tmp = (SPATII_2 + LINISTIRE + tmp.substring(0,5) + SEC);
LCD.Line1 = tmp; //strcpy(LCD.Line1, tmp.c_str());
tmp = String(Recirculare.OP) + SPATII_4;
if(Recirculare.OP > 0 && LinistireREC == 0) tmp = (INDENT + AMESTEC + tmp.substring(0,5) + SEC);
else tmp = (SPATII_2 + AMESTEC + tmp.substring(0,5) + SEC);
LCD.Line2 = tmp; //strcpy(LCD.Line2, tmp.c_str());
tmp = F(" --------- ---- ---");
LCD.Line3 = tmp; //strcpy(LCD.Line3, tmp.c_str());
break;
case 3: //AERARE
//if ( alarma ) break;
tmp += F("<< AERARE >>");
LCD.Line0 = tmp; //strcpy(LCD.Line0 , tmp.c_str());
tmp = F(" Bazin 1 Bazin 2");
LCD.Line1 = tmp; //strcpy(LCD.Line1 , tmp.c_str());
tmp = F("AER ");
tmp += String(AerareB1.OP) + SPATII_4;
tmp = (tmp.substring(0,8) + SEC + SPATII_2 );
LCD.Line2 = tmp; //strcpy(LCD.Line2 , tmp.c_str());
tmp = String(AerareB2.OP) + SPATII_4;
tmp = tmp.substring(0,4) + SEC;
LCD.Line2 += tmp; //strcat(LCD.Line2 , tmp.c_str());
tmp = F("LIN ");
tmp += String(AerareB1.CL) + SPATII_4;
tmp = (tmp.substring(0,8) + SEC + SPATII_2);
LCD.Line3 = tmp; //strcpy(LCD.Line3 , tmp.c_str());
tmp = String(AerareB2.CL) + SPATII_4;
tmp = (tmp.substring(0,4) + SEC);
LCD.Line3 += tmp; //strcat(LCD.Line3 , tmp.c_str());
break;
case 4: // ALARME
Alarme (alarma);
break;
case 5: // MESAJ NUMAI PENTRU Mcu SLAVE
LCD.Line0 = F(" ATENTIE ! "); //strcpy(LCD.Line0 , tmp.c_str());
LCD.Line1 = F(" MCU MASTER SE AFLA "); //strcpy(LCD.Line1 , tmp.c_str());
LCD.Line2 = F(" IN MENIUL SETUP "); //strcpy(LCD.Line2 , tmp.c_str());
LCD.Line3 = F("NU UMBLATI LA SETARI"); //strcpy(LCD.Line3 , tmp.c_str());
return;
break;
}
if (Meniu == 0) return;
lcd.setCursor (0,0); lcd.print(LCD.Line0); //((char*)LCD.Line0);
lcd.setCursor (0,1); lcd.print(LCD.Line1); //((char*)LCD.Line1);
lcd.setCursor (0,2); lcd.print(LCD.Line2); //((char*)LCD.Line2);
lcd.setCursor (0,3); lcd.print(LCD.Line3); //((char*)LCD.Line3);
// tmp = "";
// strcpy(LCD.Line0 , tmp.c_str());
// strcpy(LCD.Line1 , tmp.c_str());
// strcpy(LCD.Line2 , tmp.c_str());
// strcpy(LCD.Line3 , tmp.c_str());
// INDENT = "";
// SPATII_2 = "";
// SPATII_4 = "";
// SEC = "";
// LINISTIRE = "";
// EVACUARE = "";
// UMPLERE = "";
// AMESTEC = "";
}// end StareCiclu
/******************** FUNCTIE INITIALIZARE CICLU ***********************/
void Initializare_Ciclu ()
{
//oprim toate pompele
pcf8575.digitalWrite( 4, HIGH); // opreste releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
pcf8575.digitalWrite( 3, HIGH); // opreste releul de pe pinul pcf8575 P03 care activeaza pompa de evacuare in bazin 2
pcf8575.digitalWrite( 2, HIGH); // opreste releul de pe pinul pcf8575 P02 care activeaza pompa de evacuare in bazin 0
pcf8575.digitalWrite( 1, HIGH); // opreste releul de pe pinul pcf8575 P00 care activeaza pompa de aerare bazin 1
pcf8575.digitalWrite( 0, HIGH); // opreste releul de pe pinul pcf8575 P01 care activeaza pompa de aerare bazin 2
// reseteaza intarzierea
intarziere_Pin_A0 = 0;
intarziere_Pin_A1 = 0;
//reinitializez toate variabilele pentru o etapa de epurare noua
Scrie_Citeste_EEPROM (1);
AerareB1 = {POMPA.Bazin_1_Aerare, POMPA.Bazin_1_Linistire , true };
AerareB2 = {POMPA.Bazin_2_Aerare, POMPA.Bazin_2_Linistire , true };
Recirculare = {POMPA.PornireRecirculare, POMPA.AsteptareRecirculare , true };
Evacuare = {POMPA.PornireEvacuare, POMPA.LinistireEvacuare, false};
PornireEvacuareInBazin2 = POMPA.PornireEvacuare + INTARZIERE_PLUTITOR;
ORA_Recirculare = 0; //daca apare evenimentul evacuare si recircularea nu s-a efectuat
LinistireREC = POMPA.LinistireEvacuare;
// schimb pozitia electrovanei cu trei cai penru recirculare normala
if (timp_Vacanta < INTERVAL_VACANTA) pcf8575.digitalWrite( 5, HIGH);
}
/************************ DOZARE FLOCULANT **************************/
// aceasta functie porneste pompele peristaltice pentru dozarea floculantului
// procesul are loc la finalul etapei de evacuare
// pt dizolvarea/amestecarea floculantului se realizeaza in etapa de aerare
// bazin = 0 - continua dozarea implicit
// 1 - dozeaza doar in bazin 1
// 2 - dozeaza doar in bazin 2
// 3 - dozeaza in bazin 1 si bazin 2
inline void Dozare_Floculant (const byte& bazin = 0)
{
if (timpDozareFLOCULANT == 0)
{
dozareFLOCULANT = true;
if (bazin == 1 || bazin == 3)
{
pcf8575.digitalWrite( 0, LOW); // porneste releul de pe pinul pcf8575 P01 care activeaza pompa de aerare bazin 2
pcf8575.digitalWrite( 6, LOW); // porneste releul de pe pinul pcf8575 P06 care activeaza pompa peristaltica bazin 1
}
if (bazin == 2 || bazin == 3)
{
pcf8575.digitalWrite( 1, LOW); // porneste releul de pe pinul pcf8575 P00 care activeaza pompa de aerare bazin 1
pcf8575.digitalWrite( 7, LOW); // porneste releul de pe pinul pcf8575 P07 care activeaza pompa peristaltica bazin 2
}
}
timpDozareFLOCULANT++;
if (POMPA.PompaPeristaltica_B1 > POMPA.PompaPeristaltica_B2)
{
if (timpDozareFLOCULANT > ((POMPA.PompaPeristaltica_B1 / DEBIT_POMPA_PERISTALTICA) * 60))// secunde
{
pcf8575.digitalWrite( 6, HIGH); // opreste releul de pe pinul pcf8575 P06 care activeaza pompa peristaltica bazin 1
timpDozareFLOCULANT = 0;
dozareFLOCULANT = false;
}
if (timpDozareFLOCULANT > ((POMPA.PompaPeristaltica_B2 / DEBIT_POMPA_PERISTALTICA) * 60 ))// secunde
{
pcf8575.digitalWrite( 7, HIGH); // opreste releul de pe pinul pcf8575 P06 care activeaza pompa peristaltica bazin 2
}
}
else if (POMPA.PompaPeristaltica_B2 > POMPA.PompaPeristaltica_B1)
{
if (timpDozareFLOCULANT > ((POMPA.PompaPeristaltica_B1 / DEBIT_POMPA_PERISTALTICA) * 60))// secunde
{
pcf8575.digitalWrite( 6, HIGH); // opreste releul de pe pinul pcf8575 P06 care activeaza pompa peristaltica bazin 1
}
if (timpDozareFLOCULANT > ((POMPA.PompaPeristaltica_B2 / DEBIT_POMPA_PERISTALTICA) * 60))// secunde
{
pcf8575.digitalWrite( 7, HIGH); // opreste releul de pe pinul pcf8575 P06 care activeaza pompa peristaltica bazin 2
timpDozareFLOCULANT = 0;
dozareFLOCULANT = false;
}
}
else // (POMPA.PompaPeristaltica_B1 == POMPA.PompaPeristaltica_B2)
{
if (timpDozareFLOCULANT > ((POMPA.PompaPeristaltica_B1 / DEBIT_POMPA_PERISTALTICA) * 60))// secunde
{
pcf8575.digitalWrite( 6, HIGH); // opreste releul de pe pinul pcf8575 P06 care activeaza pompa peristaltica bazin 1
pcf8575.digitalWrite( 7, HIGH); // opreste releul de pe pinul pcf8575 P06 care activeaza pompa peristaltica bazin 1
timpDozareFLOCULANT = 0;
dozareFLOCULANT = false;
}
}
}//end Dozare_Floculant()
/**************************** FUNCTIE RECUPERARE TIMP LINISTIRE *****************************************/
// Acesta functie returneaza timpul recuperat dintr-o perioada de linistire aerare sau recirculare
// si se utilizeaza pt micsorarea timpului de linistire la evacuare si recirculare
unsigned int Recuperare_Timp_Linistire()
{
int RecTimpLinistire = 0;
if ((AerareB1.OP == 0 && AerareB2.OP == 0) ) // etapa de evacuare sau recirculare a aparut in perioada linistirii aerarii
{
if ((POMPA.Bazin_1_Linistire * vacanta - AerareB1.CL) >= (POMPA.Bazin_2_Linistire * vacanta - AerareB2.CL))// retine cel mai mic timp de linistire in timpul aerarii
{
RecTimpLinistire = POMPA.Bazin_2_Linistire * vacanta - AerareB2.CL;
}
else
{
RecTimpLinistire = POMPA.Bazin_1_Linistire * vacanta - AerareB1.CL;
}
if (POMPA.LinistireEvacuare > RecTimpLinistire)
{
return (POMPA.LinistireEvacuare - RecTimpLinistire);
}
else
{
return 0;
}
}
else if ((Recirculare.CL == 0 && LinistireREC != 0) && (intarziere_Pin_A0 >= INTARZIERE_PLUTITOR))// numai etapa de evacuare a aparut in perioada linistirii recircularii
{
RecTimpLinistire = LinistireREC;
return LinistireREC;
}
else//nu se afla nici in linistire aerare, nici in linistire recirculare
{
RecTimpLinistire = 0;
}
return RecTimpLinistire;
}
/************************* FUNCTIE TRATARE EVENIMENTE ISR() PINI IN ISR() TIMER **************************/
inline void call_ISR_Timer (void)
{
// se pastreaza ordinea if-urilor pt functionare corecta:
// 0. prea gol
// 1. prea plin
// 2. evacuare
// 3. recirculare
// 4. aerare
int tmp = 0;
static byte TIMP_Evacuare_PreaPlin = 0;//este utilizata pentru evacuare prea plin BAZIN 2
static byte tmp_ALARMA = 0; // stocheaza temporar alarma aparuta inainte de alarma preaplin si
// este folosita strict pentru afisare
static bool stare_nivel_B2_Pin_A1 = 0; // stocheaza starea senzorului de nivel Bazin 2 cand apare alarma 4
// adica starea pinului A1 si este folosit pentru evitare evacuare
// dupa cum urmeaza - daca este false produce un nou ciclu daca senzorul
// de nivel Bazin 2 s-a cuplat si
/**** DOZARE FLOCULANT *****/
// aici se continua procesul de dozare floculant pana la finalizare
if (dozareFLOCULANT) Dozare_Floculant();
/**** PREA GOL BAZIN 1 SI 2 IN SERIE *****/
// cand apare evenimentul prea gol nu se executa functia
// si se opresc toate pompele
if ((PINC & (1 << PC3)) != 0 && alarma != 6)
{
if (alarma != 6) tmp_ALARMA = alarma;
pcf8575.digitalWrite( 4, HIGH); // opreste releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
pcf8575.digitalWrite( 3, HIGH); // opreste releul de pe pinul pcf8575 P03 care activeaza pompa de evacuare in bazin 2
pcf8575.digitalWrite( 2, HIGH); // opreste releul de pe pinul pcf8575 P02 care activeaza pompa de evacuare in bazin 1 sau 0
pcf8575.digitalWrite( 1, HIGH); // opreste releul de pe pinul pcf8575 P00 care activeaza pompa de aerare bazin 1
pcf8575.digitalWrite( 0, HIGH); // opreste releul de pe pinul pcf8575 P01 care activeaza pompa de aerare bazin 2
LCD.Alarma[5]<255 ? LCD.Alarma[5] += 1 : LCD.Alarma[5] = 255;
alarma = 6;// alarma prea gol
StareCiclu (4);// afisez starea prea gol BAZIN 1 si 2
return;
}
else if ((PINC & (1 << PC3)) == 0 && alarma == 6) alarma = tmp_ALARMA;
else if (alarma == 6) return;
/**** VACANTA *****/
// apare daca statia nu este utilizata mai mult de 48 de ore
// adica nu evacueaza in exterior
// aici calculez timpul pt vacanta
timp_Vacanta ++;// reprezinta timpul de la aparitia ultimului eveniment EVACUARE
if (alarma_Evacuare >= 0) alarma_Evacuare ++;//reprezinta timpul de la aparitia ultimei alarme provocata de blocarea senzorului de nivel din Bazin 1
if (timp_Vacanta == INTERVAL_VACANTA) // activez starea de vacanta daca timp
{ // de 48 de ore nu s-a produs evacuarea
vacanta = 2; // aceste variabile sunt resetate cand
} // apare evenimentul evacuare
/**** PREA PLIN BAZIN 2 ****/
/* 1) acest eveniment apare atunci cand plutitorul de nivel din BAZIN 1 nu este cuplat si
plutitorul de prea plin cupleaza, adica BAZIN 1 sa umplut si nu porneste evacuarea,
transferul de apa in BAZIN 2 facanduse hidraulic pana cand se ajunge la nivelul de prea plin
din BAZIN 2 fiind necesara evacuarea
2) cand plutitorului de nivel BAZIN 1 declanseaza procesul de evacuare dar pompa de evacuare
in exterior nu porneste sau este arsa si comunicarea intre bazine se realizeaza hidraulic
pana cand se atinge nivelul de prea plin din BAZIN 2
*/
if (((PINC & (1 << PC2)) != 0) && (TIMP_Evacuare_PreaPlin >= EVACUARE_PREA_PLIN ))//plutitorul a revenit la normal dupa evacuare preaplin
{
if (TIMP_Evacuare_PreaPlin <= POMPA.PornireEvacuare )// restabilesc starea dinainte de prea plin
{ // deoarece plutitorul a revenit la normal
// in timpul evacuarii prea plin
// daca sa depasit timpul POMPA.PornireEvacuare
// nu se mai restabileste starea deoarece
// s-a iesit din alarma si statia isi face ciclurile normale
(tmp_ALARMA > 2) ? alarma = tmp_ALARMA : alarma = 0;
// pornim pompele corespunzatoare etapei intrerupte de prea plin fara reluarea umplerii
if((Evacuare.SS == true ) && (Evacuare.CL == 0) && (Evacuare.OP != 0)) {/* pompa de evacuare ramane pornita*/}// ramane pornit releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
else pcf8575.digitalWrite( 4, HIGH); //opreste releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
if((Evacuare.SS == true ) && (Evacuare.CL == 0) && (Evacuare.OP == 0)) pcf8575.digitalWrite( 3, LOW);// reia umplerea
if ((Recirculare.SS == true ) && (LinistireREC == 0))
{
pcf8575.digitalWrite( 3, LOW); // porneste releul de pe pinul pcf8575 P03 care activeaza pompa de evacuare in bazin 2
pcf8575.digitalWrite( 2, LOW); // porneste releul de pe pinul pcf8575 P02 care activeaza pompa de evacuare in bazin 1
}
if ((AerareB1.SS == true) && (AerareB1.OP != 0) && (AerareB1.CL == POMPA.Bazin_1_Linistire)) pcf8575.digitalWrite( 1, LOW); // porneste releul de pe pinul pcf8575 P00 care activeaza pompa de aerare bazin 1
if ((AerareB2.SS == true) && (AerareB2.OP != 0) && (AerareB2.CL == POMPA.Bazin_2_Linistire)) pcf8575.digitalWrite( 0, LOW); // porneste releul de pe pinul pcf8575 P01 care activeaza pompa de aerare bazin 2
}
prea_plin_B2_Pin_A2 = false;
TIMP_Evacuare_PreaPlin = 0;
}
if (((PINC & (1 << PC2)) == 0) && (TIMP_Evacuare_PreaPlin == 0))
{
prea_plin_B2_Pin_A2 = true; // pin A2 este pentru prea plin din Bazin 2
// se evacueaza in exterior 50 litri
tmp_ALARMA = alarma;
pcf8575.digitalWrite( 4, LOW); // porneste releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
pcf8575.digitalWrite( 3, HIGH); // opreste releul de pe pinul pcf8575 P03 care activeaza pompa de evacuare in bazin 2
pcf8575.digitalWrite( 2, HIGH); // opreste releul de pe pinul pcf8575 P02 care activeaza pompa de evacuare in bazin 0
pcf8575.digitalWrite( 1, HIGH); // opreste releul de pe pinul pcf8575 P00 care activeaza pompa de aerare bazin 1
pcf8575.digitalWrite( 0, HIGH); // opreste releul de pe pinul pcf8575 P01 care activeaza pompa de aerare bazin 2
TIMP_Evacuare_PreaPlin++; alarma = 1;
LCD.Alarma[0]<255 ? LCD.Alarma[0] ++ : LCD.Alarma[0] = 255;// stochez aparitia alarmei
StareCiclu (4);// afisez starea prea plin BAZIN 2
return;
}
else if (prea_plin_B2_Pin_A2 && (TIMP_Evacuare_PreaPlin < EVACUARE_PREA_PLIN)) // evacueaza in exterior parte din prea plin
{
TIMP_Evacuare_PreaPlin++; alarma = 1;
StareCiclu (4);// afisez starea prea plin BAZIN 2 cat timp dureaza " EVACUARE_PREA_PLIN "
if (TIMP_Evacuare_PreaPlin < EVACUARE_PREA_PLIN) return;
}
else if (prea_plin_B2_Pin_A2 && (TIMP_Evacuare_PreaPlin >= EVACUARE_PREA_PLIN)) // a evacuat in exterior parte din plin
{ // dar senzorul de nivel pt prea plin
// nu s-a decuplat
if ((TIMP_Evacuare_PreaPlin < POMPA.PornireEvacuare)) // preventiv continua evacuarea pana se atinge timpul " PornireEvacuare "
{ // daca contactul este activ debitul este asa de mare incat pompa de
// nu face fata (complicat sa se intample deoarece pompa din put are 3 mc/h)
// sau senzorul a ramas lipit din cauza mizeriei
alarma = 2; // declansez alarma 2, adica pompa de evacuare este arsa sau
// plutitorul prea-plin blocat, va functiona hidraulic
// pompa de evacuare se opreste in cazul plutitorului blocat cand
// este depasit timpul de evacuare intr-un ciclu normal si
// revine la ciclul normal cand se deblocheaza
if (TIMP_Evacuare_PreaPlin == EVACUARE_PREA_PLIN) LCD.Alarma[1]<255 ? LCD.Alarma[1] ++ : LCD.Alarma[1] = 255;// stochez aparitia alarmei
TIMP_Evacuare_PreaPlin++;
StareCiclu (4);// afisez starea prea-plin BAZIN 2 pana cand se termina timpul " PornireEvacuare "
return;
}
else if ((TIMP_Evacuare_PreaPlin == POMPA.PornireEvacuare ))// s-a atins timpul maxim de evacuare
{
pcf8575.digitalWrite( 4, HIGH); //opreste releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
TIMP_Evacuare_PreaPlin++;// mai adun o unitate pt ca sa se depaseasca " PornireEvacuare "
// restabilesc starea dinainte de prea plin deoarece plutitorul plutitorul nu revine la normal
// si a fost consumat timpul de pornire evacuare insemna ca pompa de evacuare s-a ars sau plutitorul a ramas cuplat
(tmp_ALARMA > 2) ? alarma = tmp_ALARMA : alarma = 0;
// pornim pompele corespunzatoare etapei intrerupte de prea plin
if(Evacuare.SS == true ) {Evacuare.OP = 0; Evacuare.CL = 0;}// sare peste etapa de evacuare daca
// daca evenimentul de prea plin a
// aparut in timpul evacuarii
//if((Evacuare.SS == true ) && (Evacuare.CL == 0) && (Evacuare.OP != 0)) pcf8575.digitalWrite( 4, LOW);// else pcf8575.digitalWrite( 4, HIGH); //opreste / porneste releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
if ((Recirculare.SS == true ) && (LinistireREC == 0))
{
pcf8575.digitalWrite( 3, LOW); // porneste releul de pe pinul pcf8575 P03 care activeaza pompa de evacuare in bazin 2
pcf8575.digitalWrite( 2, LOW); // porneste releul de pe pinul pcf8575 P02 care activeaza pompa de evacuare in bazin 0
}
if ((AerareB1.SS == true) && (AerareB1.OP != 0) && (AerareB1.CL == POMPA.Bazin_1_Linistire)) pcf8575.digitalWrite( 1, LOW); // porneste releul de pe pinul pcf8575 P00 care activeaza pompa de aerare bazin 1
if ((AerareB2.SS == true) && (AerareB2.OP != 0) && (AerareB2.CL == POMPA.Bazin_2_Linistire)) pcf8575.digitalWrite( 0, LOW); // porneste releul de pe pinul pcf8575 P01 care activeaza pompa de aerare bazin 2
}
}
// end Prea Plin
/**** EVACUARE ****/
if (LCD.Alarma[4] && prea_plin_B2_Pin_A2) // pt. alarma 5 se evita evacuare continu
{ // deoarece pompa de evacuare este sigur arsa sau
goto Evita_Evacuarea; // senzorul de prea plin a ramas lipit in contact
}
else if (alarma_Evacuare >= 0 && alarma_Evacuare < INTERVAL_VACANTA / 2) // evita Evacuarea daca senzorul de nivel Bazin 1 a ramas cuplat
{ // si umplerea Bazin 2 s-a terminat - adica a aparut alarma 4
// pentru a se evita evacuarea repetitiva
// alarma_Evacuare este setata 0 cand apare alarma 4
if ((PINC & (1 << PC0)) != 0) alarma_Evacuare = -1;// evacuarea revine la normal daca senzorul de nivel Bazin 1 se decupleaza
else if (!stare_nivel_B2_Pin_A1 && (PINC & (1 << PC1)) == 0) alarma_Evacuare = -1;// se executa evacuarea daca senzorul de nivel
// Bazin 2 s-a cuplat prin echilibrare hidraulica
// si senzorul de nivel Bazin 1 este cuplat in continuare
else goto Evita_Evacuarea;
}
else if ((alarma_Evacuare == INTERVAL_VACANTA / 2))// forteaza evacuarea odata la 24 ore daca a aparut alarma 4
{ // cu conditia ca prea plinul din Bazin 2 sa nu fie cuplat
// altfel functioneaza hidraulic
// aerarea si recircularea functioneaza normal
prea_plin_B2_Pin_A2 ? alarma_Evacuare = 0 : alarma_Evacuare = -1;
}
/******* Eliminare semnale false generate de plutitorul de nivel Bazin 1 - Pin A0 *********/
//produce intarzierea pt. eliminarea semnalelor false pe senzorul de nivel bazin 1
if (((PINC & (1 << PC0)) == 0) && (intarziere_Pin_A0 >= 0) && (intarziere_Pin_A0 < INTARZIERE_PLUTITOR))// daca plutitorul din Bazin 1 este cuplat "INTARZIERE_PLUTITOR secunde"
{ // se executa evacuarea
nivel_B1_Pin_A0 = true;
Evacuare.SS = true;
intarziere_Pin_A0++;// se produce o intarziere de "INTARZIERE_PLUTITOR secunde" necesara pentru ca plutitorul sa fie inundat
goto Evita_Evacuarea;// evita codul de evacuare
}
else if (((PINC & (1 << PC0)) != 0) && (intarziere_Pin_A0 < INTARZIERE_PLUTITOR))//daca plutitorul din Bazin 1 nu este cuplat "INTARZIERE_PLUTITOR secunde"
{ // nu se executa evacuarea
nivel_B1_Pin_A0 = false;
Evacuare.SS = false;
intarziere_Pin_A0 = 0;
goto Evita_Evacuarea;// evita codul de evacuare
}
/****************************************************************************/
/* -------aici incepe procesul de linistire, evacuare in exterior si umplere Bazin 2--------------------------------------*/
if (nivel_B1_Pin_A0 && Evacuare.SS )//eveniment pin A0 - Bazinul 1 sa umplut, opreste aerarea si
{ //recircularea pornind evacuarea,
//daca pompa de evacuare in BAZIN 1 sau BAZIN 2 s-a ars,
//functioneza ca vase comunicante
// Verifica pozitia plutitorului de nivel din Bazin 2
if ((PINC & (1 << PC1)) == 0)
{nivel_B2_Pin_A1 = true;}
else
{nivel_B2_Pin_A1 = false; }
StareCiclu (1);// afisez starea pentru evacuare cand nu avem alarme in evacuare
if (Evacuare.SS == true && Evacuare.CL == POMPA.LinistireEvacuare)// verifica daca evacuarea a aparut in timpul
{ //linistirii aerare sau recirculare
// stabileste timpul de linistire in functie de starea in care se afla statia
// adica daca se afla in perioada de linistire aerare sau recirculare
// timpul de linistire evacuare este doar diferenta de timp
tmp = Recuperare_Timp_Linistire();
if (Evacuare.CL >= tmp && tmp != 0)
{
Evacuare.CL = tmp + 1;
}
else if (Evacuare.CL < tmp && tmp != 0)
{
Evacuare.CL = 1;
}
AerareB1.SS = false; AerareB2.SS = false; Recirculare.SS = false; Evacuare.CL--;
//oprim toate pompele
pcf8575.digitalWrite( 4, HIGH); // opreste releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
pcf8575.digitalWrite( 3, HIGH); // opreste releul de pe pinul pcf8575 P03 care activeaza pompa de evacuare in bazin 2
pcf8575.digitalWrite( 2, HIGH); // opreste releul de pe pinul pcf8575 P02 care activeaza pompa de evacuare in bazin 0
pcf8575.digitalWrite( 1, HIGH); // opreste releul de pe pinul pcf8575 P00 care activeaza pompa de aerare bazin 1
pcf8575.digitalWrite( 0, HIGH); // opreste releul de pe pinul pcf8575 P01 care activeaza pompa de aerare bazin 2
timp_Vacanta = 0; vacanta = 1; // resetez starea de vacanta
pcf8575.digitalWrite( 5, HIGH); // schimb pozitia electrovanei cu trei cai penru recirculare normala
return;
}
else if ((Evacuare.SS == true) && (Evacuare.CL <= POMPA.LinistireEvacuare))// incepe perioada de linistire
{
/*---------------- linistire ----------------------------------------------------------------------------------*/
// aici continua procesul de linistire
if ( Evacuare.CL != 0 ) // releul pe pinul pcf8575 P04 este Normal Close pt. perioada CL
{
Evacuare.CL--;
if ((Evacuare.CL == 0) && (Evacuare.OP == POMPA.PornireEvacuare) && nivel_B1_Pin_A0 && !nivel_B2_Pin_A1)
{
Evacuare.OP = 0;// sare peste etapa de evacuare in exterior daca plutitorul din Bazin 2 nu este la nivel
return; // prin aceasta se realizeaza echilibrarea volumetrica a statiei de epurare
}
return;
}
//------------------ evacuare -----------------------------------------------------------------------------------*/
//aici incepe evauarea in exterior
if((Evacuare.CL == 0) && (Evacuare.OP == POMPA.PornireEvacuare) && nivel_B2_Pin_A1)// sa terminat linistirea si incepe evacuarea
{
pcf8575.digitalWrite( 4, LOW);// porneste releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
Evacuare.OP--;
return;
}
else if ((Evacuare.OP != 0) && nivel_B2_Pin_A1 )// daca apa de evacuat este mai sus de plutiorul de nivel din BAZIN 2, adica in timpul
{ // linistirii pt. evacuare sa depasit prea plinul hidraulic din BAZIN 1, elimina
Evacuare.OP--; // surplusul si revine la PornireEvacuare in cadrul ISR pin A1 cand se modifica starea plutiorului
surplus_Evacuare = true;
if (Evacuare.OP == 0) // pompa evacuare in exterior defecta sau senzor de nivel BAZIN 2 blocat ON(cuplat)
{ // fara ca pre plinul sa fie atins
alarma = 3; // declansez ALARMA - nu s-a decuplat senzorul de nivel in Bazin 2
LCD.Alarma[2]<255 ? LCD.Alarma[2] += 1 : LCD.Alarma[2] = 255;
//StareCiclu (4); // afisez starea cand s-a declansat alarma
//Initializare_Ciclu();
return;
}
}
else if ((Evacuare.OP != 0) && !nivel_B2_Pin_A1)// a fost eliminat surplusul de apa si evacueaza cantitatea de apa epurata
{
Evacuare.OP--;
if (surplus_Evacuare) // daca exista surplus de apa aparut in timpul linistirii
{ // reinitializeaza timpul de evacuare dupa eliminarea
Evacuare.OP = POMPA.PornireEvacuare; // surplusului pentru a se pastra timpii de epurare
surplus_Evacuare = false;
}
return;
}
//-------------- umplere bazin 2 ---------------------------------------------------------------------------------------*/
//aici incepe umplerea bazinului 2
if (Evacuare.CL == 0 && Evacuare.OP == 0 )// s-a epuizat linistirea si evacuarea
{
//Serial.println(PornireEvacuareInBazin2);
if (PornireEvacuareInBazin2 == POMPA.PornireEvacuare + INTARZIERE_PLUTITOR)// se umple Bazinul 2 dupa ce a fost evacuat in exterior
{ // daca senzorul de nivel din Bazinul 2-pin A1 nu este decuplat
pcf8575.digitalWrite( 4, HIGH); // opreste releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
if (!prea_plin_B2_Pin_A2 ) // porneste pompa de umplere daca preaplinul nu este cuplat,
{ // altfel transferul se realizeaza hidraulic
pcf8575.digitalWrite( 3, LOW); // porneste releul de pe pinul pcf8575 P03 care activeaza pompa de evacuare in bazin 2
//PornireEvacuareInBazin2--;
}
PornireEvacuareInBazin2--;
return;
}
else if (PornireEvacuareInBazin2 >= 0 && PornireEvacuareInBazin2 <= POMPA.PornireEvacuare + INTARZIERE_PLUTITOR) //umple bazinul 2 dupa evacuare
{ // pompa are 100 litri/min si are
// nevoie de 180 secunde de a evacua
// 300 litri in bazinul 2
if (!nivel_B2_Pin_A1 && PornireEvacuareInBazin2 != 0 && !prea_plin_B2_Pin_A2)
{
PornireEvacuareInBazin2-- ; // continua umplerea bazin 2
return;
}
else if (PornireEvacuareInBazin2 == 0 && !prea_plin_B2_Pin_A2)
{
if (((PINC & (1 << PC0)) == 0))// senzorul de nivel bazin 1 a ramas
{ // cuplat-senzor nivel defect sau murdar
// sau pompa de umplere defecta
// se adauga floculant doar in Bazin 2
alarma = 4; // declansez ALARMA - nu s-a decuplat senzorul de nivel in bazin 1
stare_nivel_B2_Pin_A1 = nivel_B2_Pin_A1;
alarma_Evacuare++ ;
LCD.Alarma[3]<255 ? LCD.Alarma[3] += 1 : LCD.Alarma[3] = 255;
StareCiclu (4); // afisez starea cand s-a declansat alarma
Initializare_Ciclu();
Dozare_Floculant (2);// aici incepe introducerea floculantului doar in bazinul 2
// in bazinul 1 nu se introduce floculant deoarece pompa de
// umplere bazin 2 sar putea sa fie arsa si cantitatea de
// floculant dozata la suprafata in bazinul 1 sa ajunga
// hidraulic in bazin 2
return;
}
else if ((PINC & (1 << PC0)) != 0)// umplerea sa facut cu succes
{ // si se adauga floculant in ambele bazine
Initializare_Ciclu();
Dozare_Floculant (3);// aici incepe introducerea floculantului in bazin 1 si bazin 2
return;
}
}
else if (((PINC & (1 << PC0)) == 0 && nivel_B2_Pin_A1) && !prea_plin_B2_Pin_A2)// forteaza umplerea daca senzorul de nivel din
{ // Bazin 2 nu a fost decuplat in urma evacuarii
PornireEvacuareInBazin2-- ;
return;
}
else if (nivel_B2_Pin_A1 && (PornireEvacuareInBazin2 != 0) && !prea_plin_B2_Pin_A2)// senzorul de nivel Bazin 2 s-a cuplat
{ // si nu s-a epuizat timpul de umplere
// continua umplerea 15 secunde
if (intarziere_Pin_A1 >= 0 && intarziere_Pin_A1 < INTARZIERE_PLUTITOR) // pompa de evacuare in Bazin 2 mai functioneaza 15 secunde
{ // aceasta situatie apare in general cand bazinul 2 nu a
// functionat plin si se produce o echilibrare de nivel
intarziere_Pin_A1++; // numara intarzierea de 15 secunde
PornireEvacuareInBazin2 = INTARZIERE_PLUTITOR - intarziere_Pin_A1;
return;
}
}
else if ((PINC & (1 << PC0)) == 0 && PornireEvacuareInBazin2 == 0 ) // s-a terminat umplerea BAZIN 2 si senzorul de nivel nu este cuplat
{ // senzor nivel defect sau murdar si nu cupleaza sau pompa de umplere defecta
// se adauga floculant doar in Bazin 2
alarma = 4; // declansez ALARMA - nu s-a decuplat senzorul de nivel in bazin 1
stare_nivel_B2_Pin_A1 = nivel_B2_Pin_A1;
alarma_Evacuare++ ;
LCD.Alarma[3]<255 ? LCD.Alarma[3] += 1 : LCD.Alarma[3] = 255;
//StareCiclu (4); // afisez starea cand s-a declansat alarma
Initializare_Ciclu();
Dozare_Floculant (2);// aici incepe introducerea floculantului doar in bazinul 2
// in bazinul 1 nu se introduce floculant deoarece pompa de
// umplere bazin 2 sar putea sa fie arsa si cantitatea de
// floculant dozata la suprafata in bazinul 1 sa ajunga
// hidraulic in bazin 2
return;
}
else if (((PINC & (1 << PC0)) == 0 || nivel_B2_Pin_A1) && prea_plin_B2_Pin_A2)// apare cand senzorul de nivel Bazin 2 nu s-a decuplat dupa evacuare
{ // deoarece verificarea senzorului se face o singura data
// la inceputul umplerii, fapt care arata ca umplerea se realizeaza
// intre nivel bazin 2 si prea plin, adica bazinul 2 a ramas plin
// si prin umplere sa atins nivelul de preaplin si
// " PornireEvacuareInBazin2 " nu a ajuns la 0
// nu se adauga floculant deoarece pompa deevacuare in exterior
// s-ar putea sa fie arsa si cantitatea de floculant dozata
// la suprafata in bazinul 2 sa ajunga hidraulic in bazin 2
alarma = 5; // declansez ALARMA - pompa de evacuare in exterior sigur este arsa
LCD.Alarma[4]<255 ? LCD.Alarma[4] += 1 : LCD.Alarma[4] = 255;
//StareCiclu (4); // afisez starea cand s-a declansat alarma
Initializare_Ciclu();
return;
}
}
}
}
return;
}// end Evacuare
Evita_Evacuarea: // saltul la aceasta eticheta pastreaza procesele
// in functiune pana se realizeaza intarzierea pe
// pinul A0 pentru eliminarea semnalelor false
/**** RECIRCULARE ****/
if (Recirculare.SS == true )//&& !nivel_B1_Pin_A0)
{
ORA_Recirculare++;
//-------------------------------------------------------------------------------
// stabilesc setari pt recirculare vacanta - are loc odata la 48 ore
if (timp_Vacanta >= INTERVAL_VACANTA && timp_Vacanta <= INTERVAL_VACANTA + 10)
{
if (timp_Vacanta == INTERVAL_VACANTA)
{
if (LinistireREC == 0)//evenimentul apare in timpul recircularii
{
//resetez recircularea
LinistireREC = POMPA.LinistireEvacuare;
Recirculare.OP = POMPA.PornireRecirculare;
}
pcf8575.digitalWrite( 3, HIGH); // opreste releul de pe pinul pcf8575 P03 care activeaza pompa de evacuare in bazin 2
pcf8575.digitalWrite( 2, HIGH); // opreste releul de pe pinul pcf8575 P02 care activeaza pompa de evacuare in bazin 1
pcf8575.digitalWrite( 5, LOW); // schimb pozitia electrovanei cu trei căi penru improspatare apa Bazin 0
}
if (timp_Vacanta == INTERVAL_VACANTA +10) // astept 10 secunde sa se comute vana cu trei căi
{
timp_Vacanta = 0;
Recirculare.CL = 0; ORA_Recirculare = 0; // fortez recircularea pentru improspatare apa Bazin 0
}
//else return;
}
//--------------------------------------------------------------------------------
//recirculare normala
if ((ORA_Recirculare == (NR_SEC_ORA * vacanta)) && (Recirculare.CL != 0)) {Recirculare.CL--; ORA_Recirculare = 0;}
if (Recirculare.CL == 0)
{
StareCiclu (2);// afisez starea pentru Recirculare
if (LinistireREC == POMPA.LinistireEvacuare)
{
// stabilesc timpul de linistire in functie de starea in care se afla statia
// adica daca se afla in perioada de linistire aerare sau recirculare
// timpul de linistire evacuare este doar diferenta de timp
tmp = Recuperare_Timp_Linistire();
if (LinistireREC >= tmp && tmp != 0)
{
LinistireREC = tmp + 1;
}
else if (LinistireREC < tmp && tmp != 0)
{
LinistireREC = 1;
}
AerareB1.OP = POMPA.Bazin_1_Aerare; AerareB2.OP = POMPA.Bazin_2_Aerare;
AerareB1.SS = false; AerareB2.SS = false; LinistireREC--;
//oprim toate pompele
pcf8575.digitalWrite( 4, HIGH); // opreste releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
pcf8575.digitalWrite( 3, HIGH); // opreste releul de pe pinul pcf8575 P03 care activeaza pompa de evacuare in bazin 2
pcf8575.digitalWrite( 2, HIGH); // opreste releul de pe pinul pcf8575 P02 care activeaza pompa de evacuare in bazin 0
pcf8575.digitalWrite( 1, HIGH); // opreste releul de pe pinul pcf8575 P00 care activeaza pompa de aerare bazin 1
pcf8575.digitalWrite( 0, HIGH); // opreste releul de pe pinul pcf8575 P01 care activeaza pompa de aerare bazin 2
return;
}
if (LinistireREC != 0)
{
LinistireREC--;
//StareCiclu (2);// afisez starea pentru Recirculare
return;
}
if (LinistireREC == 0 && Recirculare.OP == POMPA.PornireRecirculare)
{
pcf8575.digitalWrite( 3, LOW); // porneste releul de pe pinul pcf8575 P03 care activeaza pompa de evacuare in bazin 2
pcf8575.digitalWrite( 2, LOW); // porneste releul de pe pinul pcf8575 P02 care activeaza pompa de evacuare in bazin 0
Recirculare.OP--;
//StareCiclu (2);// afisez starea pentru Recirculare
return;
}
else if ((LinistireREC == 0) && (Recirculare.OP != 0))
{
Recirculare.OP--;
//StareCiclu (2);// afisez starea pentru Recirculare
return;
}
else if ((LinistireREC == 0) && (Recirculare.OP == 0)) {Initializare_Ciclu();} // s-a terminat recircularea
}
}// end Recirculare
/**** AERARE ****/
if (AerareB1.SS == true && AerareB2.SS == true)//aerarea se face in pararel la timpi diferiti pt fiecare bazin
{
if (AerareB1.OP == POMPA.Bazin_1_Aerare) {AerareB1.CL *= vacanta;}
if (AerareB2.OP == POMPA.Bazin_2_Aerare) {AerareB2.CL *= vacanta;}
StareCiclu (3);// afisez starea pentru Aerare
//aerare Bazin 1
if (AerareB1.OP == POMPA.Bazin_1_Aerare)
{
//oprim pompele de recirculare si evacuare
pcf8575.digitalWrite( 4, HIGH); // opreste releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
pcf8575.digitalWrite( 3, HIGH); // opreste releul de pe pinul pcf8575 P03 care activeaza pompa de evacuare in bazin 2
pcf8575.digitalWrite( 2, HIGH); // opreste releul de pe pinul pcf8575 P02 care activeaza pompa de evacuare in bazin 0
AerareB1.OP--;
pcf8575.digitalWrite( 1, LOW); // porneste releul de pe pinul pcf8575 P00 care activeaza pompa de aerare bazin 1
//AerareB1.CL = AerareB1.CL * vacanta;
}
else if (AerareB1.OP != 0) AerareB1.OP--;
else if ((AerareB1.OP == 0) && (AerareB1.CL == POMPA.Bazin_1_Linistire * vacanta))
{
pcf8575.digitalWrite( 1, HIGH); // opresc releul de pe pinul pcf8575 P00 care activeaza pompa de aerare bazin 1
AerareB1.CL--;
}
else if ((AerareB1.OP == 0) && (AerareB1.CL != 0)) AerareB1.CL--;
else if ((AerareB1.OP == 0) && (AerareB1.CL == 0))
{
AerareB1.CL = POMPA.Bazin_1_Linistire * vacanta; AerareB1.OP = POMPA.Bazin_1_Aerare;
}
// aerare Bazin 2
if (AerareB2.OP == POMPA.Bazin_2_Aerare)
{
//oprim pompele de recirculare si evacuare
pcf8575.digitalWrite( 4, HIGH); // opreste releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
pcf8575.digitalWrite( 3, HIGH); // opreste releul de pe pinul pcf8575 P03 care activeaza pompa de evacuare in bazin 2
pcf8575.digitalWrite( 2, HIGH); // opreste releul de pe pinul pcf8575 P02 care activeaza pompa de evacuare in bazin 0
AerareB2.OP--;
pcf8575.digitalWrite( 0, LOW); // porneste releul de pe pinul pcf8575 P00 care activeaza pompa de aerare bazin 1
//AerareB2.CL = AerareB2.CL * vacanta;
}
else if (AerareB2.OP != 0) AerareB2.OP--;
else if ((AerareB2.OP == 0) && (AerareB2.CL == POMPA.Bazin_2_Linistire * vacanta))
{
pcf8575.digitalWrite( 0, HIGH); // opresc releul de pe pinul pcf8575 P00 care activeaza pompa de aerare bazin 2
AerareB2.CL--;
}
else if ((AerareB2.OP == 0) && (AerareB2.CL != 0)) AerareB2.CL--;
else if ((AerareB2.OP == 0) && (AerareB2.CL == 0))
{
AerareB2.CL = POMPA.Bazin_2_Linistire * vacanta; AerareB2.OP = POMPA.Bazin_2_Aerare;
}
}// end Aerare
}// end call_ISR_Timer
/******************** FUNCTIE RESETARE SOFTWARE PLACA *******************/
// resetare arduino.
// Trebuie scrisa inainte functiei loop().
// resetFunc() este chemata cand este nevoie.
inline void(* resetFunc) (void) = 0;
/************************************************************************/
/************************ INTRERUPERE ISR PENTRU TIMP ***************************/
// ISR(TIMER1_OVF_vect) //Intrerupere TIMER1
// {
// /************ INTRERUPERE/EVENIMENT CARE MASOARA TIMPUL IN SECUDE **********************************/
// // Acesta intrerupere este folosita pentru functii de timp prin intreruperea functiei " loop () "
// // Se poate utiliza pentru ceas, semnale pe pini, etc. care nu au nevoie de timp de precizie la microsecunda
// //ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { UNSIGNED Long temp = Durata} din lib. #include <util/atomic.h>
// // pentru a nu se transmite un rezultat eronat in timpul intreruperii
// flag_Timer1 = true;
// }// end ISR TIMER1
/***********************************************************************************/
/************************* INTRERUPERE ISR PENTRU BUTOANE **************************/
//ATENTIE !!! pini D0 si D1 nu se utilizeaza sunt pentru transmisie seriala.
//Pentru pinii D2 si D3 se foloseste attachInterrupt() , ISR()-urile se folosesc doar pentru
//pini pe care nu se poate folosii attachInterrupt()
// ISR (PCINT0_vect)//Portul B - handle pin change interrupt for pcf8575 P00 to D13 here
// {
// nu este utilizat
// } // end of ISR PCINT0_vect
// ISR (PCINT1_vect)//Portul C - handle pin change interrupt for A0 to A5 here
// {
// nu este utilizat
// } // end of ISR PCINT1_vect
// ISR (PCINT2_vect )//Portul D - handle pin change interrupt for D4, D5 si D6 ceilalti nu se folosesc in acest caz
// {
// // //ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
// // {
// // if (((PIND & (1 << PD4)) == 0)) // butonul pe pin D4 este apasat
// // {
// // }
// // if ((PIND & (1 << PD5)) == 0 ) // butonul pe pin D5 este apasat
// // {
// // }
// // if ((PIND & (1 << PD6)) == 0 ) // butonul pe pin D6 este apasat
// // {
// // // Serial.println("DOWN");
// // start = millis();
// // }
// // //while((PIND & (1 << PD6)) != 0 ) { secundeDOWN = millis() - start;}
// // if ((PIND & (1 << PD6)) != 0 )
// // {
// // // Serial.println("UP");
// // secundeDOWN = millis() - start;// butonul pe pin D6 este apasat
// // PCIFR |= bit (PCIF2); // sterge toate intreruperile remanente;
// // }
// // // Serial.print("sec DOWN --- "); Serial.println(secundeDOWN);
// // // Serial.print("millis() --- "); Serial.println(millis());
// // // Serial.print("start --- "); Serial.println(start);
// // }
// } // end of ISR PCINT2_vect
byte numDevices = 0;
/************************************************************************************/
void setup()
{
Serial.begin(9600);//initialize the serial
// transfer date wireles HC12
HC12_Transfer_TX_LCD.begin(details(LCD), &Serial); // transmitere catre slave date wireles prin portul fizic UART
HC12_Transfer_TX_POMPA_Set.begin(details(LCD), &Serial); // transmitere catre slave date wireles prin portul fizic UART
HC12_Transfer_RX_POMPA_Set.begin(details(POMPA_Set), &Serial); // receptionare de la slave date wireles prin portul fizic UART
//senzori temperatura
//rezolutie 9, 10, 11 sau 12 biți, care corespund la 0,5 °C, 0,25 °C, 0,125 °C și, respectiv, 0,0625 °C.
temperatureSensors.begin(NonBlockingDallas::resolution_12, TIME_INTERVAL);// rezolutie senzor = 12 - adica 0.0625°C precizie
//Callbacks temperatura
temperatureSensors.onTemperatureChange(handleTemperatureChange);
//Call the following function whenever you want to request a new temperature reading without waiting for TIME_INTERVAL to elapse
temperatureSensors.requestTemperature();
lcd.begin(20, 4); //initialize the lcd
pcf8575.begin();// initialize the pcf8575 si folosesc numerotarea nesecventiala
//initializare pini pcf8575
pcf8575.pinMode(P0, OUTPUT);//P00 pinii marcati pe PCB
pcf8575.pinMode(P1, OUTPUT);//P01
pcf8575.pinMode(P2, OUTPUT);//P02
pcf8575.pinMode(P3, OUTPUT);//P03
pcf8575.pinMode(P4, OUTPUT);//P04
pcf8575.pinMode(P5, OUTPUT);//P05
pcf8575.pinMode(P6, OUTPUT);//P06
pcf8575.pinMode(P7, OUTPUT);//P07
pcf8575.pinMode(P8, OUTPUT);//P10
//initializare stare pini pcf8575
pcf8575.digitalWrite( 8, HIGH); // opreste alarma
pcf8575.digitalWrite( 7, HIGH); // opreste releul de pe pinul pcf8575 P06 care activeaza pompa peristaltica bazin 1
pcf8575.digitalWrite( 6, HIGH); // opreste releul de pe pinul pcf8575 P06 care activeaza pompa peristaltica bazin 1
pcf8575.digitalWrite( 5, HIGH); // opreste releul de pe pinul pcf8575 P05 care activeaza electrovana cu 3 cai
pcf8575.digitalWrite( 4, HIGH); // opreste releul de pe pinul pcf8575 P04 care activeaza pompa de evacuare in exterior
pcf8575.digitalWrite( 3, HIGH); // opreste releul de pe pinul pcf8575 P03 care activeaza pompa de evacuare in bazin 2
pcf8575.digitalWrite( 2, HIGH); // opreste releul de pe pinul pcf8575 P02 care activeaza pompa de evacuare in bazin 0
pcf8575.digitalWrite( 1, HIGH); // opreste releul de pe pinul pcf8575 P00 care activeaza pompa de aerare bazin 1
pcf8575.digitalWrite( 0, HIGH); // opreste releul de pe pinul pcf8575 P01 care activeaza pompa de aerare bazin 2
// initializare pin buzzer
// pinMode(PIN_BUZZER, OUTPUT);// se foloseste pentru dispozitivul SLAVE
// initializare pini senzori de nivel (plutitori cu contacte REED montati in bazine)
pinMode(A0, INPUT_PULLUP);//senzor bazin 1
pinMode(A1, INPUT_PULLUP);//senzor bazin 2
pinMode(A2, INPUT_PULLUP);//preaplin bazin 2
pinMode(A3, INPUT_PULLUP);//prea gol bazin 1 si 2 - in serie
Scrie_Citeste_EEPROM(0);// aici trebuie sa fie apelata inainte de functia
// Initializare_Ciclu() pt a fi stocate valorile
// de initializare a variabilelor la scrierea
// programului pe Mcu
Initializare_Ciclu();
/******************************* Pin change interrupt BUTOANE SETARI ********************************************/
// exemplu intrerupri alti pini decat D2 si D3 pentru PORTD, se procedeaza la fel pentru PORTB si PORTC
// sunt trei porturi PORTB, PORTC, PORTD - a se vedea diagrama controlerului si tabelul porturilor;
// DDRB, DDRC, DDRD seteaza I/O pe fiecare pin din port echivalent cu pinMode() mai rapid dar fara PULLUP;
// DDRD |= ~_BV(PD2) | ~_BV(PD4); Pini D2 si D4 setati input;
// DDRD &= (1 << PD2) & (1 << PD4); Pini D2 si D4 setati output;
// PORTD |= (1 << PD2) | (1 << PD4); Pini D2 si D4 setati PULLUP dupa ce sunt setati input ca mai sus;
// pentru fiecare port exista cite o intrerupere PCMSK0, PCMSK1, PCMSK2 - PCINTxx este nr. pinului
// in vectorul de intrerupere - vezi fisa de date a controlerului
// PCMSK2 |= bit (PCINT22); // want pin D6 - stabileste intrerupere pe pinul D6;
// PCMSK2 |= bit (PCINT21); // want pin D5 - stabileste intrerupere pe pinul D5;
// .......................
// PCMSK2 |= bit (PCINT17); // want pin D1 - stabileste intrerupere pe pinul D1;
// PCMSK2 |= bit (PCINT16); // want pin D0 - stabileste intrerupere pe pinul D0;
// sau se mai pot activa toti odata. Bitul cel mai scazut este D0 si se procedeaza pentru toate porturile la fel;
// PCMSK2 |= 0b11111111; in binar
/******************** Initializare pini care activeaza intreruperea pe PORTD ****************************/
//pinii pt. butoane sunt D4, D5 si D6 si sunt initializati mai sus cu pinMode
// PCMSK2 |= 0b01110000; // seteaza D4, D5 si D6 sa activeze ISR() ;
// PCIFR |= bit (PCIF2); // sterge toate intreruperile remanente;
// PCICR |= bit (PCIE2); // activeaza intreruperile;
// initializare pini butoane
pinMode(PIN_BUTON_SETUP, INPUT_PULLUP);
pinMode(PIN_BUTON_TIMP_MINUS, INPUT_PULLUP);
pinMode(PIN_BUTON_TIMP_PLUS, INPUT_PULLUP);
/********************* Initializez TIMER 1 sa cheme ISR la o secunda *************************************/
// calculul si stabilirea registrilor sa facut cu RTM TimerCalc
// TCCR1B = 0x10; // 0001 0000, Disable Timer
// TCCR1A = 0xA2; // 1010 0010
// ICR1 = 31250; // valuare TOP
// TCNT1 = 0x0; // porneste de la 0
// TCCR1B |= 4; // Prescale=256, Enable Timer in binar 0000 0100
// // sau (1<<CS10)|(0 << CS11)|(0 << CS12) prin scriere registrii
// // Set Overflow Interrupt Mask Bit
// TIMSK1 |= 1; // ISR Prototype --> ISR(TIMER1_OVF_vect){}
/*************************************************************************************************/
}// end setup()
void loop()
{
static unsigned long masuarare_TIMP = millis();
if ( millis() - masuarare_TIMP >= 1000 )
{
masuarare_TIMP = millis();
call_ISR_Timer ();
// if (durata > 604800)// se reseteaza controlerul la fiecare 7 de zile daca nu ajung sa elimin
// { // alarmele cu speranta ca nu sunt arse pompele si sunt doar murdari senzorii
// Initializare_Ciclu();
// resetFunc() ;
// }
//tx_HC12 (1); // transmitere date LCD
}
else
{
Defilare_Meniu_Setup(); // intra in meniul SETUP cand buttonSETUP este apasata
rx_HC12 (); // receptionare date POMPA_Set
}
temperatureSensors.update();
Info_Help();
}//end loop()
//////////////////////// FUNCTII INTRODUSE IN void loop() //////////////////////////////////////////
/************************ STOCARE SETARI IN MEMORIA EEPROM ************************/
// Acesta functie citeste sau scrie valorile variabilelor globale necesare stabilirii
// timpilor utilizati intr-un ciclu de epurare
// Aceasta functie este folosita in meniul Setup pentru stocarea modificarii variabilelor,
// in functia Initializare_Ciclu () si in functia setup()
// o scriere dureaza aproximativ 3.3 ms/octet la care se aduna si durata codului functiei
// din cate am citit EEPROM este sters odata cu instalarea unui program si toti bitii sunt 0xFF adica 1111 1111 sau 255 dec
// acest fapt este de verificat fizic
void Scrie_Citeste_EEPROM (byte flag)
{
// flag = 0 functia este folosita in functia setup()
// 1 functia este folosita in functia Initializare_Ciclu ()
// 2 functia este folosita in meniul Setup si salveaza varibila
// pentru a nu se afecta ciclul in care se afla statia
// 3 se va citi continutul memoriei
// 4 scrie primul octe 0xFF adica 1111 1111 sau 255 dec
// octetul de la adresa 0 are = 0xFF adica 1111 1111 sau 255 dec, daca programul este incarcat in Mcu prima oara
// indicativul, adica valoarea = 0x80 adica 1000 0000 sau 128 dec, daca memoria contine stocate valori nemodificate
// stocata = 0x40 adica 0100 0000 sau 64 dec, daca daca memoria a fost modificata in meniul Setup
// acest octet este necesar mai ales la resetarea Mcu pt initializarea variabilelor prin pastrarea setarilor
// cu acesta functie se stocheaza primul octet si " struct POMPE " adica variabila POMPA
// initializarea de tip bloc se realizeaza in functia setup() si in functia Initializare_Ciclu ()
// pentru AERARE si RECIRCULARE initializarea se face individual la fiecare final de ciclu
// astfel incat sa nu se afecteze buna functionare a statiei in timpul setarii in meniul Setup
// daca parametrii introdusi sunt gresiti aceasta functie genereaza erori necontrolabile
//ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
//TIMSK1 &= ~1; //opresc intrerupere Timer 1 pentru a ma asigura ca
//nu apare in timp ce scriu si citesc EEPROM
{
unsigned int EE_Address = 0;
byte indicativ = 0;// valoarea primului octet
EEPROM.get(0, indicativ);
EE_Address += sizeof (indicativ); // calculez adresa de stocare pt. tmp_POMPA
switch (flag)
{
case 0: // functia setup()
if (indicativ == 0xFF) {indicativ = 0x80; EEPROM.put(0, indicativ); EEPROM.put(EE_Address, POMPA);}// prima rulare a programului
else EEPROM.get(EE_Address, POMPA);// se initializeaza la fiecare resetare
break;
case 1: // functia Initializare_Ciclu ()
if (indicativ == 0x40) {indicativ = 0x80; EEPROM.put(0, indicativ); EEPROM.get(EE_Address, POMPA);}
break;
case 2: // meniul Setup - se va stoca la fiecare SAVE & EXIT din submeniuri
EEPROM.put(0, 0x40); EEPROM.put(EE_Address, POMPA_Set);
break;
case 3: // se va citi continutul memoriei pentru reinitializare variabile în setare timp pompe
EEPROM.get(EE_Address, POMPA_Set);
break;
case 4: // scrie primul octet 0xFF adica 1111 1111 sau 255 dec, pentru resetare fabrica se foloseste in functia Defilare_Meniu_Setup
EEPROM.put(0, 0xFF);
break;
}
}
//TIMSK1 |= 1;// pornesc intrerupere Timer 1
}// end Scrie_Citeste_EEPROM
/**********************************************************************************/
/******************** FUNCTIE Button_Timp_PLUS_MINUS *****************************/
// Acesta functie adauga sau scade timp in timpul Meniului setup pentru
// modificarea parametrilor de functionare
//Intervalele min. max. si pasul de incrementre se regasesc in sectiune de declarare variabile globale
// modificat este diferit de 0 si suntem in meniul anterior se vor salva valorile modificate
inline void Button_Timp_PLUS_MINUS( int &val_11, int &val_22)
{
// val_11 si val_22 sunt adresele acelorasi variabile din functia Blink_Meniu() si nu trebuie confundate
static byte modificat = 0;//daca se fac modificari se vor salva cand se paraseste meniul
// prin SAVE&EXIT si ia urmatoarele valori
// 1 AERARE BAZIN 1
// 2 AERARE BAZIN 2
// 3 EVACUARE
// 4 RECIRCULARE
// 5 DOZARE FLOCULANT
/*---------------- AERARE BAZIN 1 -------------------*/
if (subMeniuAERARE == 1 && modificat == 1) {Scrie_Citeste_EEPROM(2); modificat = 0;} //salveaza modificarea pt aerare Bazin 1
if (subMeniuAERARE == 1) Scrie_Citeste_EEPROM(3);// citeste valorile existente in structura POMPA_Set
if (subMeniuBazin_1_AERARE == 1 )// AERARE
{
if (POMPA_Set.Bazin_1_Aerare <= 230) {if (!digitalRead(PIN_BUTON_TIMP_PLUS)) POMPA_Set.Bazin_1_Aerare += 10; modificat = 1; init_SETUP = true;}
if (POMPA_Set.Bazin_1_Aerare >= 40 ) {if (!digitalRead(PIN_BUTON_TIMP_MINUS)) POMPA_Set.Bazin_1_Aerare -= 10; modificat = 1; init_SETUP = true;}
val_11 = POMPA_Set.Bazin_1_Aerare; val_22 = POMPA_Set.Bazin_1_Linistire / 60; return;
}
else if (subMeniuBazin_1_AERARE == 2 )// LINISTIRE
{
if (POMPA_Set.Bazin_1_Linistire <= 3300) {if (!digitalRead(PIN_BUTON_TIMP_PLUS)) POMPA_Set.Bazin_1_Linistire += 300; modificat = 1; init_SETUP = true;}
if (POMPA_Set.Bazin_1_Linistire >= 600 ) {if (!digitalRead(PIN_BUTON_TIMP_MINUS)) POMPA_Set.Bazin_1_Linistire -= 300; modificat = 1; init_SETUP = true;}
val_11 = POMPA_Set.Bazin_1_Aerare; val_22 = POMPA_Set.Bazin_1_Linistire / 60; return;
}
else if (subMeniuBazin_1_AERARE == 3 ) {val_11 = POMPA_Set.Bazin_1_Aerare; val_22 = POMPA_Set.Bazin_1_Linistire / 60; return;}
/*---------------- AERARE BAZIN 2 -------------------*/
if (subMeniuAERARE == 2 && modificat == 2) {Scrie_Citeste_EEPROM(2); modificat = 0;}// salveaza modificarea pt aerare Bazin 2
if (subMeniuAERARE == 2) Scrie_Citeste_EEPROM(3);// citeste valorile existente in structura POMPA_Set
if (subMeniuBazin_2_AERARE == 1 )//AERARE
{
if (POMPA_Set.Bazin_2_Aerare <= 230) {if (!digitalRead(PIN_BUTON_TIMP_PLUS)) POMPA_Set.Bazin_2_Aerare += 10; modificat = 2; init_SETUP = true;}
if (POMPA_Set.Bazin_2_Aerare >= 40 ) {if (!digitalRead(PIN_BUTON_TIMP_MINUS)) POMPA_Set.Bazin_2_Aerare -= 10;modificat = 2; init_SETUP = true;}
val_11 = POMPA_Set.Bazin_2_Aerare; val_22 = POMPA_Set.Bazin_2_Linistire / 60; return;
}
else if (subMeniuBazin_2_AERARE == 2 )//LINISTIRE
{
if (POMPA_Set.Bazin_2_Linistire <= 3300) {if (!digitalRead(PIN_BUTON_TIMP_PLUS)) POMPA_Set.Bazin_2_Linistire += 300; modificat = 2; init_SETUP = true;}
if (POMPA_Set.Bazin_2_Linistire >= 600 ) {if (!digitalRead(PIN_BUTON_TIMP_MINUS)) POMPA_Set.Bazin_2_Linistire -= 300; modificat = 2; init_SETUP = true;}
val_11 = POMPA_Set.Bazin_2_Aerare; val_22 = POMPA_Set.Bazin_2_Linistire/60; return;
}
else if (subMeniuBazin_2_AERARE == 3 ) {val_11 = POMPA_Set.Bazin_2_Aerare; val_22 = POMPA_Set.Bazin_2_Linistire / 60; return;}
/*---------------- EVACUARE -------------------*/
if (Meniu == 2 && modificat == 3) {Scrie_Citeste_EEPROM(2); modificat = 0;}// salveaza modificarea pt Evacuare
if (Meniu == 2) Scrie_Citeste_EEPROM(3);// citeste valorile
if (subMeniuEVACUARE == 1 )//EVACUARE
{
if (POMPA_Set.PornireEvacuare <= 290) {if (!digitalRead(PIN_BUTON_TIMP_PLUS)) POMPA_Set.PornireEvacuare += 10; modificat = 3; init_SETUP = true;}
if (POMPA_Set.PornireEvacuare >= 190 ) {if (!digitalRead(PIN_BUTON_TIMP_MINUS)) POMPA_Set.PornireEvacuare -= 10; modificat = 3; init_SETUP = true;}
val_11 = POMPA_Set.PornireEvacuare; val_22 = POMPA_Set.LinistireEvacuare / 60; return;
}
else if (subMeniuEVACUARE == 2 )//LINISTIRE evacuare
{
if (POMPA_Set.LinistireEvacuare <= 3300) {if (!digitalRead(PIN_BUTON_TIMP_PLUS)) POMPA_Set.LinistireEvacuare += 300; modificat = 3; init_SETUP = true;}
if (POMPA_Set.LinistireEvacuare >= 600 ) {if (!digitalRead(PIN_BUTON_TIMP_MINUS)) POMPA_Set.LinistireEvacuare -= 300; modificat = 3; init_SETUP = true;}
val_11 = POMPA_Set.PornireEvacuare; val_22 = POMPA_Set.LinistireEvacuare/60; return;
}
else if (subMeniuEVACUARE == 3 ) {val_11 = POMPA_Set.PornireEvacuare; val_22 = POMPA_Set.LinistireEvacuare/60; return;}
/*---------------- RECIRCULARE -------------------*/
if (Meniu == 3 && modificat == 4) {Scrie_Citeste_EEPROM(2); modificat = 0;}
if (Meniu == 3 ) Scrie_Citeste_EEPROM(3);
if (subMeniuRECIRCULARE == 1 )//RECIRCULARE amestec
{
if (POMPA_Set.PornireRecirculare <= 115) {if (!digitalRead(PIN_BUTON_TIMP_PLUS)) POMPA_Set.PornireRecirculare += 5; modificat = 4; init_SETUP = true;}
if (POMPA_Set.PornireRecirculare >= 20 ) {if (!digitalRead(PIN_BUTON_TIMP_MINUS)) POMPA_Set.PornireRecirculare -= 5; modificat = 4; init_SETUP = true;}
val_11 = POMPA_Set.PornireRecirculare; val_22 = POMPA_Set.AsteptareRecirculare; return;
}
else if (subMeniuRECIRCULARE == 2 )//INTERVAL RECIRCULARE perioada de timp la care se realizeaza
{
if (POMPA_Set.AsteptareRecirculare <= 7) {if (!digitalRead(PIN_BUTON_TIMP_PLUS)) POMPA_Set.AsteptareRecirculare += 1; modificat = 4; init_SETUP = true;}
if (POMPA_Set.AsteptareRecirculare >= 4 ) {if (!digitalRead(PIN_BUTON_TIMP_MINUS)) POMPA_Set.AsteptareRecirculare -= 1; modificat = 4; init_SETUP = true;}
val_11 = POMPA_Set.PornireRecirculare; val_22 = POMPA_Set.AsteptareRecirculare; return;
}
else if (subMeniuRECIRCULARE == 3 ) {val_11 = POMPA_Set.PornireRecirculare; val_22 = POMPA_Set.AsteptareRecirculare; return;}
/*----------------- FLOCULANT ---------------------*/
if (Meniu == 4 && modificat == 5) {Scrie_Citeste_EEPROM(2); modificat = 0;}
if (Meniu == 4 ) Scrie_Citeste_EEPROM(3);
if (subMeniuFLOCULANT == 1 )//DOZARE BAZIN 1
{
if (POMPA_Set.PompaPeristaltica_B1 <= 19) {if (!digitalRead(PIN_BUTON_TIMP_PLUS)) POMPA_Set.PompaPeristaltica_B1 += 1; modificat = 5; init_SETUP = true;}
if (POMPA_Set.PompaPeristaltica_B1 >= 1 ) {if (!digitalRead(PIN_BUTON_TIMP_MINUS)) POMPA_Set.PompaPeristaltica_B1 -= 1; modificat = 5; init_SETUP = true;}
val_11 = POMPA_Set.PompaPeristaltica_B1; val_22 = POMPA_Set.PompaPeristaltica_B2; return;
}
else if (subMeniuFLOCULANT == 2 )//DOZARE BAZIN 2
{
if (POMPA_Set.PompaPeristaltica_B2 <= 19) {if (!digitalRead(PIN_BUTON_TIMP_PLUS)) POMPA_Set.PompaPeristaltica_B2 += 1; modificat = 5; init_SETUP = true;}
if (POMPA_Set.PompaPeristaltica_B2 >= 1 ) {if (!digitalRead(PIN_BUTON_TIMP_MINUS)) POMPA_Set.PompaPeristaltica_B2 -= 1; modificat = 5; init_SETUP = true;}
val_11 = POMPA_Set.PompaPeristaltica_B1; val_22 = POMPA_Set.PompaPeristaltica_B2; return;
}
else if (subMeniuFLOCULANT == 3 ) {val_11 = POMPA_Set.PompaPeristaltica_B1; val_22 = POMPA_Set.PompaPeristaltica_B2; return;}
}// end Button_Timp_PLUS_MINUS
/*************************************************************************************/
/************ FUNCTIE CARE DETERMINA CAT TIMP ESTE APASAT UN BUTON *******************/
// Aceasta fuctie determina cat timp este apasat butonul
// Daca timpAPASARE este egal cu zero returneaza
// TIMPUL MAXIM DE APASARE ESTE 2^32-1 MILISECUNDE APROXIMATIV 50 ZILE APOI SE RESETEAZA
// Variabila " start " reprezinta timpul la care a fost apasat butonul si se determina
// cu functia arduino " millis() "
// Variabila " timpAPASARE " reprezinta timpul necesar de apasare ca butonul sa produca efect si este dat in milisecude,
// In interiorul functiei calculul se realizeaza in milisecunde deoarece valoarea " start " este data de functia " millis() "
unsigned long Timp_Apasare_BTN (const uint8_t &btnPIN, const unsigned long &timpAPASARE)
{
unsigned long secundeDOWN = 0;
unsigned long start = millis();
if (digitalRead(btnPIN)) {return false;}
while(!digitalRead(btnPIN)) { secundeDOWN = millis();}
if ( secundeDOWN >= start )
{
if (timpAPASARE == 0) {return (secundeDOWN - start);}
else if ((secundeDOWN - start) >= timpAPASARE) {return true;}
else {return false;}
}
else if (secundeDOWN < start)
{
if (timpAPASARE == 0) {return (( pow(2 , 32) -1 - start) + secundeDOWN );}
else if ((( pow(2 , 32) -1 - start) + secundeDOWN )>= timpAPASARE) {return true;}
else {return false;}
}
}//end Timp_Apasare_BTN
/*********************** FUNCTIE Blink_Meniu ***********************/
// Acesata functie afiseaza meniul pentru afisaj 20x4
// Meniul selectat va clipi
// Prima linie a afisajului este folosita pentru titlu
// Sunt afisate doar trei linii de meniu
// Denumirea meniului nu trebuie sa fie mai mare de 14 caractere daca este
// necesara introducere de date, altfel sa nu depasasca 18 caractere
// sel reprezinta pozitia meniului selectat
// sel reprezinta linia de afisare cu valori 1, 2 sau 3
// val_ reprezinta valorile variabilelor care se vor afisa modificate prin introducere de date
// UM_ reprezinta unitatea de masura
void Blink_Meniu ( int sel, const String &meniu_1 = "", const String &meniu_2 = "", const String &meniu_3 = "",
int val_1 = -1, int val_2 = -1, int val_3 = -1,
const String &UM_1 = "", const String &UM_2 = "", const String &UM_3 = "" )
{
int max_nrChar = 0;// nr. maxim de caracte dintr-un meniu afisat
max_nrChar =max ( max( meniu_1.length(), meniu_2.length() ), meniu_3.length() ) + 3;// se aduna 3 pentru ca adauga caracterul >> sau 2 spatii inainte + spatiul de delimitare
if (Meniu == 1) {max_nrChar = 19;} // pentru a sterge caracterele de la " RESETARE FABRICA "
switch (sel) // stabileste meniul selectat
{
case 1: meniu_1 = ">> " + meniu_1; meniu_2 = " " + meniu_2 ; meniu_3 = " " + meniu_3 ; break;
case 2: meniu_1 = " " + meniu_1 ; meniu_2 = ">> " + meniu_2; meniu_3 = " " + meniu_3 ; break;
case 3: meniu_1 = " " + meniu_1 ; meniu_2 = " " + meniu_2 ; meniu_3 = ">> " + meniu_3; break;
}
for ( byte i = 2; (i = max_nrChar - meniu_1.length()); i++ ) { meniu_1 = meniu_1 + " "; } // se adauga spatii daca textul este mai mic decat max_nrChar
for ( byte i = 2; (i = max_nrChar - meniu_2.length()); i++ ) { meniu_2 = meniu_2 + " "; } // se adauga spatii daca textul este mai mic decat max_nrChar
for ( byte i = 2; (i = max_nrChar - meniu_3.length()); i++ ) { meniu_3 = meniu_3 + " "; } // se adauga spatii daca textul este mai mic decat max_nrChar
Button_Timp_PLUS_MINUS( val_1, val_2);
lcd.setCursor(0, 1); lcd.print( meniu_1 ); if (val_1 != -1) { lcd.setCursor(max_nrChar, 1); lcd.print(val_1); }; if (UM_1 != "") { lcd.setCursor(17, 1); lcd.print(UM_1); }
lcd.setCursor(0, 2); lcd.print( meniu_2 ); if (val_2 != -1) { lcd.setCursor(max_nrChar, 2); lcd.print(val_2); }; if (UM_2 != "") { lcd.setCursor(17, 2); lcd.print(UM_2); }
lcd.setCursor(0, 3); lcd.print( meniu_3 ); if (val_3 != -1) { lcd.setCursor(max_nrChar, 3); lcd.print(val_3); }; if (UM_3 != "") { lcd.setCursor(17, 3); lcd.print(UM_3); }
delay(250);// intarzierea este obligatorie pt a nu se incarca stiva care conduce la blocare
if (val_1 != -1 && sel == 1) { lcd.setCursor(max_nrChar, sel); lcd.print(" ");}// afiseaza 3 spatii si creaza efectul de clipire citire date
else if (val_2 != -1 && sel == 2) { lcd.setCursor(max_nrChar, sel); lcd.print(" ");}// afiseaza 3 spatii si creaza efectul de clipire citire date
else if (val_3 != -1 && sel == 3) { lcd.setCursor(max_nrChar, sel); lcd.print(" ");}// afiseaza 3 spatii si creaza efectul de clipire citire date
else if (subMeniuRESET_FABRICA == 1) { lcd.setCursor(3, 2 ); lcd.print("< >");}
else if (subMeniuRESET_FABRICA == 2) { lcd.setCursor(11, 2); lcd.print("< >");}
else { lcd.setCursor(0, sel); lcd.print( " " ); }//afiseaza 2 spatii si creaza efectul de clipire meniu
delay(150);// intarzierea este obligatorie pt a nu se incarca stiva care conduce la blocare
}// end Blink_Meniu
/***************** FUNCTIE Afisare_Meniu ********************/
// Aceasta functie afiseaza Meniul si Meniul selectat prin licarire si marcat cu caracterul ">"
// Functia este utilizata in interiorul functiei Defilare_Meniu ()
inline void Afisare_Meniu_Setup ()
{
//ATOMIC_BLOCK(ATOMIC_RESTORESTATE) // cu LCD_I2C se blocheaza in WOKWI
{
String AERARE = F("AERARE");
String EVACUARE = F("EVACUARE");
String RECIRCULARE = F("RECIRCULARE");
String BAZIN_1 = F("BAZIN 1");
String BAZIN_2 = F("BAZIN 2");
String EXIT = F("EXIT");
String PORNIRE = F("PORNIRE");
String LINISTIRE = F("LINISTIRE");
String ASTEPTARE = F("ASTEPTARE");
String SAVE_EXIT = F("SAVE & EXIT");
String ORE = F("ore");
String MIN = F("min");
String SEC = F("sec");
String RESET_FABRICA = F("RESETARE FABRICA");
String DA = F("DA");
String NU = F("NU");
String FLOCULANT = F("DOZARE FLOCULANT");
String DOZAJ_BAZIN_1 = F("BAZIN 1");
String DOZAJ_BAZIN_2 = F("BAZIN 2");
String ML = F("ml");
if (Meniu >= 1 && Meniu <= 6) { lcd.setCursor(0, 0); lcd.print(F("------ SETARE ------"));}
// Meniu principal 1 - AERARE
if (Meniu == 1) {Blink_Meniu ( 1, AERARE, EVACUARE, RECIRCULARE );}
// Meniu principal 2 - EVACUARE
else if (Meniu == 2) {Blink_Meniu ( 2, AERARE, EVACUARE, RECIRCULARE );}
// Meniu principal 3 - RECIRCULARE
else if (Meniu == 3) {Blink_Meniu ( 3, AERARE, EVACUARE, RECIRCULARE );}
// Meniu principal 4 - DOZARE FLOCULANT
else if (Meniu == 4) {Blink_Meniu ( 3, EVACUARE, RECIRCULARE, FLOCULANT );}
// Meniu principal 5 - RESET FABRICA
else if (Meniu == 5) {Blink_Meniu ( 3, RECIRCULARE, FLOCULANT, RESET_FABRICA );}
// Meniu principal 5 - EXIT
else if (Meniu == 6) {Blink_Meniu ( 3, FLOCULANT, RESET_FABRICA, EXIT );}
// Meniu AERARE
else if (Meniu == 7)
{
if (subMeniuAERARE >= 1 && subMeniuAERARE <= 3) { lcd.setCursor(0, 0); lcd.print(F("-- SETARE: AERARE --"));}
// subMeniuAERARE
if (subMeniuAERARE == 1) {Blink_Meniu ( 1, BAZIN_1, BAZIN_2, EXIT ); }
else if (subMeniuAERARE == 2) {Blink_Meniu ( 2, BAZIN_1, BAZIN_2, EXIT ); }
else if (subMeniuAERARE == 3) {Blink_Meniu ( 3, BAZIN_1, BAZIN_2, EXIT ); }
//Aerare BAZIN 1
else if (subMeniuAERARE == 4)
{
lcd.setCursor(0, 0); lcd.print(F("-- AERARE BAZIN 1 --"));
//AERARE
if (subMeniuBazin_1_AERARE == 1) {Blink_Meniu ( 1, AERARE, LINISTIRE, SAVE_EXIT,POMPA.Bazin_1_Aerare, POMPA.Bazin_1_Linistire/60, -1, SEC, MIN ); }
//LINISTIRE
else if (subMeniuBazin_1_AERARE == 2) {Blink_Meniu ( 2, AERARE, LINISTIRE, SAVE_EXIT,POMPA.Bazin_1_Aerare, POMPA.Bazin_1_Linistire/60, -1, SEC, MIN ); }
//SAVE & EXIT
else if (subMeniuBazin_1_AERARE == 3) {Blink_Meniu ( 3, AERARE, LINISTIRE, SAVE_EXIT,POMPA.Bazin_1_Aerare, POMPA.Bazin_1_Linistire/60, -1, SEC, MIN ); }
}
// Aerare BAZIN 2
else if (subMeniuAERARE == 5)
{
lcd.setCursor(0, 0); lcd.print(F("-- AERARE BAZIN 2 --"));
//AERARE
if (subMeniuBazin_2_AERARE == 1) {Blink_Meniu ( 1, AERARE, LINISTIRE, SAVE_EXIT,POMPA.Bazin_1_Aerare, POMPA.Bazin_1_Linistire/60, -1, SEC, MIN ); }
//LINISTIRE
else if (subMeniuBazin_2_AERARE == 2) {Blink_Meniu ( 2, AERARE, LINISTIRE, SAVE_EXIT,POMPA.Bazin_1_Aerare, POMPA.Bazin_1_Linistire/60, -1, SEC, MIN ); }
//SAVE & EXIT
else if (subMeniuBazin_2_AERARE == 3) {Blink_Meniu ( 3, AERARE, LINISTIRE, SAVE_EXIT,POMPA.Bazin_1_Aerare, POMPA.Bazin_1_Linistire/60, -1, SEC, MIN ); }
}
}
// Meniu EVACUARE
else if (Meniu == 8)
{
// subMeniuEVACUARE
lcd.setCursor(0, 0); lcd.print(F("----- EVACUARE -----"));
//EVACUARE
if (subMeniuEVACUARE == 1) Blink_Meniu ( 1, EVACUARE, LINISTIRE, SAVE_EXIT, POMPA.PornireEvacuare, POMPA.LinistireEvacuare/60, -1, SEC, MIN );
//LINISTIRE
else if (subMeniuEVACUARE == 2) Blink_Meniu ( 2, EVACUARE, LINISTIRE, SAVE_EXIT, POMPA.PornireEvacuare, POMPA.LinistireEvacuare/60, -1, SEC, MIN );
//SAVE & EXIT
else if (subMeniuEVACUARE == 3) Blink_Meniu ( 3, EVACUARE, LINISTIRE, SAVE_EXIT, POMPA.PornireEvacuare, POMPA.LinistireEvacuare/60, -1, SEC, MIN );
}
// Meniu RECIRCULRE
else if (Meniu == 9)
{
// subMeniuRECIRCULARE
lcd.setCursor(0, 0); lcd.print(F("---- RECIRCULARE ---"));
//PORNIRE
if (subMeniuRECIRCULARE == 1) Blink_Meniu ( 1, PORNIRE, ASTEPTARE , SAVE_EXIT, POMPA.PornireRecirculare, POMPA.AsteptareRecirculare, -1, SEC , ORE );
//ASTEPTARE
else if (subMeniuRECIRCULARE == 2) Blink_Meniu ( 2, PORNIRE, ASTEPTARE , SAVE_EXIT, POMPA.PornireRecirculare, POMPA.AsteptareRecirculare, -1, SEC , ORE );
// SAVE & EXIT
else if (subMeniuRECIRCULARE == 3) Blink_Meniu ( 3, PORNIRE, ASTEPTARE , SAVE_EXIT, POMPA.PornireRecirculare, POMPA.AsteptareRecirculare, -1, SEC , ORE );
}
// Meniu DOZARE FLOCULANT
else if (Meniu == 10)
{
// subMeniuFLOCULANT
lcd.setCursor(0, 0); lcd.print(F("- DOZARE FLOCULANT -"));
//DOZAJ BAZIN 1
if (subMeniuFLOCULANT == 1) Blink_Meniu ( 1, DOZAJ_BAZIN_1, DOZAJ_BAZIN_2 , SAVE_EXIT, POMPA.PompaPeristaltica_B1, POMPA.PompaPeristaltica_B2, -1, ML, ML);
//DOZAJ BAZIN 2
else if (subMeniuFLOCULANT == 2) Blink_Meniu ( 2, DOZAJ_BAZIN_1, DOZAJ_BAZIN_2 , SAVE_EXIT, POMPA.PompaPeristaltica_B1, POMPA.PompaPeristaltica_B2, -1, ML, ML);
//SAVE & EXIT
else if (subMeniuFLOCULANT == 3) Blink_Meniu ( 3, DOZAJ_BAZIN_1, DOZAJ_BAZIN_2 , SAVE_EXIT, POMPA.PompaPeristaltica_B1, POMPA.PompaPeristaltica_B2, -1, ML, ML);
}
// Meniu RESET FABRICA
else if (Meniu == 11)
{
//RESETARE FABRICA
lcd.setCursor(0, 0); lcd.print(F("- RESETARE FABRICA -"));
//NU
if (subMeniuRESET_FABRICA == 1) Blink_Meniu ( 4, F(""), F(" < NU > DA") );
//DA
else if (subMeniuRESET_FABRICA == 2) Blink_Meniu ( 4, F(""), F(" NU < DA >") );
}
// AERARE = "";
// EVACUARE = "";
// RECIRCULARE = "";
// BAZIN_1 = "";
// BAZIN_2 = "";
// EXIT = "";
// PORNIRE = "";
// LINISTIRE = "";
// ASTEPTARE = "";
// SAVE_EXIT = "";
// ORE = "";
// MIN = "";
// SEC = "";
}
}// end Afisare_Meniu_Setup
/***************** FUNCTIE CARE DEFILEZA MeniuL SETARE CU UN SINGUR BUTON ********************/
// Cand este chemata modifica valoare variabilei " Meniu ".
// Functia este executata numai cand valorea variabilei " Meniu " este >= 1
// Cand variabila " Meniu = -1 " microcontroler-ul executa alte operatii
// Daca butonul SETARE este apasat >= 1 secunda programul intra in modul setare
// Daca butonul SETARE este apasat >= 1 secunda pe subMeniu se intra in subMeniuri
// Daca butonul SETARE este apasat 0.45 - 0.9 secunde defileaza intre meniuri
inline void Defilare_Meniu_Setup ()
{
if (Meniu == -1 && init_SETUP) {init_SETUP = false; Initializare_Ciclu();}
if (Meniu == -1 && (PIND & (1 << PD6)) != 0) return;//digitalRead(PIN_BUTON_SETUP)) return;
//if (Meniu == -1 && digitalRead(PIN_BUTON_SETUP)) return;
Afisare_Meniu_Setup ();
//if (digitalRead(PIN_BUTON_SETUP)) return;
if ((PIND & (1 << PD6)) != 0) return;//daca nu este apasat butonul SETUP
bool timp = Timp_Apasare_BTN ( PIN_BUTON_SETUP, 1000 );// returneaza intotdeauna TRUE sau FALSE
// deoarece timpAPASARE este diferit de zero
switch (Meniu) { // Meniul principal are 4 submeniuri
case -1: // intra in modul SETARE
if (timp) { Meniu = 1; lcd.clear (); }
break;
case 1: // Meniu principal 1 - AERARE
if (!timp) { Meniu ++; }
else { Meniu = 1 + 6; subMeniuAERARE = 1; lcd.clear(); }
break;
case 2: // Meniu principal 2 - EVACUARE
if (!timp) { Meniu ++; }
else { Meniu = 2 + 6; subMeniuEVACUARE = 1; lcd.clear(); }
break;
case 3: // Meniu principal 3 - RECIRCULARE
if (!timp) { Meniu ++; }
else { Meniu = 3 + 6; subMeniuRECIRCULARE = 1; lcd.clear(); }
break;
case 4: // Meniu principal 4 - DOZAJ FLOCULANT
if (!timp) { Meniu ++; }
else { Meniu = 4 + 6 ; subMeniuFLOCULANT = 1; lcd.clear(); }
break;
case 5: // Meniu principal 4 - RESET FABRICA
if (!timp) { Meniu ++; }
else { Meniu = 5 + 6 ; subMeniuRESET_FABRICA = 1; lcd.clear(); }
break;
case 6: // Meniu principal 4 - EXIT
if (!timp) { Meniu = 1; }
else { Meniu = -1 ; subMeniuAERARE = -1; subMeniuEVACUARE = -1; subMeniuRECIRCULARE = -1; subMeniuRESET_FABRICA = -1; lcd.clear(); }
break;
case 7: // Meniu secundar 1 - AERARE
switch (subMeniuAERARE) { // subMeniuAERARE are 3 subMeniuri bazin 1 bazin 2 exit
case 1: // sub Meniu BAZN 1
if (!timp) { subMeniuAERARE ++; }
else { subMeniuAERARE = 1 + 3; subMeniuBazin_1_AERARE = 1;}
break;
case 2: // sub Meniu BAZN 2
if (!timp) { subMeniuAERARE ++; }
else { subMeniuAERARE = 2 + 3; subMeniuBazin_2_AERARE = 1;}
break;
case 3: // sub Meniu EXIT
if (!timp ) { subMeniuAERARE = 1; }
else { Meniu = 1; subMeniuAERARE = -1; lcd.clear ();}
break;
case 4: //sub Meniu Bazin 1 AERARE // are 3 submeniuri PORNIRE , LINISTIRE si SAVE & EXIT
switch (subMeniuBazin_1_AERARE) {
case 1: //PORNIRE
if (!timp ) { subMeniuBazin_1_AERARE++; }
break;
case 2: //LINISTIRE
if (!timp ) { subMeniuBazin_1_AERARE++; }
break;
case 3: //SAVE & EXIT
if (!timp ) { subMeniuBazin_1_AERARE = 1; }
else { subMeniuAERARE = 1; subMeniuBazin_1_AERARE = -1; subMeniuBazin_2_AERARE = -1; lcd.clear (); }
break;
}// end switch (subMeniuBazin_1_AERARE)
break;
case 5: //sub Meniu Bazin 2 AERARE // are 3 submeniuri PORNIRE , LINISTIRE si SAVE & EXIT
switch (subMeniuBazin_2_AERARE) {
case 1: //PORNIRE
if (!timp ) { subMeniuBazin_2_AERARE++; }
break;
case 2: //LINISTIRE
if (!timp ) { subMeniuBazin_2_AERARE++; }
break;
case 3: //SAVE & EXIT
if (!timp ) { subMeniuBazin_2_AERARE = 1; }
else { subMeniuAERARE = 2; subMeniuBazin_1_AERARE = -1; subMeniuBazin_2_AERARE = -1; lcd.clear (); }
break;
}// end switch (subMeniuBazin_2_AERARE)
break;
}// end switch (subMeniuAERARE)
break;
case 8: // sub Meniu EVACUARE // are 3 sub Meniuri PORNIRE, LINISTIRE si SAVE & EXIT
switch (subMeniuEVACUARE) {
case 1: //PORNIRE
if (!timp ) { subMeniuEVACUARE++; }
break;
case 2: //LINISTIRE
if (!timp ) { subMeniuEVACUARE++; }
break;
case 3: //SAVE & EXIT
if (!timp ) { subMeniuEVACUARE = 1; }
else { Meniu = 2; subMeniuEVACUARE = -1; lcd.clear (); }
break;
}// end switch (subMeniuEVACUARE)
break;
case 9: // RECIRCULARE // are 3 sub Meniuri PORNIRE, ASTEPTARE si SAVE & EXIT
switch (subMeniuRECIRCULARE) {
case 1: //PORNIRE
if (!timp ) { subMeniuRECIRCULARE++; }
break;
case 2: //ASTEPTARE
if (!timp ) { subMeniuRECIRCULARE++; }
break;
case 3: //SAVE & EXIT
if (!timp ) { subMeniuRECIRCULARE = 1; }
else { Meniu = 3; subMeniuRECIRCULARE = -1; lcd.clear (); }
break;
}// end switch (subMeniuRECIRCULARE)
break;
case 10: // DOZAJ FLOCULANT // are 3 sub Meniuri DOZAJ BAZIN 1, DOZAJ BAZIN 2 si SAVE & EXIT
switch (subMeniuFLOCULANT) {
case 1: //DOZAJ BAZIN 1
if (!timp ) { subMeniuFLOCULANT++; }
break;
case 2: //DOZAJ BAZIN 2
if (!timp ) { subMeniuFLOCULANT++; }
break;
case 3: //SAVE & EXIT
if (!timp ) { subMeniuFLOCULANT = 1; }
else { Meniu = 4; subMeniuFLOCULANT = -1; lcd.clear (); }
break;
}// end switch (subMeniuFLOCULANT)
break;
case 11: // RESET FABRICA // are 2 sub meniuri NU si DA
switch (subMeniuRESET_FABRICA){
case 1: // NU
if (!timp ) { subMeniuRESET_FABRICA++; }
else { Meniu = 5; subMeniuRESET_FABRICA = -1; lcd.clear (); }
break;
case 2: // DA
if (!timp ) { subMeniuRESET_FABRICA = 1; }
else { Meniu = 5; subMeniuRESET_FABRICA = -1; lcd.clear (); Scrie_Citeste_EEPROM(4); resetFunc();}
break;
}// end switch (subMeniuRESET_FABRICA)
break;
}// end switch (Meniu)
}//end Defilare_Meniu_Setup
/************** FUNCTIE INFO-HELP *******************/
// Aceasta functie afiseaza informatii privind temperatura si alarmele aparute
// Partea de help textul alarmelor pt a se cunoaste ce reprezinta fiecare alarma
// Alarmele sunt in numar de sase si se afiseaza (Ax) - yyy , Ax inseamna A1, A2,...A6
// iar yyy insemna numarul de aparitii a alarmei, maxim stocate 255
// aparitiile alarmelor nu sunt stocate in memoria EEPROM, la fiecare resetare sau
// intreruperea curentului nr. aparitiei alarmelor se vor reseta la zero
void Info_Help()
{
byte tmp = 0;
bool timp_help = false;
bool timp_info = false;
if (digitalRead(PIN_BUTON_TIMP_PLUS) && digitalRead(PIN_BUTON_TIMP_MINUS)) return;
else if (!digitalRead(PIN_BUTON_TIMP_MINUS)) {timp_info = Timp_Apasare_BTN ( PIN_BUTON_TIMP_MINUS, 1000 ); tmp = 102;}// returneaza intotdeauna TRUE sau FALSE
else if (!digitalRead(PIN_BUTON_TIMP_PLUS)) {timp_help = Timp_Apasare_BTN ( PIN_BUTON_TIMP_PLUS, 1000 ); tmp = 101;}// returneaza intotdeauna TRUE sau FALSE
// deoarece timpAPASARE este diferit de zero
if (Meniu == -1 && timp_info && info_help == 0) {Meniu = 0; info_help = -1; }// afiseaza info
else if (Meniu == 0 && timp_info && info_help < 0) {Meniu = -1; info_help = 0; return;}// iese din info si afiseaza starea curenta
if (Meniu == -1 && timp_help && info_help == 0) {Meniu = 0; info_help = 1; }// afiseaza help
else if (Meniu == 0 && timp_help && info_help > 0) {Meniu = -1; info_help = 0; return;}// iese din help si afiseaza starea curenta
if (info_help < 0 && (tmp == 101)) return;
if (info_help > 0 && (tmp == 102)) return;
lcd.clear();
tmp =0;
switch (info_help) {
case -2: // info alarme
if (!timp_info) { info_help ++; }
lcd.setCursor (0,0); lcd.print(F("< APARITII ALARME >"));
for (byte i = 1; i <= 6; i++)
{
if (i <= 3) tmp = 1;
else tmp = 11;
lcd.setCursor (tmp - 1, (i <= 3 ? i : i - 3));lcd.print(F("A("));lcd.print(i);lcd.print(F(")"));
lcd.setCursor (4 + tmp, (i <= 3 ? i : i - 3));lcd.print(LCD.Alarma[i-1]);
}
break;
case -1: // info teperatura
if (!timp_info) { info_help --; }
lcd.setCursor (0,0); lcd.print(F("<TEMPERATURA STATIE>"));
lcd.setCursor (10,1); lcd.print(F("EXT"));
lcd.setCursor (10,2); lcd.print(F("INT"));
for (byte i = 1; i <= 5; i++)
{
if (i <= 3)
{
tmp = 0;
lcd.setCursor (0, i);lcd.print(F("B"));lcd.print(i-1);
}
else tmp = 11;
if (LCD.Temperatura[i-1] > 0)
{
lcd.setCursor (3 + tmp, (i <= 3 ? i : i - 3));lcd.print("+");
lcd.setCursor (4 + tmp, (i <= 3 ? i : i - 3));lcd.print(LCD.Temperatura[i-1]);
}
else if (LCD.Temperatura[i-1] == 0)
{
//lcd.setCursor (3 + tmp, (i <= 3 ? i : i - 3));lcd.print(" ");
lcd.setCursor (4 + tmp, (i <= 3 ? i : i - 3));lcd.print(LCD.Temperatura[i-1]);
}
else if (LCD.Temperatura[i-1] < 0)
{
lcd.setCursor (3 + tmp, (i <= 3 ? i : i - 3));lcd.print(LCD.Temperatura[i-1]);
}
}
break;
case 1 ... 5: // alarma 1
if (!timp_help) { info_help ++; }
break;
case 6: // Meniu principal 2 - EVACUARE
if (!timp_help) { info_help = 1; }
break;
}
if (info_help >= 1)
{
Alarme (info_help);
lcd.setCursor (0,0); lcd.print(LCD.Line0); // ((char*)LCD.Line0);
lcd.setCursor (0,1); lcd.print(LCD.Line1); //((char*)LCD.Line1);
lcd.setCursor (0,2); lcd.print(LCD.Line2); //((char*)LCD.Line2);
lcd.setCursor (0,3); lcd.print(LCD.Line3); //((char*)LCD.Line3);
}
}// end Info_Help
. . . . . . POMPE . . . . . . .
P2.2 P1.2 .P2.3 .P1.1 P2.1
ElectroVANĂ
. . . 3 cai . . .
------------------PLUTITORI--------------------
. . . . . . . . . . . . . Contacte Reed. . . . . . . . . . . . . .
1-Nivel B1, 2-Nivel B2, 3-PreaPLIN B2, 4-PreaGol B1-B2
POMPA Peristaltica
BAZIN 2 BAZIN 1
ALARMA
B0..... B1..... B2... int.... ext