//Copyright (c) 2024 Duțoiu Nicolae

// Mcu MASTER

// 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 si butoane 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 D2 citeste senzorii de temperatura DS18B20 din fiecare bazin si din incinta
// emisia se relizeaza in functia StareCiclu  la o secundă si in functia Scrie_Citeste_EEPROM
// iar receptia 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 umplere bazin 2 si evacuarea exterioara evacuarea 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 2 // 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
int8_t 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
int8_t subMeniuAERARE = -1;
int8_t subMeniuEVACUARE = -1;
int8_t subMeniuRECIRCULARE = -1;
int8_t subMeniuFLOCULANT = -1;
int8_t subMeniuRESET_FABRICA = -1;
int8_t subMeniuBazin_1_AERARE = -1;
int8_t 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
//    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

// };

// ATENTIE ! - sa nu se schimbe pozitia variabilelor in "struct POMPE" pentru a functiona impachetarea
// Variabile pompe
// ATENTIE ! - sa nu se schimbe pozitia variabilelor in "struct POMPE" pentru a functiona impachetarea
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
   byte  Re_set               = 0;   // 0 - se reseteaza master pt. alarme
                                     // 1 - master transmite ca este setat 
                                     // 2 - slave transmite ca a modificat setarile
                                     // 3 - master si slave au fost initializate si nu se mai transmite
};

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
  char Line0[21];  // Aceasta structura va fi transmisa wireles
  char Line1[21];  // catre controlerul SLAVE prin HC-12 433 MHz
  char Line2[21];  // pt afisare pe SLAVE in inmp real
  char Line3[21];  // transmiterea datelor se efectueaza in functia StareCiclu
  float Temperatura[5] = {0, 0, 0, 0, 0}; // stocheaza temperatura din Bazin 0, Bazin 1, Bazin 2, incapere, exterior
  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
} LCD; 

int8_t 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


//byte Reset = 0;// variabila transmisa de Mcu slave pentru resetare alarme

/******************** FUNCTIE RESETARE SOFTWARE PLACA  *******************/
// resetare arduino.
// Trebuie scrisa inainte functiei loop().
// resetFunc() este chemata cand este nevoie.
inline void(* resetFunc) (void) = 0;

/************************************************************************/


/************************ 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
// static byte tmp =0;
//     if (Meniu > 0) tmp ++;
//     if (tmp >2) return;
    ///////////////////////////////////////// Send buffer
    switch (tip)
    {
      case 1:
          HC12_Transfer_TX_LCD.sendData();// este folosit in functia StareCiclu
          //delay(20);
      break;
      case 2:
          HC12_Transfer_TX_POMPA_Set.sendData();// este folosit in functia Scrie_Citeste_EEPROM
                                                // cand se seteaza master pt a transmite la slave
          //delay(100);
          break;
    }

  }// end TX_HC12

inline void rx_HC12 () // receptionare date
  {
    if (Meniu > 0) return; 
    // use this variable to keep track of how many
    // bytes we've processed from the receive buffer
    if (HC12_Transfer_RX_POMPA_Set.receiveData())
      {
        //if (Reset = 255) {resetFunc();}
        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

    bool tmp = false;
    static bool stare_Alarma = false;

    for (uint8_t i = 0; i <= 5; i++) { if (LCD.Alarma[i] > 0) tmp = true; }
    if (!tmp) {pcf8575.digitalWrite( 8, HIGH); return(vacanta == 1 ? F("STARE ") : F("VEGHE "));}
    else if (tmp  && !stare_Alarma) {stare_Alarma = true; pcf8575.digitalWrite( 8, HIGH); return (vacanta == 1 ?  F("STARE ") : F("VEGHE "));}
    else if (tmp && stare_Alarma) {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 (int8_t& tipAlarma)
  {
    String tmp = "";
    switch (tipAlarma)
    {
      case 1: //PREA PLIN BAZIN 2
        tmp = F("(A1) ALARM PREAPLIN "); strcpy(LCD.Line0 , tmp.c_str());
        tmp = F(" Verifica evacuarea."); strcpy(LCD.Line1 , tmp.c_str());
        tmp = F("  Sau debit  peste  "); strcpy(LCD.Line2 , tmp.c_str());
        tmp = F("  100 litri / min.  "); strcpy(LCD.Line3 , tmp.c_str());
      break;
      case 2: //PREA PLIN BAZIN 2
        tmp = F("(A2) ALARM PREAPLIN "); strcpy(LCD.Line0 , tmp.c_str());
        tmp = F("Pompa Evac.P2.2 arsa"); strcpy(LCD.Line1 , tmp.c_str());
        tmp = F("sau plutitor prea - "); strcpy(LCD.Line2 , tmp.c_str());
        tmp = F("plin BAZIN 2 blocat."); strcpy(LCD.Line3 , tmp.c_str());
      break;
      case 3: //EVACUARE
        tmp = F("(A3) ALARM EVACUARE "); strcpy(LCD.Line0 , tmp.c_str());
        tmp = F("Pompa de evacuare in"); strcpy(LCD.Line1 , tmp.c_str());
        tmp = F("exterior P2.2 arsa. "); strcpy(LCD.Line2 , tmp.c_str());
        tmp = F("Senzor nivel blocat."); strcpy(LCD.Line3 , tmp.c_str());         
      break;
      case 4: //EVACUARE
        tmp = F("(A4)ALARM UMPLERE B2"); strcpy(LCD.Line0 , tmp.c_str());
        tmp = F("Senzorii de nivel   "); strcpy(LCD.Line1 , tmp.c_str());
        tmp = F("defecti sau murdari/"); strcpy(LCD.Line2 , tmp.c_str());
        tmp = F("P1.2 umplere B2 arsa"); strcpy(LCD.Line3 , tmp.c_str());
      break;
      case 5: //EVACUARE
        tmp = F("(A5) ALARM EVACUARE "); strcpy(LCD.Line0 , tmp.c_str());
        tmp = F("      ATENTIE !     "); strcpy(LCD.Line1 , tmp.c_str());
        tmp = F("Pompa de evacuare in"); strcpy(LCD.Line2 , tmp.c_str());
        tmp = F("exterior P2.2 arsa. "); strcpy(LCD.Line3 , tmp.c_str());         
      break;
      case 6: //PREA GOL
        tmp = F("(A6) ALARM PREA-GOL "); strcpy(LCD.Line0 , tmp.c_str());
        tmp = F("     ATENTIE !      "); strcpy(LCD.Line1 , tmp.c_str());
        tmp = F(" NIVELUL APEI  ESTE "); strcpy(LCD.Line2 , tmp.c_str());
        tmp = 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) return;
  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 >>");
      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); 
      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);
      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);
      strcpy(LCD.Line3, tmp.c_str());
    break;
    case 2: //RECIRCULARE
      //if ( alarma ) break;
      tmp += F("<< RECIRCUL >>");
      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);
      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);
      strcpy(LCD.Line2, tmp.c_str());
      tmp = F("  --------- ---- ---");
      strcpy(LCD.Line3, tmp.c_str());
    break;
    case 3: //AERARE
      //if ( alarma ) break;
      tmp += F("<<  AERARE  >>");
      strcpy(LCD.Line0 , tmp.c_str());

      tmp = F("    Bazin 1  Bazin 2");
      strcpy(LCD.Line1 , tmp.c_str());

      tmp = F("AER ");
      tmp += String(AerareB1.OP) + SPATII_4;
      tmp = (tmp.substring(0,8) + SEC + SPATII_2 );
      strcpy(LCD.Line2 , tmp.c_str());
      tmp = String(AerareB2.OP) + SPATII_4;
      tmp = tmp.substring(0,4) + SEC;
      strcat(LCD.Line2 , tmp.c_str());

      tmp = F("LIN ");
      tmp += String(AerareB1.CL) + SPATII_4;
      tmp = (tmp.substring(0,8) + SEC + SPATII_2);
      strcpy(LCD.Line3 , tmp.c_str());
      tmp = String(AerareB2.CL) + SPATII_4;
      tmp = (tmp.substring(0,4) + SEC);
      strcat(LCD.Line3 , tmp.c_str());

    break;
    case 4: // ALARME
      Alarme (alarma);
    break;
    case 5: // MESAJ NUMAI PENTRU Mcu SLAVE
      tmp = F("     ATENTIE !      "); strcpy(LCD.Line0 , tmp.c_str());
      tmp = F(" MCU MASTER SE AFLA "); strcpy(LCD.Line1 , tmp.c_str());
      tmp = F("  IN MENIUL SETUP   "); strcpy(LCD.Line2 , tmp.c_str());
      //tmp = F("NU RESETATI ALARMELE"); strcpy(LCD.Line3 , tmp.c_str());
      tmp = F("NU UMBLATI LA SETARI"); strcpy(LCD.Line3 , tmp.c_str());
      // tx_HC12 (1); // transmitere date LCD
      // return;         
    break;

  }
    tx_HC12 (1); // transmitere date LCD
    //delay(50);
    //Serial.println((char*)LCD.Line0);
    if (Meniu == 0 || etapa == 5) return;
    lcd.setCursor (0,0); lcd.print((char*)LCD.Line0);
    lcd.setCursor (0,1); lcd.print((char*)LCD.Line1);
    lcd.setCursor (0,2); lcd.print((char*)LCD.Line2);
    lcd.setCursor (0,3); lcd.print((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) 
    {
      // restabilesc starea dinainte de prea gol
      alarma = tmp_ALARMA;
      // pornim pompele corespunzatoare etapei intrerupte de prea plin fara reluarea umplerii
      if((Evacuare.SS == true ) && (Evacuare.CL == 0) && (Evacuare.OP != 0)) pcf8575.digitalWrite( 4, LOW);// reia 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
    }
  else if (alarma == 6) {StareCiclu (4); 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(); return;} // 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


/************************ 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

  lcd.begin(20, 4); //initialize the lcd

  // 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(POMPA_Set), &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();

  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 P07 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 - plutitori legati 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 prima scriere 
                          // a 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 ();      
    }
  Defilare_Meniu_Setup();  // intra in meniul SETUP cand buttonSETUP este apasata 
  
  Info_Help();//intra in info sau help cand este apasat butonul - sau +
  
  temperatureSensors.update(); // este chemata functia pt citirea temperaturilor
  
  rx_HC12 (); // receptionare date POMPA_Set

}//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

      {
        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);EEPROM.get(EE_Address, POMPA_Set);}// 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);
              tx_HC12 (2); // transmitere date PMPA_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;
          }
      }
  }// 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, String meniu_1 = "", String meniu_2 = "", String meniu_3 = "",
                     int val_1 = -1, int val_2 = -1, int val_3 = -1, 
                     String UM_1 = "", String UM_2 = "", String UM_3 = "" )
 {
    static unsigned long delayNoBloking = millis();
    int max_nrChar = 0;// nr. maxim de caracte dintr-un meniu afisat
    String PU  = F("<    >");
    String PUM = F(">> ");
    String SP2 = F("  ");
    String SP3 = F("   ");
    
    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 = PUM + meniu_1; meniu_2 = SP2 + meniu_2 ; meniu_3 = SP2 + meniu_3 ; break;
        case 2: meniu_1 = SP2 + meniu_1 ; meniu_2 = PUM + meniu_2; meniu_3 = SP2 + meniu_3 ; break;
        case 3: meniu_1 = SP2 + meniu_1 ; meniu_2 = SP2 + meniu_2 ; meniu_3 = PUM + 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    
    if      (val_1 != -1 && sel == 1) { lcd.setCursor(max_nrChar, sel); lcd.print(SP3);}// afiseaza 3 spatii si creaza efectul de clipire citire date
    else if (val_2 != -1 && sel == 2) { lcd.setCursor(max_nrChar, sel); lcd.print(SP3);}// afiseaza 3 spatii si creaza efectul de clipire citire date
    else if (val_3 != -1 && sel == 3) { lcd.setCursor(max_nrChar, sel); lcd.print(SP3);}// afiseaza 3 spatii si creaza efectul de clipire citire date
    else if (subMeniuRESET_FABRICA == 1) { lcd.setCursor(3, 2 ); lcd.print(PU);}
    else if (subMeniuRESET_FABRICA == 2) { lcd.setCursor(11, 2); lcd.print(PU);}
    else    { lcd.setCursor(0, sel); lcd.print(SP2); }//afiseaza 2 spatii si creaza efectul de clipire meniu             
    delay(150);// intarzierea este obligatorie 
 }

    /***************** 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()
  {

    static int8_t info_help = 0;// var. pt afisare info despre temperatura si alarme sau help afisand textul alarmei
    
    byte tmp = 0;
    bool timp_help = false;
    bool timp_info = false;
        
    if (Meniu > 0) return;

    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; timp_info = false;}// 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++)//aici scriu A(1) ... A(6)
              {
                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);// aici scriu B0 ... B2
                  }
                 
                else tmp = 11;
                if (LCD.Temperatura[i-1] > 0)// aici scriu temperaturile cu semn - 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 ... 5
            if (!timp_help) { info_help ++; }
            break;
      case 6: // alarma 6
            if (!timp_help) { info_help = 1; }
            break;
    }
    if (info_help >= 1)
      {
        Alarme (info_help);
        lcd.setCursor (0,0); lcd.print((char*)LCD.Line0);
        lcd.setCursor (0,1); lcd.print((char*)LCD.Line1);
        lcd.setCursor (0,2); lcd.print((char*)LCD.Line2);
        lcd.setCursor (0,3); lcd.print((char*)LCD.Line3);
      }
  }// end Info_Help
pcf8575Breakout
. . . . . . 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
TEMPERATURA BAZINE
- Pompele sun actionate de module start-soft - Ledurile care reprezintă pompele în fapt sunt relee care actioneaza modulele start-soft. - Mini Pompele peristaltice pentru alimentare cu floculant sunt alimentate în fapt la 12Vcc. - Ledul de la electrovana în fapt reprezinta releul care actioneaza elecrovana cu 3 cai
MOD DE UTILIZARE - Prin apasarea butonului SETUP mai mult de o secunda se intra in meniul setup sau in sub meniuri - Prin apasarea butoanelor Timp- si Timp+ se ajusteza timpii in submeniuri - Prin apasarea butonului Timp- mai mult de o secunda se afiseaza succesiv informatii despre temperatura si numarul de apariții al alarmelor - Prin apasarea butonului Timp+ mai mult de o secunda se afiseaza succesiv continutul alarmelor - cauza care a generat alama
- Indentificarea senzorilor se va face înainte de intoducerea in bazine = B0, B1 și B2 reprezinta bazinele în care sunt introduși senzorii - int reprezinta senzorul din interiorul incaperii in care se afla montate bazinele - ext reprezinta senzorul aflat in exteriorul incaperii
CONTROLER MASTER STATIE DE EPURARE HOME MADE RELIZATA DIN REZERVOARE IBC NOTA : - Acest controler gestioneaza statia si transmite date către slave . . . . . . .- Modulul HC-12 de comunicare wireles nu este reprezentat in aceasta schema