//Copyright (c) 2024 Duțoiu Nicolae

// Mcu SLAVE

// 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 butoane se utilizeza CI MAX6817
// Transmisia wireles este programata direct in IDE pt asigurare comunicatie Master - Slave
// 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 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_I2C.h>
#include <EEPROM.h>
#include <EasyTransfer.h>//transmite pe hardware serial o structura de maxim 255 octeti

LiquidCrystal_I2C lcd(0x27, 20, 4); // I2C address 0x27, 20 column and 4 rows
                                    // adresa este pt a functiona in wokwi,
                                    // alfel trebuie setata pe afisaj
// Transfer Serial date
EasyTransfer HC12_Transfer_TX_POMPA_Set;

EasyTransfer HC12_Transfer_RX_LCD;
EasyTransfer HC12_Transfer_RX_POMPA_Set;


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


// 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] ="bbvfrdscc";  // 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; 


//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 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 :
//        - POMPA_Set
// se receptioneaza variabilla :
//        - POMPA_Set
//        - structura LCD20x4

inline void tx_HC12 () // transmitere date
  {
    // EasyTRansfer poate trimite o singura structura de maxim 255 octeti
    // tip 1 - transmite struct LCD
    // tip 2 - transmite POMPA_Set
    ///////////////////////////////////////// Send buffer
    HC12_Transfer_TX_POMPA_Set.sendData();// este folosit in functia Scrie_Citeste_EEPROM
                                          // cand se seteaza slave pt a transmite la master
  }// end TX_HC12

inline void rx_HC12 () // receptionare date
  {
    if (Meniu > -1) return; 
    // use this variable to keep track of how many
    // bytes we've processed from the receive buffer
    if (HC12_Transfer_RX_LCD.receiveData())
      {
        StareCiclu ();
      }
    if (HC12_Transfer_RX_POMPA_Set.receiveData())
      {
        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
      }
delay(100);
  } // end RX_HC12


/*********************** FUNCTII PENTRU AFISARE *********************************/


/******************* FUNCTIE ALARME *************************/
// acesta functie scrie variabila LCD cu textul necesar afisarii alarmelor
// 

void Alarme (char& tipAlarma)
  {
    String tmp = "";
    switch (tipAlarma)
    {
      case 1: //PREA PLIN BAZIN 2
        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 datele receptionate de la master

void StareCiclu ()
{
    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 StareCiclu


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

void setup() 
{
  Serial.begin(9600);//initialize the serial

  lcd.init(); //initialize the lcd
  lcd.backlight(); //open the backlight
  
  // transfer date wireles HC12
  HC12_Transfer_TX_POMPA_Set.begin(details(POMPA_Set), &Serial); // transmitere catre master date wireles prin portul fizic UART 
  
  HC12_Transfer_RX_LCD.begin(details(LCD), &Serial); // receptionare de la master date wireles prin portul fizic UART 
  HC12_Transfer_RX_POMPA_Set.begin(details(POMPA_Set), &Serial); // receptionare de la master date wireles prin portul fizic UART 
  

  // initializare pin buzzer
  pinMode(PIN_BUZZER, OUTPUT);// se foloseste pentru dispozitivul SLAVE
  digitalWrite(PIN_BUZZER, LOW);

 // initializare pini butoane
  pinMode(PIN_BUTON_SETUP, INPUT_PULLUP);
  pinMode(PIN_BUTON_TIMP_MINUS, INPUT_PULLUP);
  pinMode(PIN_BUTON_TIMP_PLUS, INPUT_PULLUP);

  Scrie_Citeste_EEPROM(0);// aici trebuie sa fie apelata pt a fi 
                          // stocate valorile de initializare
                          // a variabilelor la prima scriere 
                          // a programului pe Mcu

  StareCiclu ();
}// end setup()


void loop() 
{
  Defilare_Meniu_Setup();  // intra in meniul SETUP cand buttonSETUP este apasata 

  Info_Help();//intra in info sau help cand este apasat butonul - sau +

  rx_HC12 (); // receptionare date POMPA_Set

}//end 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_Set);}// prima rulare a programului
              else 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_Set);} 
              // break;
            case 2: // meniul Setup - se va stoca la fiecare SAVE & EXIT din submeniuri
              EEPROM.put(0, 0x40); EEPROM.put(EE_Address, POMPA_Set);
              break;
            case 3: // se va citi continutul memoriei pentru reinitializare variabile în setare timp pompe
              EEPROM.get(EE_Address, POMPA_Set); 
              break;
            case 4: // scrie primul octet 0xFF adica 1111 1111 sau 255 dec, pentru resetare fabrica se foloseste in functia Defilare_Meniu_Setup
              EEPROM.put(0, 0xFF); 
              break;
          }
      }
  }// 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 () 
  {
    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");

    //Scrie_Citeste_EEPROM(3);

    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_Set.Bazin_1_Aerare, POMPA_Set.Bazin_1_Linistire/60, -1, SEC, MIN ); }
            //LINISTIRE                                  
            else if (subMeniuBazin_1_AERARE == 2) {Blink_Meniu ( 2, AERARE, LINISTIRE, SAVE_EXIT,POMPA_Set.Bazin_1_Aerare, POMPA_Set.Bazin_1_Linistire/60, -1, SEC, MIN ); }
            //SAVE & EXIT                                  
            else if (subMeniuBazin_1_AERARE == 3) {Blink_Meniu ( 3, AERARE, LINISTIRE, SAVE_EXIT,POMPA_Set.Bazin_1_Aerare, POMPA_Set.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_Set.Bazin_1_Aerare, POMPA_Set.Bazin_1_Linistire/60, -1, SEC, MIN ); }
            //LINISTIRE                                  
            else if (subMeniuBazin_2_AERARE == 2) {Blink_Meniu ( 2, AERARE, LINISTIRE, SAVE_EXIT,POMPA_Set.Bazin_1_Aerare, POMPA_Set.Bazin_1_Linistire/60, -1, SEC, MIN ); }
            //SAVE & EXIT                                  
            else if (subMeniuBazin_2_AERARE == 3) {Blink_Meniu ( 3, AERARE, LINISTIRE, SAVE_EXIT,POMPA_Set.Bazin_1_Aerare, POMPA_Set.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_Set.PornireEvacuare, POMPA_Set.LinistireEvacuare/60, -1, SEC, MIN );
        //LINISTIRE
        else if (subMeniuEVACUARE == 2) Blink_Meniu ( 2, EVACUARE, LINISTIRE, SAVE_EXIT, POMPA_Set.PornireEvacuare, POMPA_Set.LinistireEvacuare/60, -1, SEC, MIN );
        //SAVE & EXIT
        else if (subMeniuEVACUARE == 3) Blink_Meniu ( 3, EVACUARE, LINISTIRE, SAVE_EXIT, POMPA_Set.PornireEvacuare, POMPA_Set.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_Set.PornireRecirculare, POMPA_Set.AsteptareRecirculare, -1, SEC , ORE ); 
        //ASTEPTARE
        else if (subMeniuRECIRCULARE == 2) Blink_Meniu ( 2, PORNIRE, ASTEPTARE , SAVE_EXIT, POMPA_Set.PornireRecirculare, POMPA_Set.AsteptareRecirculare, -1, SEC , ORE );
        // SAVE & EXIT
        else if (subMeniuRECIRCULARE == 3) Blink_Meniu ( 3, PORNIRE, ASTEPTARE , SAVE_EXIT, POMPA_Set.PornireRecirculare, POMPA_Set.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_Set.PompaPeristaltica_B1, POMPA_Set.PompaPeristaltica_B2, -1, ML, ML); 
        //DOZAJ BAZIN 2
        else if (subMeniuFLOCULANT == 2) Blink_Meniu ( 2, DOZAJ_BAZIN_1, DOZAJ_BAZIN_2 , SAVE_EXIT, POMPA_Set.PompaPeristaltica_B1, POMPA_Set.PompaPeristaltica_B2, -1, ML, ML);
        //SAVE & EXIT
        else if (subMeniuFLOCULANT == 3) Blink_Meniu ( 3, DOZAJ_BAZIN_1, DOZAJ_BAZIN_2 , SAVE_EXIT, POMPA_Set.PompaPeristaltica_B1, POMPA_Set.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 >") ); 
      }

  }// 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; tx_HC12();}

    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 char 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;
    //Meniu = -1;
//Serial.println((Meniu));        
    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; lcd.clear(); 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; lcd.clear(); 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
  /******************************************************************************************/
ALARMA
CONTROLER SLAVE STATIE DE EPURARE HOME MADE RELIZATA DIN REZERVOARE IBC NOTA : - Acest controler primeste date de la master si le afiseaza in casa . . . . . . .- Modulul HC-12 de comunicare wireles nu este reprezentat in aceasta schema
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