//Библиотеки.
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>

//////////////////////////////////////////////////////////////////
//Ножки задействованные под реле и индикаторы
#define ReleC  4    // реле компрессора
#define ReleF  5    // реле вентилятора
#define ReleT  6    // реле оттайки
#define LedT  13    // свет оттайки

//На какой ноге датчик температуры?
#define TEMP_WIRE_BUS 2

//Зацепки для термометра.
OneWire tempWire(TEMP_WIRE_BUS);           //объявили переменную датчиков
DallasTemperature TempSensors(&tempWire);  //объявили структуру типа Даллас термометр

// /////////////////////////////////////////////////////////////////

//Константные параметры работы холодильника
const float targetTemp = -18;                 //Установленная температура заморозки (C)
const float targetDefrostTemp = 10;           //Установленная температура разморозки (C)
const unsigned long compReadTime = 60000;   //Интервал считывания температуры компрессора (ms)
const unsigned long heatReadTime = 10000;    //Интервал считывания температуры нагревателя (ms)
const unsigned long compWorkTime = 3000000;   //Максимальное время непрерывной работы компрессора (ms)
const unsigned long heatWorkTime = 900000;    //Максимальное время непрерывной работы нагревателя (ms)
const unsigned long compRestTime = 420000;    //Время паузы на охлаждение компрессора (ms)
const unsigned long defrostTime = 43200000;   //Интервал запуска цикла разморозки (ms)


//Переменные
unsigned long lastDefrostTime;

// /////////////////////////////////////////////////////////////////

//Функция снятия температуры
float getTemp(){
  //Считка данных с термодатчика
  TempSensors.requestTemperatures();
  //Преобразование данных в градусы Цельсия
  float tempTemp=TempSensors.getTempCByIndex(0);
  Serial.println(tempTemp);
  return tempTemp;
}

// /////////////////////////////////////////////////////////////////

// Подпрограмма цикла компрессии
 void compressorCycle()
  {
  unsigned long compTimeStamp=millis(); //Время включения компрессора
  while (getTemp() > targetTemp && millis() - compTimeStamp < compWorkTime) //Проверка на температуру и допустимое время работы
    {digitalWrite(ReleC, HIGH); //Включение компрессора
    delay (compReadTime);       //Интервал проверки температуры и времени
    }
  digitalWrite(ReleC, LOW);     //Выключение компрессора
  delay (compRestTime);         //Принудительная пауза перед перезапуском компрессора
  }

// Подпрограмма цикла нагрева
void heaterCycle()
{
  unsigned long heatTimeStamp=millis(); //Время включения нагревателя
  digitalWrite (LedT, HIGH);            //Включение индикатора нагревателя
  while (millis() - heatTimeStamp < heatWorkTime) //Проверка на допустимое время работы
    {if (getTemp() < targetDefrostTemp) //Проверка на температуру
      {digitalWrite (ReleT, HIGH);}     //Включение нагревателя
    else {digitalWrite (ReleT, LOW);};  //Выключение нагревателя
  delay (heatReadTime);                 //Интервал проверки температуры и времени
  }
  digitalWrite (ReleT, LOW);            //Последнее выключение нагревателя
  digitalWrite (LedT, LOW);             //Выключение индикатора нагревателя
}


// /////////////////////////////////////////////////////////////////

// ////////////////////////////////////////////////////////////////////
void setup() {
  //Инициализация реле компрессора
  pinMode(ReleC, OUTPUT);
  digitalWrite(ReleC, LOW);
  //Инициализация реле вентилятора
  pinMode(ReleF, OUTPUT);
  digitalWrite(ReleF, LOW);
  //Инициализация реле нагревателя
  pinMode(ReleT, OUTPUT);
  digitalWrite(ReleT, LOW);
  //Инициализация индикатора цикла разморозки
  pinMode(LedT, OUTPUT);
  digitalWrite (LedT, HIGH);
  //Инициализация термодатчика
  TempSensors.begin();
  //Сериал-порт для дебага
  Serial.begin(9600);
  //Задержка семь минут, защита от скачков напряжения
  delay(420000);
  lastDefrostTime = millis();
  digitalWrite (LedT, LOW);
}
// //////////////////////////////////////////////////////////////////

// /////////////////////////////////////////////////////////////////
void loop() {

if (millis() < lastDefrostTime) {lastDefrostTime = millis();} //Проверка на перелив времени

unsigned long tillDefrost = millis() - lastDefrostTime; //Вычисление времени до цикла нагревателя

 if (tillDefrost > defrostTime) {        //Проверка на достижение интервала
 digitalWrite(ReleF, LOW);               //Выключение вентилятора
  heaterCycle();                         //Цикл разморозки
  lastDefrostTime = millis();            //Сброс таймера разморозки
  }
  else
  {digitalWrite(ReleF, HIGH);            //Выключение вентилятора
   compressorCycle();                    //Цикл компрессии
  };
}   
// /////////////////////////////////////////////////////////////////
