// připojení potřebných knihoven
  #include <NewPing.h>    // knihovna pro práci s ultrazvukovým senzorem HY-SRF05
  #include <DHT.h>    // knihovna pro práci se senzorem teploty a vlhkosti DHT22
  #include <Wire.h>    // knihovna umožňující komunikaci se zařízeními I2C
  #include <LiquidCrystal_I2C.h>    // knihovna pro práci s LCD displejem 16x2 přes I2C sběrnici

// definice konstant pro jednotlivá tlačítka
  #define FILLING_BUTTON 2    // definování pinu pro tlačítko ruční doplňování
  #define INH_CAPACITIVE_BUTTON 22    // definování pinu pro tlačítko inhibice kapacitních senzorů
  #define INH_FLOAT_BUTTON 24    // definování pinu pro tlačítko inhibice plovákových senzorů
  #define INH_ULTRASONIC_BUTTON 26    // definování pinu pro tlačítko inhibice ultrazvukového senzoru
  #define FAULT_CAPPACITIVE_BUTTON 28    // definování pinu pro tlačítko simulování poruchy kapacitních senzorů
  #define FAULT_FLOAT_BUTTON 30    // definování pinu pro tlačítko simulování poruchy plovákových senzorů
  #define FAULT_ULTRASONIC_BUTTON 34    // definování pinu pro tlačítko simulování poruchy ultrazvukového senzoru
  #define INFORMATIONS_BUTTON 36    // definování pinu pro tlačítko informace
  
// deklarace konstantních proměnných pro jednotlivé LEDky tlačítek
  #define FILLING_LED 3    // definování pinu pro LED tlačítka ruční doplňování
  #define INH_CAPPACITIVE_LED 23    // definování pinu pro LED tlačítka inhibice kapacitních senzorů
  #define INH_FLOAT_LED 25    // definování pinu pro LED tlačítka inhibice plovákových senzorů
  #define INH_ULTRASONIC_LED 27    // definování pinu pro LED tlačítka inhibice ultrazvukového senzoru
  #define FAULT_CAPPACITIVE_LED 29    // definování pinu pro LED tlačítka simulování poruchy kapacitních senzorů
  #define FAULT_FLOAT_LED 31    // definování pinu pro LED tlačítka simulování poruchy plovákových senzorů
  #define FAULT_ULTRASONIC_LED 35    // definování pinu pro LED tlačítka simulování poruchy ultrazvukového senzoru
  #define INFORMATIONS_LED 37    // definování pinu pro LED tlačítka informace

// deklarace konstantních proměnných pro jednotlivé senzory
  #define TRIG 40    // definování pinu pro trig pin ultrazvukového senzoru HY-SRF05
  #define ECHO 41    // definování pinu pro echo pin ultrazvukového senzoru HY-SRF05
  #define CAPPACITIVE_MAX 42    // definování datového pinu vyhodnocení horní meze hladiny kapacitního senzoru XKC-Y25-V 
  #define CAPPACITIVE_MIN 43    // definování datového pinu vyhodnocení dolní meze hladiny kapacitního senzoru XKC-Y25-V 
  #define FLOAT_MAX 44    // definování datového pinu vyhodnocení horní meze hladiny plovákového senzoru ECLIPSERA
  #define FLOAT_MIN 45    // definování datového pinu vyhodnocení dolní meze hladiny plovákového senzoru ECLIPSERA
  #define DHT_DATA 46    // definování datového pinu senzoru teploty a vlhkosti DHT22
  
// deklarace konstantní proměnné pro relé
  #define RELAY 50    // definování pinu pro impuls na sepnutí či rozepnutí relé spínajícího čerpadlo

// vytvoření objektů
  NewPing hy_srf05(TRIG, ECHO, 350);    // vytvoření objektu ultrazvukového senzoru
  LiquidCrystal_I2C lcd(0x27,16,2);    // vytvoření objektu LCD displeje
  DHT dht_22(DHT_DATA, DHT22);    // vytvoření objektu senzoru teploty a vlhkosti

// deklarace proměnných pro detekci změny stavu tlačítek
  bool filling_button_state = false;    // aktuální stav tlačítka ruční doplňování
  bool filling_button_last_state = false;    // stav tlačítka ruční doplňování v předchozím průběhu programem
  bool inh_cappacitive_button_state = false;    // aktuální stav tlačítka inhibice kapacitních senzorů
  bool inh_cappacitive_button_last_state = false;    // stav tlačítka inhibice kapacitních senzorů v předchozím průběhu programem
  unsigned int inh_cappacitive_button_push_count = 0;    // počet stisků tlačítka inhibice kapacitních senzorů
  bool inh_float_button_state = false;    // aktuální stav tlačítka inhibice plovákových senzorů
  bool inh_float_button_last_state = false;    // stav tlačítka inhibice plovákových senzorů v předchozím průběhu programem
  unsigned int inh_float_button_push_count = 0;    // počet stisků tlačítka inhibice plovákových senzorů
  bool inh_ultrasonic_button_state = false;    // aktuální stav tlačítka inhibice ultrazvukového senzoru
  bool inh_ultrasonic_button_last_state = false;    // stav tlačítka inhibice ultrazvukového senzoru v předchozím průběhu programem
  unsigned int inh_ultrasonic_button_push_count = 0;    // počet stisků tlačítka inhibice ultrazvukového senzoru
  bool fault_cappacitive_button_state = false;    // aktuální stav tlačítka simulování poruchy kapacitních senzorů
  bool fault_cappacitive_button_last_state = false;    // stav tlačítka simulování poruchy kapacitních senzorů v předchozím průběhu programem
  unsigned int fault_cappacitive_button_push_count = 0;    // počet stisků tlačítka simulování poruchy kapacitních senzorů
  bool fault_float_button_state = false;    // aktuální stav tlačítka simulování poruchy plovákových senzorů
  bool fault_float_button_last_state = false;    // stav tlačítka simulování poruchy plovákových senzorů v předchozím průběhu programem
  unsigned int fault_float_button_push_count = 0;    // počet stisků tlačítka simulování poruchy plovákových senzorů
  bool fault_ultrasonic_button_state = false;    // aktuální stav tlačítka simulování poruchy ultrazvukového senzoru
  bool fault_ultrasonic_button_last_state = false;    // stav tlačítka simulování poruchy ultrazvukového senzoru v předchozím průběhu programem
  unsigned int fault_ultrasonic_button_push_count = 0;    // počet stisků tlačítka simulování poruchy ultrazvukového senzoru
  bool informations_button_state = false;    // aktuální stav tlačítka informace
  bool informations_button_last_state = false;    // stav tlačítka informace v předchozím průběhu programem
  unsigned int informations_button_push_count = 0;    // počet stisků tlačítka informace

// deklarace proměnných pro vyhodnocení mezních stavů hladiny
  bool cappacitive_max_state = false;    // vyhodnocení horní meze hladiny vody kapacitním senzorem
  bool cappacitive_min_state = true;    // vyhodnocení dolní meze hladiny vody kapacitním senzorem
  bool float_max_state = false;    // vyhodnocení horní meze hladiny vody plovákovým senzorem
  bool float_min_state = true;    // vyhodnocení dolní meze hladiny vody plovákovým senzorem

// deklarace proměných pro vyhodnocení výběru ze snímačů k sepnutí relé pro doplnění vody v nádobě
  bool notice_inhibition = false;    // chybové hlášení při pokusu přidat do inhibice tři senzory současně
  bool notice_fault = false;    // chybové hlášení při pokusu simulovat více než jednu poruchu současně
  byte selection_max = 0;    // počet senzorů aktuálně vyhodnocujících horní mez hladiny vody
  byte selection_min = 0;    // počet senzorů aktuálně vyhodnocujících dolní mez hladiny vody
  byte selection_set = 0;    // nastavení výběru senzorů pro sepnutí či rozepnutí relé pro doplňovací čerpadlo na základě aktuálního nastavení inhibicí senzorů
  byte timer = 0;    // pomocná proměnná pro časování zobrazení chybové zprávy o překroření počtu inhibicí a simulácí poruch na LCD displeji
  String selection = "2/3";    // pomocná proměnná pro zobrazení aktuálního výběru ze senzorů na LCD displeji

// deklarace proměnných pro inhibici a simulaci poruch senzorů
  bool inhibition_cappacitive = false;    // inhibice kapacitních senzorů
  bool inhibition_float = false;    // inhibice plovákových senzorů
  bool inhibition_ultrasonic = false;    // inhibice ultrazvukového senzoru
  bool fault_cappacitive = false;    // simulace poruchy kapacitních senzorů
  bool fault_float = false;    // simulace poruchy plovákových senzorů
  bool fault_ultrasonic = false;    // simulace poruchy ultrazvukového senzoru

// deklarace polí s informací pro rozsvěcení jednotlivých pixelů segmentů displeje
  byte char_y_with_comma[8] = {    // znak "ý"       
      B00010,          
      B00100,           
      B10001,           
      B10001,           
      B01111,           
      B00001,           
      B01110,           
      B00000, };
  byte char_e_with_hook[8] = {    // znak "ě"         
      B01010,          
      B00100,           
      B01110,           
      B10001,           
      B11111,         
      B10000,           
      B01110,           
      B00000, };
  byte char_degree[8] = {    // znak "°"          
      B00010,         
      B00101,           
      B00010,           
      B00000,           
      B00000,         
      B00000,           
      B00000,           
      B00000, };
  byte char_ultrasonic[8] = {    // symbol reprezentující ultrazvukový senzor         
      B10001,          
      B01010,           
      B00100,           
      B00000,           
      B10001,         
      B01010,           
      B00100,           
      B00000, };
  byte char_cappacitive_empty[8] = {    // symbol reprezentující kapacitní senzor v nesepnutém stavu        
      B00000,               
      B00100,           
      B01010,           
      B10001,           
      B10001,         
      B01010,           
      B00100,           
      B00000, };
  byte char_cappacitive_full[8] = {    // symbol reprezentující kapacitní senzor v sepnutém stavu          
      B00000,          
      B00100,           
      B01110,           
      B11111,           
      B11111,         
      B01110,           
      B00100,           
      B00000, };
  byte char_float_empty[8] = {    // symbol reprezentující plovákový senzor v nesepnutém stavu         
      B00100,               
      B01010,           
      B01010,           
      B01010,           
      B01010,         
      B10001,           
      B10001,           
      B01110, };
  byte char_float_full[8] = {    // symbol reprezentující plovákový senzor v sepnutém stavu            
      B00100,       
      B01110,           
      B01110,           
      B01110,           
      B01110,         
      B11111,           
      B11111,           
      B01110, };

// deklarace dalších pomocných proměnných
  unsigned long cur_time = 0;    // časování čtení výstupů ze senzorů a zápisu na LCD displej
  float temperature = 20;    // informace o teplotě ze senzoru DHT22
  float humidity = 70;    // informace o vlhkosti ze senzoru DHT22
  float distance_per_second = 0;    // vypočítaná uražená vzdálenost impulzu za jednotku času z ultrazvukového senzoru HY-SRF05 v závislosti na okolní teplotě
  float duration = 0;    // změřená doba šíření impulzu z ultrazvukového senzoru HY-SRF05 od senzoru ke hladině a zpět
  float distance = 0;    // vypočítaná uražená vzdálenost impulzu z ultrazvukového senzoru HY-SRF05 v centimetrech
  float water_level = 0;    // přepočet na výšku hladiny v centimetrech
  byte brightness = 0;    // jas tlačítka ruční doplňování
  byte fade_amount = 5;    // změna jasu tlačítka ruční doplňování

  
// přiřazení IO funkce pinům, nastavení pro první průchod programem
  void setup() {
    // nastavení IO funkce pinů
      pinMode(TRIG, OUTPUT);    // nastavení pinu trig jako výstup
      pinMode(ECHO, INPUT);    // nastavení pinu echo jak vstup
      pinMode(CAPPACITIVE_MAX, INPUT);    // nastavení pinu horní meze kapacitního senzoru jako vstup
      pinMode(CAPPACITIVE_MIN, INPUT);    // nastavení pinu dolní meze kapacitního senzoru jako vstup
      pinMode(FLOAT_MAX, INPUT);    // nastavení pinu horní meze plovákového senzoru jako vstup
      pinMode(FLOAT_MIN, INPUT);    // nastavení pinu dolní meze plovákového senzoru jako vstup
      pinMode(RELAY, OUTPUT);    // nastavení pinu relé jako výstup
      pinMode(FILLING_BUTTON, INPUT);    // nastavení pinu tlačítka ruční doplňování jako vstup
      pinMode(INH_CAPACITIVE_BUTTON, INPUT);    // nastavení pinu tlačítka inhibice kapacitních senzorů jako vstup
      pinMode(INH_FLOAT_BUTTON, INPUT);    // nastavení pinu tlačítka inhibice plovákových senzorů jako vstup
      pinMode(INH_ULTRASONIC_BUTTON, INPUT);    // nastavení pinu tlačítka inhibice ultrazvukového senzoru jako vstup
      pinMode(FAULT_CAPPACITIVE_BUTTON, INPUT);    // nastavení pinu tlačítka simulace poruchy kapacitních senzorů jako vstup
      pinMode(FAULT_FLOAT_BUTTON, INPUT);    // nastavení pinu tlačítka simulace poruchy plovákových senzorů jako vstup
      pinMode(FAULT_ULTRASONIC_BUTTON, INPUT);    // nastavení pinu tlačítka simulace poruchy ultrazvukového senzoru jako vstup
      pinMode(INFORMATIONS_BUTTON, INPUT);    // nastavení pinu tlačítka informace jako vstup
      pinMode(FILLING_LED, OUTPUT);    // nastavení pinu LED tlačítka ruční doplňování jako výstup
      pinMode(INH_CAPPACITIVE_LED, OUTPUT);    // nastavení pinu LED tlačítka inhibice kapacitních senzorů jako výstup
      pinMode(INH_FLOAT_LED, OUTPUT);    // nastavení pinu LED tlačítka inhibice plovákových senzorů jako výstup
      pinMode(INH_ULTRASONIC_LED, OUTPUT);    // nastavení pinu LED tlačítka inhibice ultrazvukového senzoru jako výstup
      pinMode(FAULT_CAPPACITIVE_LED, OUTPUT);    // nastavení pinu LED tlačítka simulace poruchy kapacitních senzorů jako výstup
      pinMode(FAULT_FLOAT_LED, OUTPUT);    // nastavení pinu LED tlačítka simulace poruchy plovákových senzorů jako výstup
      pinMode(FAULT_ULTRASONIC_LED, OUTPUT);    // nastavení pinu LED tlačítka simulace poruchy ultrazvukového senzoru jako výstup
      pinMode(INFORMATIONS_LED, OUTPUT);    // nastavení pinu LED tlačítka informace jako výstup

    // spuštění funkcí
      dht_22.begin();    // spuštění komunikace se senzorem teploty a vlhkosti DHT22

    // spuštění funkce a počáteční nastavení displeje
      lcd.init();    // inicializace LCD displeje 16x2
      lcd.backlight();    // zapnutí podsvícení LCD displeje
      lcd.clear();    // vyčištění případných zanechaných znaků na LCD displeji
      lcd.createChar(1, char_y_with_comma);    // vytvoření znaku "ý"
      lcd.createChar(2, char_e_with_hook);    // vytvoření znaku "ě"
      lcd.createChar(3, char_degree);    // vytvoření znaku "°"
      lcd.createChar(4, char_ultrasonic);    // vytvoření symbolu reprezentujícího ultrazvukový senzor  
      lcd.createChar(5, char_cappacitive_empty);    // vytvoření symbolu reprezentujícího kapacitní senzor v nesepnutém stavu 
      lcd.createChar(6, char_cappacitive_full);    // vytvoření symbolu reprezentujícího kapacitní senzor v sepnutém stavu
      lcd.createChar(7, char_float_empty);    // vytvoření symbolu reprezentujícího plovákový senzor v nesepnutém stavu
      lcd.createChar(8, char_float_full);    // vytvoření symbolu reprezentujícího plovákový senzor v sepnutém stavu
      lcd.setCursor(0,0);    // prvotní nastavení LCD displeje
      lcd.print("Hladina: 00.0 cm");    // prvotní nastavení LCD displeje
      lcd.setCursor(0,1);    // prvotní nastavení LCD displeje
      lcd.print("V");    // prvotní nastavení LCD displeje
      lcd.write(byte(1));    // prvotní nastavení LCD displeje    
      lcd.print("b");    // prvotní nastavení LCD displeje
      lcd.write(byte(2));    // prvotní nastavení LCD displeje
      lcd.print("r: 2/3");    // prvotní nastavení LCD displeje

    // prvotní zápis signálu na LED tlačítek inhibicí, poruch a informace
      digitalWrite(INH_CAPPACITIVE_LED, LOW);    // nastavení LED tlačítka inhibice kapacitních senzorů jako vypnuto
      digitalWrite(INH_FLOAT_LED, LOW);    // nastavení LED tlačítka inhibice plovákových senzorů jako vypnuto
      digitalWrite(INH_ULTRASONIC_LED, LOW);    // nastavení LED tlačítka inhibice ultrazvukového senzoru jako vypnuto
      digitalWrite(FAULT_CAPPACITIVE_LED, LOW);    // nastavení LED tlačítka simulace poruchy kapacitních senzorů jako vypnuto
      digitalWrite(FAULT_FLOAT_LED, LOW);    // nastavení LED tlačítka simulace poruchy plovákových senzorů jako vypnuto
      digitalWrite(FAULT_ULTRASONIC_LED, LOW);    // nastavení LED tlačítka simulace poruchy ultrazvukového senzoru jako vypnuto
      digitalWrite(INFORMATIONS_LED, HIGH);    // nastavení LED tlačítka informace jako zapnuto
  }


// hlavní smyčka programu
  void loop() {

    // uložení času v milisekundách do proměnné pro časově řízené odečítání hodnot ze senzorů
      cur_time = millis();

    // zjištění aktuálního stavu tlačítek
      filling_button_state = digitalRead(FILLING_BUTTON);
      inh_cappacitive_button_state = digitalRead(INH_CAPACITIVE_BUTTON);
      inh_float_button_state = digitalRead(INH_FLOAT_BUTTON);
      inh_ultrasonic_button_state = digitalRead(INH_ULTRASONIC_BUTTON);
      fault_cappacitive_button_state = digitalRead(FAULT_CAPPACITIVE_BUTTON);
      fault_float_button_state = digitalRead(FAULT_FLOAT_BUTTON);
      fault_ultrasonic_button_state = digitalRead(FAULT_ULTRASONIC_BUTTON);
      informations_button_state = digitalRead(INFORMATIONS_BUTTON);

    // inhibice kapacitních senzorů
      if (inh_cappacitive_button_state != inh_cappacitive_button_last_state)
          inhibition_cappacitive_sensors();

    // inhibice plovákových senzorů
      if (inh_float_button_state != inh_float_button_last_state)
          inhibition_float_sensors();

    // inhibice ultrazvukového senzoru
      if (inh_ultrasonic_button_state != inh_ultrasonic_button_last_state)
          inhibition_ultrasonic_sensor();

    // simulace poruchy kapacitních senzorů
      if (fault_cappacitive_button_state != fault_cappacitive_button_last_state)
          fault_cappacitive_sensors();

    // simulace poruchy plovákových senzorů
      if (fault_float_button_state != fault_float_button_last_state)
          fault_float_sensors();

    // simulace poruchy ultrazvukového senzoru
      if (fault_ultrasonic_button_state != fault_ultrasonic_button_last_state)
          fault_ultrasonic_sensor();

    // výstražná zpráva při pokusu inhibovat třetí senzor
      if (((cur_time % 1000) == 400) && (notice_inhibition == true))
          inhibition_warning_notice();

    // výstražná zpráva při pokusu simulovat více jak jednu poruchu senzoru
      if (((cur_time % 1000) == 400) && (notice_fault == true))
          fault_warning_notice();

    // odečet teploty a vlhkosti ze senzoru DHT22
      if ((cur_time % 500) == 0)
          temperature_and_humidity_read();

    // odečet vzdálenosti hladiny od ultrazvukového senzoru HY-SRF05 a následný přepočet na výšku hladiny
      if ((cur_time % 500) == 100)
          ultrasonic_sensor_read();

    // odečet mezních stavů minimální a maximální hladiny z kapacitních senzorů XKC-Y25-V
      if ((cur_time % 500) == 200)
          capacitive_sensors_read();

    // odečet mezních stavů minimální a maximální hladiny z plovákových senzorů ECLIPSERA
      if ((cur_time % 500) == 300)
          float_sensors_read();

    // součet výběrů ze senzorů pro maximální stav hladiny
      selection_max_count();

    // součet výběrů ze senzorů pro minimální stav hladiny
      selection_min_count();

    // zjištění počtu inhibicí pro vytvoření nastavení výběru
      selection_set_for_filling();

    // impuls pro sepnutí relé na doplňovací čerpadlo na základě splnění podmínky aktuálního výběru
      relay_impulse();

    // zjištění stavu tlačítka "doplňování" a impuls na relé spínající či rozpínající čerpadlo
      if (filling_button_state != filling_button_last_state)
          manual_filling();

    // PWM ovládání LED tlačítka "doplňování"
      if ((cur_time % 77) == 7)
          filling_button_lightning();

    // odečítání hodnot a ovládání LED tlačítka "informace"
      if (informations_button_state != informations_button_last_state)
          informations_switch();

    // smyčka zobrazovaných informací na LCD displeji
      if (((cur_time % 1000) == 400) && (notice_inhibition == false) && (notice_fault == false))
          lcd_write();
  } 

          
// inhibice kapacitních senzorů
  void inhibition_cappacitive_sensors() {
      if (inh_cappacitive_button_state == HIGH) {
          if ((inh_cappacitive_button_push_count % 2) == 0) {
              if ((inhibition_float == true) && (inhibition_ultrasonic == true))
                  notice_inhibition = true;
              else {
                  inhibition_cappacitive = true;
                  digitalWrite(INH_CAPPACITIVE_LED, HIGH);
                  inh_cappacitive_button_push_count++;
                  }
          }
          else {
              inhibition_cappacitive = false;
              digitalWrite(INH_CAPPACITIVE_LED, LOW);
              inh_cappacitive_button_push_count++;
          }
      }
      inh_cappacitive_button_last_state = inh_cappacitive_button_state;
  }

      
// inhibice plovákových senzorů
  void inhibition_float_sensors() {
      if (inh_float_button_state == HIGH) {
          if ((inh_float_button_push_count % 2) == 0) {
              if ((inhibition_cappacitive == true) && (inhibition_ultrasonic == true))
                  notice_inhibition = true;
              else {
                  inhibition_float = true;
                  digitalWrite(INH_FLOAT_LED, HIGH);
                  inh_float_button_push_count++;
                  }
          }
          else {
              inhibition_float = false;
              digitalWrite(INH_FLOAT_LED, LOW);
              inh_float_button_push_count++;
          }
      } 
      inh_float_button_last_state = inh_float_button_state;
  }


// inhibice ultrazvukového senzoru
  void inhibition_ultrasonic_sensor() {
      if (inh_ultrasonic_button_state == HIGH) {
          if ((inh_ultrasonic_button_push_count % 2) == 0) {
              if ((inhibition_cappacitive == true) && (inhibition_float == true))
                  notice_inhibition = true;
              else {
                  inhibition_ultrasonic = true;
                  digitalWrite(INH_ULTRASONIC_LED, HIGH);
                  inh_ultrasonic_button_push_count++;
              }
          }
          else {
              inhibition_ultrasonic = false;
              digitalWrite(INH_ULTRASONIC_LED, LOW);
              inh_ultrasonic_button_push_count++;
          }
      }      
      inh_ultrasonic_button_last_state = inh_ultrasonic_button_state;
  }


// simulace poruchy kapacitních senzorů
  void fault_cappacitive_sensors() {
      if (fault_cappacitive_button_state == HIGH) {
          if ((fault_cappacitive_button_push_count % 2) == 0) {
              if ((fault_float == true) || (fault_ultrasonic == true))
                  notice_fault = true;
              else {
                  fault_cappacitive = true;
                  digitalWrite(FAULT_CAPPACITIVE_LED, HIGH);
                  fault_cappacitive_button_push_count++;
              }
          }
          else {
              fault_cappacitive = false;
              digitalWrite(FAULT_CAPPACITIVE_LED, LOW);
              fault_cappacitive_button_push_count++;
          }
      }      
      fault_cappacitive_button_last_state = fault_cappacitive_button_state;
  }


// simulace poruchy plovákových senzorů
  void fault_float_sensors() {
      if (fault_float_button_state == HIGH) {
          if ((fault_float_button_push_count % 2) == 0) {
              if ((fault_cappacitive == true) || (fault_ultrasonic == true))
                  notice_fault = true;
              else {
                  fault_float = true;
                  digitalWrite(FAULT_FLOAT_LED, HIGH);
                  fault_float_button_push_count++;
              }
          }
          else {
              fault_float = false;
              digitalWrite(FAULT_FLOAT_LED, LOW);
              fault_float_button_push_count++;
          }
      }      
      fault_float_button_last_state = fault_float_button_state;
  }


// simulace poruchy ultrazvukového senzoru
  void fault_ultrasonic_sensor() {
      if (fault_ultrasonic_button_state == HIGH) {
          if ((fault_ultrasonic_button_push_count % 2) == 0) {
              if ((fault_cappacitive == true) || (fault_float == true))
                  notice_fault = true;
              else {
                  fault_ultrasonic = true;
                  digitalWrite(FAULT_ULTRASONIC_LED, HIGH);
                  fault_ultrasonic_button_push_count++;
              }
          }
          else {
              fault_ultrasonic = false;
              digitalWrite(FAULT_ULTRASONIC_LED, LOW);
              fault_ultrasonic_button_push_count++;
          }
      }
      fault_ultrasonic_button_last_state = fault_ultrasonic_button_state;
  }

  

// výstražná zpráva při pokusu inhibovat třetí senzor
  void inhibition_warning_notice() {
      timer++;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(" INHIBOVAT LZE");
      lcd.setCursor(0,1);
      lcd.print("POUZE 2 SENZORY!");
      if (timer == 4) {
          notice_inhibition = false;
          timer = 0;
      }
      delay(2);
  }

  
// výstražná zpráva při pokusu simulovat více jak jednu poruchu senzoru
  void fault_warning_notice() {
      timer++;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(" SIMULOVAT LZE");
      lcd.setCursor(0,1);
      lcd.print("POUZE 1 PORUCHU!");
      if (timer == 4) {
          notice_fault = false;
          timer = 0;
      }
          delay(2);
  }
      

// odečet teploty a vlhkosti ze senzoru DHT22
  void temperature_and_humidity_read() {
      temperature = dht_22.readTemperature();
      humidity = dht_22.readHumidity();
      if (isnan(temperature) || isnan(humidity)) {
        temperature = 20;
        humidity = 101;
      }
      delay(2);
  }


// odečet vzdálenosti hladiny od ultrazvukového senzoru HY-SRF05 a následný přepočet na výšku hladiny
  void ultrasonic_sensor_read() {
      if (fault_ultrasonic == false) {
          distance_per_second = (331.82 + (0.61 * temperature)) / 10000.0;
          duration = hy_srf05.ping_median(5);
          distance = ((duration / 2) * distance_per_second);
          water_level = 27.5 - distance;
          delay(2);
      }
      else {
          water_level = random(-5, 22);
      }
  }


// odečet mezních stavů minimální a maximální hladiny z kapacitních senzorů XKC-Y25-V
 void capacitive_sensors_read() {
      if (fault_cappacitive == false) {
          cappacitive_max_state = digitalRead(CAPPACITIVE_MAX);
          cappacitive_min_state = digitalRead(CAPPACITIVE_MIN);
          delay(2);
      }
      else {
          cappacitive_max_state = false;
          cappacitive_min_state = false;
      }
  }
      

// odečet mezních stavů minimální a maximální hladiny z plovákových senzorů ECLIPSERA
  void float_sensors_read() {
      if (fault_float == false) {
          float_max_state = digitalRead(FLOAT_MAX);
          float_min_state = digitalRead(FLOAT_MIN);
          delay(2);
      }
      else {
          float_max_state = true;
          float_min_state = true;
      }
  }


// součet výběrů ze senzorů pro maximální stav hladiny
  void selection_max_count() {
      selection_max = 0;
      if ((inhibition_ultrasonic == false) && (water_level >= 18.0))
          selection_max++;
      if ((inhibition_cappacitive == false) && (cappacitive_max_state == true))
          selection_max++;
      if ((inhibition_float == false) && (float_max_state == true))
          selection_max++;
  }


// součet výběrů ze senzorů pro minimální stav hladiny
  void selection_min_count() {
      selection_min = 0;
      if ((inhibition_ultrasonic == false) && (water_level <= 5.0))
          selection_min ++;
      if ((inhibition_cappacitive == false) && (cappacitive_min_state == false))
          selection_min++;
      if ((inhibition_float == false) && (float_min_state == false))
          selection_min++;
  }


// zjištění počtu inhibicí pro vytvoření nastavení výběru
  void selection_set_for_filling() {
      selection_set = 0;
      if (inhibition_ultrasonic == false)
          selection_set++;
      if (inhibition_cappacitive == false)
          selection_set++;
      if (inhibition_float == false)
          selection_set++;
  }


// impuls pro sepnutí relé na doplňovací čerpadlo na základě splnění podmínky aktuálního výběru
  void relay_impulse() {
      if (selection_set >= 3) {
          if (selection_max >= 2)
              digitalWrite(RELAY, LOW);
          else if (selection_min >= 2)
              digitalWrite(RELAY, HIGH);
          selection = "2/3";
      }
      else if (selection_set == 2) {
          if (selection_max >= 2)
              digitalWrite(RELAY, LOW);
          else if (selection_min >= 2)
              digitalWrite(RELAY, HIGH);
          selection = "2/2";
      }
      else if (selection_set <= 1) {
          if (selection_max >= 2)
              digitalWrite(RELAY, LOW);
          else if (selection_min >= 2)
              digitalWrite(RELAY, HIGH);
          selection = "1/1";
      }
  }


// zjištění stavu tlačítka "doplňování" a impuls na relé spínající či rozpínající čerpadlo
  void manual_filling() {
      if (filling_button_state == HIGH) {
          if (selection_set >= 2) {
              if (selection_max < 2)
                  digitalWrite(RELAY, HIGH);
          }
          else if (selection_set <= 1) {
              if (selection_max < 1)
                  digitalWrite(RELAY, HIGH);
          }
      }
      else
          digitalWrite(RELAY, LOW);
      filling_button_last_state = filling_button_state;
  }


// PWM ovládání LED tlačítka "doplňování"
  void filling_button_lightning() {
          analogWrite(FILLING_LED, brightness);
          brightness = brightness + fade_amount;
          if ((brightness == 0) || (brightness == 255))
              fade_amount = -fade_amount;
      }


// odečítání hodnot a ovládání LED tlačítka "informace"
  void informations_switch() {
      if (informations_button_state == HIGH)
          informations_button_push_count++;
      informations_button_last_state = informations_button_state;
  }


// smyčka zobrazovaných informací na LCD displeji
  void lcd_write() {
          if ((informations_button_push_count % 3) == 0) {
              lcd.clear();
              lcd.setCursor(0,0);
              lcd.print("Hladina: ");
              lcd.print(water_level, 1);
              lcd.print(" cm");
              lcd.setCursor(0,1);
              lcd.print("V");
              lcd.write(byte(1));
              lcd.print("b");
              lcd.write(byte(2));
              lcd.print("r: ");
              lcd.print(selection);
          }
          else if ((informations_button_push_count % 3) == 1) {
              if (humidity != 101) {
                  lcd.clear();
                  lcd.setCursor(0,0);
                  lcd.print("Teplota: ");
                  lcd.print(temperature);
                  lcd.setCursor(13,0);
                  lcd.print(" ");
                  lcd.write(byte(3));
                  lcd.print("C");
                  lcd.setCursor(0,1);
                  lcd.print("Vlhkost: ");
                  lcd.print(humidity);
                  lcd.setCursor(13,1);
                  lcd.print(" ");
                  lcd.print(" %");
              }
              else {
                  lcd.clear();
                  lcd.setCursor(0,0);
                  lcd.print("CHYBA CTENI DAT");
                  lcd.setCursor(0,1);
                  lcd.print("    Z DHT22");
              }
          }
          else if ((informations_button_push_count % 3) == 2) {
              lcd.clear();
              lcd.setCursor(0,0);
              lcd.print("HLA ");
              lcd.write(byte(4));
              lcd.setCursor(7,0);
              lcd.print(" MAX: ");
              if (cappacitive_max_state == true)
                  lcd.write(byte(6));
              else
                  lcd.write(byte(5));
              lcd.setCursor(15,0);
              if (float_max_state == true)
                  lcd.write(byte(8));
              else
                  lcd.write(byte(7));
              lcd.setCursor(0,1);
              lcd.print(water_level);
              lcd.setCursor(7,1);
              lcd.print(" MIN: ");
              if (cappacitive_min_state == false)
                  lcd.write(byte(6));
              else
                  lcd.write(byte(5));
              lcd.setCursor(15,1);
              if (float_min_state == false)
                  lcd.write(byte(8));
              else
                  lcd.write(byte(7));
          }
      }
