#include <avr/wdt.h>
uint32_t myTimer1, myTimer2, myTimer3, myTimer4;

#define PUMP 2 // Насос
#define HAH_LEV 3 // ВАУ верхний аварийный уровень
#define HWH_LEV 4 // ВРУ верхний рабочий уровень
#define HWL_LEV 5 // НРУ нижний рабочий уровень
#define HAL_LEV 6 // НАУ нижний аварийный уровень


#define LED_PUMP 7 // PUMP Индикация работы насоса
#define LED_HAH_LEV 8 // Индикация датчика ВАУ верхний аварийный уровень
#define LED_HWH_LEV 9 // Индикация датчика ВРУ верхний рабочий уровень
#define LED_HWL_LEV 10 // Индикация датчика НРУ нижний рабочий уровень
#define LED_HAL_LEV 11 // Индикация датчика НАУ нижний аварийный уровень

#define MODE A0 // Режим работы уровнемера (срабатывают по очереди = 1, все сработали при максимальнеом уровне = 0)
#define TYPE_HWL A1 // Тип дптчика нижний рабочий уровень НРУ (нормально разомкнут = 1, нормально сомкнут = 0)
#define TYPE_HWH A2 // Тип дптчика верхний рабочий уровень ВРУ (нормально разомкнут = 1, нормально сомкнут = 0)
#define TYPE_HAL 12 // Тип дптчика нижний аварийный уровень НРУ (нормально разомкнут = 1, нормально сомкнут = 0)
#define TYPE_HAH 13 // Тип дптчика верхний аварийный уровень ВРУ (нормально разомкнут = 1, нормально сомкнут = 0)

#define SLEEP_0 A3 // 0 разряд - включения / отключения насоса в скважине 
#define SLEEP_1 A4 // 1 разряд - включения / отключения насоса в скважине 
#define SLEEP_2 A5 // 2 разряд - включения / отключения насоса в скважине
#define SLEEP_3 A6 // 3 разряд - включения / отключения насоса в скважине
#define STEP_SLEEP A7 // Множитель разомкнут = 5 секунд, замкнут = 20 секунд

// 0000 = 0 * STEP_SLEEP = 0 или 0 секунд
// 0001 = 1 * STEP_SLEEP = 5 или 20 секунд  
// 0010 = 2 * STEP_SLEEP = 10 или 40 секунд 
// 0011 = 3 * STEP_SLEEP = 15 или 60 секунд 
// 0100 = 4 * STEP_SLEEP = 20 или 80 секунд 
// 0101 = 5 * STEP_SLEEP = 25 или 100 секунд
// 0110 = 6 * STEP_SLEEP = 30 или 120 секунд
// 0111 = 7 * STEP_SLEEP = 35 или 140 секунд
// 1000 = 8 * STEP_SLEEP = 40 или 160 секунд
// 1001 = 9 * STEP_SLEEP = 45 или 180 секунд
// 1010 = 10 * STEP_SLEEP = 50 или 200 секунд
// 1011 = 11 * STEP_SLEEP = 55 или 220 секунд
// 1100 = 12 * STEP_SLEEP = 60 или 240 секунд
// 1101 = 13 * STEP_SLEEP = 65 или 260 секунд
// 1110 = 14 * STEP_SLEEP = 70 или 280 секунд
// 1111 = 15 * STEP_SLEEP = 75 или 300 секунд

// ---SETUP---
// переменные для уровней
bool b_hah_lev = false;
bool b_hwh_lev = false;
bool b_hwl_lev = false;
bool b_hal_lev = false;


// переменные настройки
bool b_type_hal = false;// вход тип датчика НАУ
bool b_type_hah = false;// вход тип датчика ВАУ
bool b_type_hwl = false;// вход тип датчика НРУ
bool b_type_hwh = false;// вход тип датчика ВРУ
bool b_mode = false; // режим работы зависит от используемых датчиков без перемычки только срабатывание без фиксации уровня
bool b_sleep_0 = false; // вход пауза 0 
bool b_sleep_1 = false; // вход пауза 1 
bool b_sleep_2 = false; // вход пауза 2 
bool b_sleep_3 = false; // вход пауза 3 
bool b_step_sleep = false; // вход множителя

int i_sleep = 0;
int i_step_sleep = 5;
int i_pause = 0;

bool failure_sensor = false; // ошибка сенсора
bool failure_equipment = false; // ошибка оборудования

void setup() {

  wdt_disable();
  wdt_enable (WDTO_4S); // Для тестов не рекомендуется устанавливать значение менее 8 сек.
  // Возможные значения для константы
  //  WDTO_15MS
  //  WDTO_30MS
  //  WDTO_60MS
  //  WDTO_120MS
  //  WDTO_250MS
  //  WDTO_500MS
  //  WDTO_1S
  //  WDTO_2S
  //  WDTO_4S
  //  WDTO_8S
  
 Serial.begin(9600);
  // 
  pinMode(0, OUTPUT); // светодиод на плате
  pinMode(1, OUTPUT); // светодиод на плате
  pinMode(PUMP, OUTPUT); // выход на насос
  pinMode(HAH_LEV, INPUT_PULLUP); // вход ВАУ
  pinMode(HWH_LEV, INPUT_PULLUP); // вход ВРУ
  pinMode(HWL_LEV, INPUT_PULLUP); // вход НРУ
  pinMode(HAL_LEV, INPUT_PULLUP); // вход НАУ

  // сигнальные диоды
  pinMode(LED_PUMP, OUTPUT); // выход диод насоса
  pinMode(LED_HAH_LEV, OUTPUT); // выход диод датчика ВАУ
  pinMode(LED_HWH_LEV, OUTPUT); // выход диод датчика ВРУ
  pinMode(LED_HWH_LEV, OUTPUT); // выход диод датчика НРУ
  pinMode(LED_HAL_LEV, OUTPUT); // выход диод датчика НАУ

  pinMode(MODE, INPUT_PULLUP); // режим работы зависит от используемых датчиков без перемычки только срабатывание без фиксации уровня
  pinMode(TYPE_HAH, INPUT_PULLUP); // вход тип датчика ВАУ
  pinMode(TYPE_HWH, INPUT_PULLUP); // вход тип датчика ВРУ
  pinMode(TYPE_HWL, INPUT_PULLUP); // вход тип датчика НРУ
  pinMode(TYPE_HAL, INPUT_PULLUP); // вход тип датчика НАУ
 
  
  pinMode(SLEEP_0, INPUT_PULLUP); // вход пауза 0
  pinMode(SLEEP_1, INPUT_PULLUP); // вход пауза 1
  pinMode(SLEEP_2, INPUT_PULLUP); // вход пауза 2
  pinMode(SLEEP_3, INPUT_PULLUP); // вход пауза 3
  pinMode(STEP_SLEEP, INPUT_PULLUP); // вход множителя

  // --инициализация выходов--
  digitalWrite(0, HIGH); // диод на плате включен
  digitalWrite(1, LOW); // диод на плате выключен
  digitalWrite(PUMP, LOW); // насос выключен

  digitalWrite(LED_PUMP, LOW); // диод насоса выключен
  digitalWrite(LED_HAH_LEV, LOW); // диод ВАУ выключен
  digitalWrite(LED_HWH_LEV, LOW); // диод ВРУ выключен
  digitalWrite(LED_HWL_LEV, LOW); // диод НРУ выключен
  digitalWrite(LED_HAL_LEV, LOW); // диод НАУ выключен

//читаем входы настройки
// типы датчиков и режим работы уровнемера
b_mode = !digitalRead(MODE);
b_type_hah = digitalRead(TYPE_HAH); 
b_type_hwh = digitalRead(TYPE_HWH); 
b_type_hwl = digitalRead(TYPE_HWL); 
b_type_hal = digitalRead(TYPE_HAL); 

// читаем коэфициенты паузы включения отключения насоса
b_sleep_0 = !digitalRead(SLEEP_0); 
b_sleep_1 = !digitalRead(SLEEP_1); 
b_sleep_2 = !digitalRead(SLEEP_2);
b_sleep_3 = !digitalRead(SLEEP_3); 
b_step_sleep = !digitalRead(STEP_SLEEP); 

b_sleep_3 = 1;
b_step_sleep = 1;

// вычисляем паузу срабатывания включения отключения насоса
if (b_sleep_0 == true) i_sleep = i_sleep + 1;
if (b_sleep_1 == true) i_sleep = i_sleep + 2;
if (b_sleep_2 == true) i_sleep = i_sleep + 4;
if (b_sleep_3 == true) i_sleep = i_sleep + 8;
if (b_step_sleep == true) i_step_sleep = 20;
i_pause = i_step_sleep * i_sleep;


}

// ---LOOP---

void loop() {
  Serial.println("Start WDT = 1sec OK!");
  boolean  Lev_HA, Lev_HW, Lev_LW, Lev_LA;
  bool b_hah_lev, b_hwh_lev, b_hwl_lev, b_hal_lev; // переменные уровней

// прочитаем датчики и обработаем их с учетом настроек входов типов датчиков
  b_hah_lev = digitalRead(HAH_LEV) ^ b_type_hah; // вход ВАУ
  b_hwh_lev = digitalRead(HWH_LEV) ^ b_type_hwh; // вход ВРУ
  b_hwl_lev = digitalRead(HWL_LEV) ^ b_type_hwl; // вход НРУ
  b_hal_lev = digitalRead(HAL_LEV) ^ b_type_hal; // вход НАУ

// установим сигнальные диоды согласно датчикам и насосу
digitalWrite (LED_HAH_LEV, b_hah_lev);
digitalWrite (LED_HWH_LEV, b_hwh_lev);
digitalWrite (LED_HWL_LEV, b_hwl_lev);
digitalWrite (LED_HAL_LEV, b_hal_lev);
digitalWrite (LED_PUMP, digitalRead (PUMP));

//тип работы уровнемеров включаються поочередно включен или один, или не одного
if (b_mode == false) {

// контроль срабатывания уровня, фильтр на замыкание только одного датчика
 Lev_HA = b_hah_lev & !b_hwh_lev & !b_hwl_lev & !b_hal_lev;  // ВАУ сработал = установить аварию
 Lev_HW = !b_hwl_lev & b_hwh_lev & !b_hwl_lev & !b_hal_lev; // ВРУ сработал = отключаем насос
 Lev_LW = !b_hah_lev & !b_hwh_lev & b_hwl_lev & !b_hal_lev; // НРУ сработал = включить насос
 Lev_LA = !b_hah_lev & !b_hwh_lev & !b_hwl_lev & b_hal_lev; // НАУ сработал = установить аварию

// контроль датчика уровня на залипание контактов 
 if (Lev_HA != b_hah_lev) failure_sensor = true;
 if (Lev_HW != b_hwh_lev) failure_sensor = true;
 if (Lev_LW != b_hwl_lev) failure_sensor = true;
 if (Lev_LA != b_hal_lev) failure_sensor = true;

// контроль оборудования на нормальную работу недопущение работы при ВАУ и НАУ   
if (Lev_HA == true) failure_equipment = true;
if (Lev_LA == true) failure_equipment = true;

// управление насосом в зависимости от режима датчика уровня
 if (failure_sensor == true || failure_equipment == true) {
// есть ошибки в работе датчиков и оборудования отключаем насос
    digitalWrite (PUMP, LOW);
// включаем сигнальную лампу на плате 0 - сенсор, 1 - оборудование
    digitalWrite(0, LOW); // тушим диод 0
    digitalWrite(1, LOW); // тушим диод 1
    if (failure_sensor == true) digitalWrite(0, HIGH); // ошибка сенсора диод 0 зажигаем
    if (failure_equipment == true) digitalWrite(1, HIGH); // ошибка оборудования диод 1 зажигаем
 }
else {
// ошибок оборудования и сенсора нет можно работать с уровнями и включать насос
    if (Lev_HW == true && Lev_LW == false) digitalWrite (PUMP, LOW);
    if (Lev_HW == false && Lev_LW == true) digitalWrite (PUMP, HIGH); 
 }

}

//тип работы уровнемеров включаються снизу вверх включенны могут быть все если максимальный уровень
if (b_mode == true) {
// контроль срабатывания уровня, фильтр на замыкание только одного датчика
 Lev_HA = b_hah_lev & b_hwh_lev & b_hwl_lev & b_hal_lev;  // ВАУ сработал = установить аварию
 Lev_HW = !b_hah_lev & b_hwh_lev & b_hwl_lev & b_hal_lev; // ВРУ сработал = отключаем насос
 Lev_LW = !b_hah_lev & !b_hwh_lev & b_hwl_lev & b_hal_lev; // НРУ сработал = включить насос
 Lev_LA = !b_hah_lev & !b_hwh_lev & !b_hwl_lev & b_hal_lev; // НАУ сработал = установить аварию

// контроль датчика уровня на залипание контактов 
 if (Lev_HA != b_hah_lev) failure_sensor = true;
 if (Lev_HW != b_hwh_lev) failure_sensor = true;
 if (Lev_LW != b_hwl_lev) failure_sensor = true;
 if (Lev_LA != b_hal_lev) failure_sensor = true;

// контроль оборудования на нормальную работу недопущение работы при ВАУ и НАУ   
if (Lev_HA == true) failure_equipment = true;
if (Lev_LA == true) failure_equipment = true; 

// управление насосом в зависимости от режима датчика уровня
 if (failure_sensor == true || failure_equipment == true) {
// есть ошибки в работе датчиков и оборудования отключаем насос
    digitalWrite (PUMP, LOW);
// включаем сигнальную лампу на плате 0 - сенсор, 1 - оборудование
    digitalWrite(0, LOW); // тушим диод 0
    digitalWrite(1, LOW); // тушим диод 1
    if (failure_sensor == true) digitalWrite(0, HIGH); // ошибка сенсора диод 0 зажигаем
    if (failure_equipment == true) digitalWrite(1, HIGH); // ошибка оборудования диод 1 зажигаем
 }
else {
// ошибок оборудования и сенсора нет можно работать с уровнями и включать насос
    if (Lev_HW == true && Lev_LW == false) digitalWrite (PUMP, LOW);
    if (Lev_HW == false && Lev_LW == true) digitalWrite (PUMP, HIGH); 
 }

}

// сигнализация нормальной работы
if (failure_sensor == true || failure_equipment == true) {
  if (millis() - myTimer2 >= 250) {   // Delay (0.5 с)
      myTimer2 = millis();              // Timer reset
      digitalWrite(0, !digitalRead(0)); //
      digitalWrite(1, !digitalRead(1)); //
  }
}

wdt_reset();    
}