Термореле для холодильника на Arduino Pro Mini и ds18b20.

bwn
Offline
Зарегистрирован: 25.08.2014

Namelost пишет:

А какие симптомы? Просто контакта не будет? И как быстро должно окислиться? Там на замыкание вообще почти не нужен ни вольтаж ни ампераж.

То работает, то нет, то датчик отваливается. Китайский бредборд, он такой китайский. Пока отлаживаешь, бывает пять раз провода дергаешь. Ну, хозяин - барин.
Кроме окислиться, они еще и разжимаются.

Клапауций 001
Offline
Зарегистрирован: 05.09.2015

Namelost пишет:

А какие симптомы? Просто контакта не будет? И как быстро должно окислиться? Там на замыкание вообще почти не нужен ни вольтаж ни ампераж.

симптомы плохого контакта при малых токах, напряжениях и окружающем балалайку мощном радио и электромагнитном фоне очень прикольные.

*почитай о детекторных приёмниках начала прошлого века.

картинко для привлечения внимания:

bwn
Offline
Зарегистрирован: 25.08.2014

А шняга люминиевая, это типа для настройки? Да и такой детекторный диод нынче в дефиците)))).

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

диоды-то ещё мона найти..... а вот бамбука - не нашёл :( , как и клемм раритетных.....

Клапауций 001
Offline
Зарегистрирован: 05.09.2015

bwn пишет:

и такой детекторный диод нынче в дефиците)))).

дык, используй китайские контакты - сабж об этом

pka_ua
Offline
Зарегистрирован: 03.11.2014

Прошел год, холодильник бодренько работает на втором варианте скетча. Тьфу-тьфу-тьфу. :)

Из изменений - поменял датчик на герметизированный.

eugene.volin
Offline
Зарегистрирован: 12.12.2015

Эта тема вдохновила меня на ремонт холодильника.

Холодильник Атлант МХМ-1802. Реле ТАМ-133 вышло из строя.

Первоначально блок управления был сделан выносным, имел экран и рисовал графики:

Когда стало понятно что собранное устройство работает стабильно и на гарфики смотреть надоело, все детали были спрятаны в холодильник. Места там достаточно.

1 - светодиод;
2 - arduino uno r3 (китайский клон);
3 - твердотельное реле SSR-25;
4 - зарядное устройство USB 500 мА.

Датчик температуры ds18s20. Провод датчик заведен в холодильник через трубку слива конденсата, которая имеет достаточный диаметр чтобы провод никак не влиял на её функционирование.

Скетч в общих чертах повторяет пример автора темы.

Namelost
Offline
Зарегистрирован: 12.06.2015

Поменял реле на механическое - иногда срабатывание слишком медленное. Свет в холодильнике горит, но компрессор не фурычит. Внутри холодильника стоит 2 вентилятора, почти наледенения нет.

merroma
Offline
Зарегистрирован: 19.03.2016

а мона скетч показать очень интересно  а то пациент почти токойже тока переделываем тошибу двух камерную на  arduino uno китай 

pka_ua
Offline
Зарегистрирован: 03.11.2014

merroma пишет:
а мона скетч показать

Скетч на предыдущей странице темы, в #19-м сообщении http://arduino.ru/forum/proekty/termorele-dlya-kholodilnika-na-arduino-pro-mini-i-ds18b20#comment-88329

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

хобби есть хобби :)
...но не проще ли так ? https://robom.ru/product/datchiki/elektronnyj-termostat-w1209.html
...а применению ардуины отвести больше времени ?
моя сделал - как сказал выше.....

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Namelost пишет:

Поменял реле на механическое - иногда срабатывание слишком медленное. Свет в холодильнике горит, но компрессор не фурычит. Внутри холодильника стоит 2 вентилятора, почти наледенения нет.

просто современные компрессоры стали умнее....
помнишь надпись
"Нельзя включать холодильник в сеть220 после выключения ранее чем через 10 мин после откл. от 
сеть220  ?

это - была защита компрессора от перегрузок :)
современные компрессоры - сами знают , надо ли включаться по сигналу ВКЛ. ?

...а ты это воспринимаешь как - "иногда срабатывание слишком медленное"

Namelost
Offline
Зарегистрирован: 12.06.2015

SU-27-16 пишет:

хобби есть хобби :)
...но не проще ли так ? https://robom.ru/product/datchiki/elektronnyj-termostat-w1209.html
...а применению ардуины отвести больше времени ?
моя сделал - как сказал выше.....

Если есть наличие под рукой уже купленной ардуинены, не вижу смсысла для ВРЕМЕННОГО решения покупать что-то ещё.

SU-27-16 пишет:

Namelost пишет:

Поменял реле на механическое - иногда срабатывание слишком медленное. Свет в холодильнике горит, но компрессор не фурычит. Внутри холодильника стоит 2 вентилятора, почти наледенения нет.

просто современные компрессоры стали умнее....
помнишь надпись
"Нельзя включать холодильник в сеть220 после выключения ранее чем через 10 мин после откл. от 
сеть220  ?

это - была защита компрессора от перегрузок :)
современные компрессоры - сами знают , надо ли включаться по сигналу ВКЛ. ?

...а ты это воспринимаешь как - "иногда срабатывание слишком медленное"

 

Ну через некоторое время при включении холодильника щелчок/треск у колонок компьютера стал дольше. Также звук компрессора при подобном включении мне не понравился. При переходе на механическое реле - прекратилось. Может контакт окислился (о чём тут предупреждали, может ещё что) - я разбираться не стал, поменял, работает - ну и замечательно.

Сейчас уже снял это чудо техники - куплен новый холодильник.

zitadel007
Offline
Зарегистрирован: 24.04.2016

Потрясная тема... у меня тоже гикнулось там133. Поменял по этой схеме... работает. добавил только экран для вывода температуры - верхней нижней камеры .. жалко что не предусмотрел автор скетча режим "заморозка" а следовательно и использование обогревателя установленного на испаритель. Пытаюсь чтото кривыми ручками добавлять сам... идея интересная.
Но все равно отличный пост.. Гранд Мерси..

zitadel007
Offline
Зарегистрирован: 24.04.2016

а можно подсмотреть на ваш скетч.. особенно в плане подключения NOKIA LCD5110.. это ведь он?

eugene.volin
Offline
Зарегистрирован: 12.12.2015

Да, это 5110. Для работы с ним я использовал библиотеку https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library

Скетча сейчас под рукой нет.

zitadel007
Offline
Зарегистрирован: 24.04.2016

eugene.volin пишет:

 

Скетча сейчас под рукой нет.

 

Очень печально... хотелось бы не изобретать велосипед а взять готовое.. спасибо..

BHigh
Offline
Зарегистрирован: 01.09.2016

Внезапно полезная тема, когда нашел на помойке samsung sr-398. Оттуда где плата управления торчали оборваные провода. Включил компрессор напрямую - включился, подождал 40 мин - холодит. Отличный экземпляр для дачи.

Сразу нагуглил эту тему, прочитал второй пост, заказал готовый термостат. Ждать долго, творить охота сейчас, ардуины, реле и прочее есть прям сейчас, залил ОП-код, втолкнул реле и датчик - все отлично работает, автор молодец.

Но потом начались проблемы, уже к моменту приделывания ардуинокостылей (к этому моменту холодильник работал уже дня три в режиме час через три) эффективность охлаждения сильно упала.

Я его разобрал:

В первую очередь было обнаружено, что там был колхоз ремонт(изолента). И далее с помощью гугла выяснилось, что холодильник noFrost, а это значит, что в этот радиатор встроен нагреватель (видимо на 220В) который периодически нагревается и размораживает лед. Как работало в этом холодильнике - непонятно, ибо все разворочено. Гуглением выяснилось, что многие холодильники размораживаются раз в 8 часов работы компрессора. Тут сразу же стало ясно, что можно немного дополнить скетч и всечь еще одно реле. Я далеко не профи в этом и сделал так, посмотрите, норм? Дополнения в строчках 31, 32, 40, 51, 97-101, 108-111, 138.

#include <avr/wdt.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// Температура включения компрессора
#define TEMPERATURE_MAX 5.0
// Температура отключения компрессора
#define TEMPERATURE_MIN -1.0
// Пауза перед включением компрессора (600000 = 10 минут)
#define DELAY_COMPRESSOR 10000
// Максимальное время работы компрессора (3600000 = 1 час)
#define MAXTIME_COMPRESSOR 3600000
// Реле подключено к 3 пину
#define RELE 3
// Реле нагревателя разморозки подключено к 4 пину
#define RELE_R 4
// Датчик температуры подключён к 2 пину
#define ONE_WIRE_BUS 2
// Светодиод активности подключён к 13 пину
#define LED_ACTIVITY 13
// Свечение светодиода активности в мс
#define LED_ACTIVITY_ON 50
// Пауза светодиода активности в мс
#define LED_ACTIVITY_OFF 3950
// Светодиод ошибки датчика температуры подключён к 12 пину
#define LED_ERROR 12
// Время работы компрессора при ошибке датчика температуры (1200000 = 20 минут)
#define ERROR_COMPRESSOR_ON 1200000
// Время паузы компрессора при ошибке датчика температуры (2400000 = 40 минут)
#define ERROR_COMPRESSOR_OFF 2400000
// Время работы нагревателя разморозки (900000 = 15 минут)
#define razmorozkaTime 900000



float f_tempC;                         // Текущая температура
unsigned long ul_offTime;              // Время отключения компрессора
unsigned long ul_workTime;             // Время включения компрессора
unsigned long ul_newTime;              // Текущее время
unsigned long ul_deltaTime;            // Разница времени
unsigned long ul_sumWorkTime;          // Сумарное время работы компрессора
unsigned long ul_actHeartLedTime;      // Время светодиода активности
boolean b_actLedOn;                    // Светодиод активности включён
boolean b_compressorOff;               // Компрессор выключен

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup() {
  wdt_enable(WDTO_2S);
  pinMode(RELE, OUTPUT);
  pinMode(RELE_R, OUTPUT);
  pinMode(LED_ACTIVITY, OUTPUT);
  pinMode(LED_ERROR, OUTPUT);
  digitalWrite(RELE, HIGH);             // При загрузке компрессор отключён
  b_compressorOff = true;
  digitalWrite(LED_ACTIVITY, LOW);
  b_actLedOn = false;
  digitalWrite(LED_ERROR, LOW);
  sensors.begin();
  ul_offTime = millis();               // Запоминаем время начала работы программы
  ul_actHeartLedTime = ul_offTime;

}

// Функция вычисления разницы времени
unsigned long deltamills(unsigned long t_old, unsigned long t_new) {
  unsigned long delta;
  if ( t_old <= t_new ) {        
    delta = t_new - t_old;
  } else {
    delta = (4294967295 - t_old) + t_new;
  }
  return delta;
}

// Функция моргания светодиодом активности
void heartIndication(unsigned long ul_newLedTime) {
  unsigned long ul_deltaHeartTime = deltamills(ul_actHeartLedTime, ul_newLedTime);
  if(b_actLedOn){
      // Если светодиод активности включён, ждём интервала LED_ACTIVITY_ON мс
      if(ul_deltaHeartTime > LED_ACTIVITY_ON){
        digitalWrite(LED_ACTIVITY, LOW);
        b_actLedOn = false;
        ul_actHeartLedTime = ul_newLedTime;
      }
  } else {
    // Если светодиод активности выключен, ждём интервала LED_ACTIVITY_OFF мс
    if(ul_deltaHeartTime > LED_ACTIVITY_OFF){
      digitalWrite(LED_ACTIVITY, HIGH); 
      b_actLedOn = true;
      ul_actHeartLedTime = ul_newLedTime;
    }
  }
}


void razmorozka() //функция разморозки
{
digitalWrite(RELE_R, HIGH);
delay(razmorozkaTime);
}



void loop() {
  wdt_reset();                         // Обнуляем WDT (сторожевой таймер)
 
   if ( ul_sumWorkTime > 28800000 ) {        //проверяем, не пора ли разморозиться
    ul_sumWorkTime = 0;
     razmorozka();
}
  
  ul_newTime =  millis();              // Получаем текущее время

  heartIndication(ul_newTime);         // Моргаем светодиодом активности

  sensors.requestTemperatures();
  f_tempC = sensors.getTempCByIndex(0);  // Получаем температуру с датчика

  // Проверяем работоспособность датчика температуры
  if(( f_tempC > -20.0 ) && ( f_tempC < 50.0 )){ // Температурный датчик исправен
    digitalWrite(LED_ERROR, LOW);
    if ( b_compressorOff ) {                 // Если компрессор выключен
      ul_deltaTime = deltamills(ul_offTime, ul_newTime); // Разница времени простоя
      if (ul_deltaTime > DELAY_COMPRESSOR) {  // Если разница времени простоя больше разрешенной
        if ( f_tempC > TEMPERATURE_MAX ) {    // Если температура больше максимально допустимой
          digitalWrite(RELE, LOW);           // Включаем компрессор
          b_compressorOff = false;
          ul_workTime = millis();             // Записываем время включения
        }
      }
    } else {                                  // Если компрессор включен
      ul_deltaTime = deltamills(ul_workTime, ul_newTime);  // Разница времени работы
          
      // Если температура меньше минимально допустимой или время работы больше допустимого
      if ( ( f_tempC < TEMPERATURE_MIN ) || ( ul_deltaTime > MAXTIME_COMPRESSOR ) ) {
        digitalWrite(RELE, HIGH);              // Выключаем компрессор
        ul_sumWorkTime = ul_deltaTime + ul_sumWorkTime; //считаем время работы компрессора для разморозки
        b_compressorOff = true;
        ul_offTime = millis();                // Запоминаем время выключения компрессора
      }
    }
  } else {                                    // Температурный датчик неисправен или оборван
    digitalWrite(LED_ERROR, HIGH);
    if( b_compressorOff ){                    // Если компрессор выключен при неисправном датчике
        ul_deltaTime = deltamills(ul_offTime, ul_newTime); // Разница времени простоя
        if (ul_deltaTime > ERROR_COMPRESSOR_OFF) {  // Если разница времени простоя больше разрешенной
          digitalWrite(RELE, LOW);           // Включаем компрессор
          b_compressorOff = false;
          ul_workTime = millis();             // Записываем время включения
        }
    } else {                                  // Если компрессор включен при неисправном датчике
      ul_deltaTime = deltamills(ul_workTime, ul_newTime);
      if ( ul_deltaTime > ERROR_COMPRESSOR_ON ) {
        digitalWrite(RELE, HIGH);              // Выключаем компрессор
        b_compressorOff = true;
        ul_offTime = millis();                // Запоминаем время выключения компрессора
      }
    }
  }


}

Пока еще не ясно, выбран ли оптимальный подход в алгоритме разморзки. Время в 15 минут взято с потолка, надо гуглить или экспериментировать. Так же просторы предлагают использовать готовые решения в виде прибора ТАБ-Т-3, я не очень понял как он работает, термореле, но как оно понимает, что льда много - хз. Холоднее что ли становится? Знал бы параметры температур при перемерзании - поставил бы второй ds18b20. Еще как вариант - оптопара, она же будет лед замечать?

В общем еще раз спасибо автору и жду ваших комментариев и замечаний.

 

pka_ua
Offline
Зарегистрирован: 03.11.2014

Первым делом обратите внимание, что я в итоге отказался от применения watchdog, потому я бы рекомендовал программу из сообщения #19. Если Вы уверены, что Ваша модель arduino корректно работает с watchdog, тогда можно оставить и так, но у Вас в 111 строке вызывается подпрограмма, содержащая delay, а значит watchdog будет постоянно сбрасываться.

Кроме того в 100 строке Вы включаете реле разморозки, но я не нашел, где это реле выключается, т.е. раз включившись оно будет греть постоянно.

Это, так сказать, то, что сразу бросилось в глаза.

Рад, что Вам понравился мой проект.

Удачи.

Alex_Ts
Offline
Зарегистрирован: 04.10.2016

Воодушевившись этой темой, а так-же отказавшим термореле на старом холодильнике в общежитии решил по аналогии разработать свой терморегулятор с "блэк-джеком и...". Однако столкнулся с такой проблемой, как перезагрузка ардуинки в момент запуска двигателя компрессора. Проведя серию экспериментов, установил, что ноги растут от датчика DS18B20, расположенного в камере холодильника. Вернее, от наводок на него (предполагаю).

Что было опробовано: замена датчика, 2х-3х проводное его подключение, использование экранированного кабеля (~1,5м), использование шлейфа(15см), замена ардуинки (ProMini), заземление корпуса холодильника, объединение корпуса холодильника и "-" питания, смена вариантов питания, экранирование платы фольгой (xD). На закуску - комплект конденсаторов (100n керамика + 100mF электролит) у датчика.

Я просто в замешательстве. Казалось бы...

Код - чисто наброски. Т.к. идей много, но на этапе железа пока все встало:(

#include <OneWire.h>
#include <DallasTemperature.h>

// Реле подключено к 3 пину
#define RELE 3
// Датчик DS18B20 подключен к 2 пину
#define ONE_WIRE_BUS 2 
// Светодиод ошибки датчика температуры подключён к 12 пину
#define LED_ERROR 12
// Светодиод активности подключён к 13 пину
#define LED_ACTIVITY 13
// Температура на испарителе
#define TEMPERATURE_CTR 7
// Температура максимальная (аварийная)
#define TEMPERATURE_MAX 50.0 //15.0
// Температура минимальная  (аварийная)
#define TEMPERATURE_MIN -20.0 //-10.0

float f_tempC;                          // Текущая температура
int count;                              //Счетчик недач
unsigned long ul_offTime;              // Время отключения компрессора
unsigned long ul_actHeartLedTime;      // Время для светодиода активности
boolean b_compressorOn;                // Признак запущенного компрессора

OneWire oneWire(ONE_WIRE_BUS);          // Настройка библиотеки oneWire для общения с любыми OneWire устройствами
DallasTemperature sensors(&oneWire);    // Pass our oneWire reference to Dallas Temperature. 

void setup(void)
{
  //start serial port
  Serial.begin(9600);
  Serial.println("Termocotroller started");

  pinMode(RELE, OUTPUT);
  pinMode(LED_ACTIVITY, OUTPUT);
  pinMode(LED_ERROR, OUTPUT);
  digitalWrite(RELE, HIGH);             // При загрузке компрессор отключён
  b_compressorOn = false;
  digitalWrite(LED_ACTIVITY, LOW);
  digitalWrite(LED_ERROR, LOW);
  sensors.begin();                     //Запускаем библиотеку опроса датчиков
  ul_offTime = millis();               // Запоминаем время начала работы программы
  ul_actHeartLedTime = ul_offTime;
}


void loop(void)
{ 
  sensors.requestTemperatures();         // Посылаем комаду sensors.requestTemperatures() для запроса температуры (для всех устройств на шине)
  f_tempC = sensors.getTempCByIndex(0);  // Мы используем функцию ByIndex, и получаем температуру от только первого датчика.
  
  Serial.print("Temperature is: ");
  Serial.println(f_tempC); 
  //Serial.print("CompressorOn: ");
  //Serial.println(b_compressorOn); 

  if (f_tempC > TEMPERATURE_MIN && f_tempC < TEMPERATURE_MAX) //Проверка на выход за рабочий дииапазон (апартаный сбой)
    { 
      digitalWrite(LED_ERROR, LOW);           //Аварии нет
      count = 0;
      if (f_tempC > (TEMPERATURE_CTR + 1.4) && b_compressorOn == false)  //Если температура больше заданной и компрессор не работает  - устанавливаем низкий уровень на выходе (включаем реле для работы компрессора)
        {
        digitalWrite(LED_ACTIVITY, HIGH);     //Зажигаем светодиод работы компрессора
        digitalWrite(RELE, LOW);              //Включаем компрессор
        Serial.println("Compressor ON");
        b_compressorOn = true;
       // delay(5000);
        }
       
      if (f_tempC < (TEMPERATURE_CTR - 0.8) && b_compressorOn == true) //Если температура ниже заданной и компрессор работает
        {
        digitalWrite(LED_ACTIVITY, LOW);      //Тушим светодиод работы компрессора
        digitalWrite(RELE, HIGH);             //Выключаем компрессор
        b_compressorOn = false;
        Serial.println("Compressor OFF");
        }
    } else {
      digitalWrite(LED_ERROR, LOW);           //Зажигаем светодиод индикации аварии
      count++;                                //Увеличиваем счетчик на 1
      if (count > 3)                          //Если температура нереальная нескольо раз подряд то переходим к...
        {
        digitalWrite(LED_ERROR, HIGH);        //Зажигаем светодиод аварии
        if (b_compressorOn == true)
          {
          digitalWrite(RELE, HIGH);  
          b_compressorOn = false;
          Serial.println("Fault! Compressor OFF");
          //Авторежим
          }
        }
    }  
}

 

pka_ua
Offline
Зарегистрирован: 03.11.2014

Alex_Ts пишет:
Я просто в замешательстве. Казалось бы...

Попробуйте для начала поменять источник питания ардуинки. Я использовал лишнее зарядное устройство с выходом 5 вольт. Оно сразу заработало, но я, в принципе, был готов к тому, что источник питания придёться подбирать. Возьмите хотя бы для пробы хорошую зарядку и переходничок, по типу такого (пользуюсь такими, чтобы быстро запитать что-либо от 5 вольт)

Переходник питания

и попробуйте, идёт перезагрузка при работе или нет.

Удачи.

Alex_Ts
Offline
Зарегистрирован: 04.10.2016

-

Alex_Ts
Offline
Зарегистрирован: 04.10.2016

pka_ua пишет:
Попробуйте для начала поменять источник питания ардуинки.

Планировал питать все от такого блока. Далее, пробовал через юарт от USB порта компьютера. Так жде от добротной зарядки 5v 2A.

 

pka_ua
Offline
Зарегистрирован: 03.11.2014

А как Вы подключили реле? Релейным модулем или как-то ещё?

Alex_Ts
Offline
Зарегистрирован: 04.10.2016

pka_ua пишет:

А как Вы подключили реле? Релейным модулем или как-то ещё?

Да, вот таким.

pka_ua
Offline
Зарегистрирован: 03.11.2014

Попробуйте сделать следующее. Включите термореле в розетку, но не подключайте к реле холодильник. Холодильник включайте и выключайте вручную. При этом наблюдайте, как реагирует ардуина. Попробуйте написать скетч, при котором с определённой периодичностью будет включаться и выключаться реле (без холодильника). Т.е. определите, помеха от холодильника или помеха от релейного модуля перегружает ардуину. Ещё есть вероятность, что подкорачивает конкретный вывод на самой ардуине, тогда можно просто переписать скетч на другой вывод. 

Удачи

pka_ua
Offline
Зарегистрирован: 03.11.2014

Пошел второй год работы холодильника с термореле. Тьфу-тьфу-тьфу пока всё нормально :)

melvladimir
Offline
Зарегистрирован: 08.03.2013

pka_ua пишет:

Пошел второй год работы холодильника с термореле. Тьфу-тьфу-тьфу пока всё нормально :)

3-й :)
Полных 2 года работы. Покупное у меня так же трудится не выключаясь, тольк она лето/зиму меняю температуру.

safari
Offline
Зарегистрирован: 02.02.2015

Такое мех. реле надо обязательно питать отдельно (не от ардуины). Иначе, будет периодически перезазгужаться.

uncle_grin
Offline
Зарегистрирован: 26.04.2015

Воодушевленный разработкой автора и поломкой термостата у двухкамерного двухмоторного холодильника Electrolux я сделал свлой термостат

В основе Arduino Nano, блок на 4 реле с опторазвязкой, причем зараза срабатывает по низкому уровню, два DS18B20, включенные по схеме с паразитным питанием и индикатор на базе max7219 LED 7segment (диод по питанию закорочен, иначе при питании в 5 вольт показывает ерунду).

Питание - от зарядка от мобилки + пара кондеров и дроссель (ибо БП "срёт") и всё заведено на Vin.

Логика работы - из первого сообщения, ничего не менял, только температуры.

Делалось быстро, т.к. мясо и пельмени были под угрозой растаивания :)

В перспективе - константы хранить в EEPROM, приделать энкодер, им менять температуру и гистерезис, но это потом... Код ужасный, не спорю, однако рабочий :)

/*
  termostat_for_electrolux.ino

  Термореле для бытового двухкамерного  холодильника
  Arduino Nano + 4 Relay Module + 2xDS18B20

  4 Relay Module 0 - канал ВКЛЮЧЕН, 1 - канал ВЫКЛЮЧЕН (вот такой модуль попался)

  При включении напряжения сети - пауза 10 минут до включения двигателей независимо от температуры.
  При отключении, повторное включение не ранее 10 минут независимо от температуры.
  При перезагрузке - пауза 10 минут до включения двигателей независимо от температуры.
  Если компрессор работает более 1 часа - принудительная остановка независимо от температуры.
  Если температурный датчик оборван или неисправен, то компрессор работает
  в цикле (20 мин работа/40 мин отдых), при этом загорается аварийный светодиод

  Version: 2017-06-12
*/

#include <avr/wdt.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "LedControl.h"

/*
 Now we need a LedControl to work with.
 ***** These pin numbers will probably not work with your hardware *****
 pin A0 is connected to the DataIn 
 pin A1 is connected to the CLK
 pin A2 is connected to LOAD
 We have only a single MAX72XX.
 */
LedControl lc=LedControl(14,15,16,1);

// константы. Потом перезапишу их в EEPROM
// Датчик температуры подключён к 8 пину
#define ONE_WIRE_BUS 8

// Холодильник
// Температура включения компрессора холодильника 5.0
#define TEMPERATURE1_MAX  5.0
// Температура отключения компрессора холодильника 1.0
#define TEMPERATURE1_MIN  1.0
// Реле холодильника подключено к 9 пину
#define RELE1 9
// Светодиод ошибки датчика температуры холодильника подключён к 11 пину
#define LED1_ERROR 11

// Морозилка
// Температура включения компрессора морозилки -16.0
#define TEMPERATURE2_MAX  -16.0
// Температура отключения компрессора морозилки -19.0
#define TEMPERATURE2_MIN  -19.0
// Реле морозилки подключено к 10 пину
#define RELE2 10
// Светодиод ошибки датчика температуры морозилки подключён к 12 пину
#define LED2_ERROR 12



// Пауза перед включением компрессоров (600000 = 10 минут)
#define DELAY_COMPRESSOR 600000
// Максимальное время работы компрессоров (3600000 = 1 час)
#define MAXTIME_COMPRESSOR 3600000

// Секция аварийного режима
// Время работы компрессора при ошибке датчика температуры (1200000 = 20 минут)
#define ERROR_COMPRESSOR_ON 1200000
// Время паузы компрессора при ошибке датчика температуры (2400000 = 40 минут)
#define ERROR_COMPRESSOR_OFF 2400000


// Светодиод активности подключён к 13 пину
#define LED_ACTIVITY 13
// Свечение светодиода активности в мс
#define LED_ACTIVITY_ON 50
// Пауза светодиода активности в мс
#define LED_ACTIVITY_OFF 3950


float f_tempC1;                        // Текущая температура холодильника
float f_tempC2;                        // Текущая температура морозилки

unsigned long ul_newTime;              // Текущее время

unsigned long ul_actHeartLedTime;      // Время светодиода активности
boolean b_actLedOn;                    // Светодиод активности включён


unsigned long ul_offTime1;             // Время отключения компрессора холодильника
unsigned long ul_offTime2;             // Время отключения компрессора морозилки

unsigned long ul_workTime1;            // Время включения компрессора холодильника
unsigned long ul_workTime2;            // Время включения компрессора морозилки

unsigned long ul_deltaTime1;           // Разница времени для холодильника
unsigned long ul_deltaTime2;           // Разница времени для морозилки

boolean b_compressor1Off;              // Флаг компрессор холодильника выключен true / включен false
boolean b_compressor2Off;              // Флаг компрессор морозилки выключен true / включен false

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress Thermometer1 = {0x28, 0xFF, 0xB2, 0x1B, 0x50, 0x15, 0x02, 0xFC };  // адрес датчика холодильника (маркирован одной точкой)
DeviceAddress Thermometer2 = {0x28, 0xFF, 0xD4, 0x16, 0x50, 0x15, 0x02, 0xEC };  // адрес датчика морозилки (маркирован двумя точками)

// =======================================================================================================================================
void setup() {
  wdt_enable(WDTO_2S);

   
  pinMode(LED_ACTIVITY, OUTPUT);
  digitalWrite(LED_ACTIVITY, LOW);
  b_actLedOn = false;
  
  pinMode(RELE1, OUTPUT);
  pinMode(RELE2, OUTPUT);
  digitalWrite(RELE1, HIGH);      // При загрузке компрессор холодильника отключен (ИНВЕРСНО)
  b_compressor1Off = true;        // выставляем флаг холодильника
  digitalWrite(RELE2, HIGH);      // При загрузке компрессор морозилки отключен (ИНВЕРСНО)
  b_compressor2Off = true;        // выставляем флаг морозилки
  
  pinMode(LED1_ERROR, OUTPUT);
  pinMode(LED2_ERROR, OUTPUT);
  digitalWrite(LED1_ERROR, LOW);  // Гасим светодиод ошибки холодильника
  digitalWrite(LED2_ERROR, LOW);  // Гасим светодиод ошибки морозилки

  sensors.begin();                // Инициализация датчиков температуры
  sensors.setResolution(Thermometer1, 9); // Режим точности 9 бит +-0.5 С
  sensors.setResolution(Thermometer2, 9);
  
  ul_offTime1 = millis();          // Запоминаем время начала работы программы
  ul_offTime2 = millis();          // Запоминаем время начала работы программы
  ul_actHeartLedTime = millis();
  
  // start serial port для отладки
  //Serial.begin(9600);

  lc.shutdown(0,false);
  /* Set the brightness to a medium values */
  lc.setIntensity(0,8);
  /* and clear the display */
  lc.clearDisplay(0);
}


// ==========================================================================================================================================
// Функция вычисления разницы времени
unsigned long deltamills(unsigned long t_old, unsigned long t_new) {
  unsigned long delta;
  if ( t_old <= t_new ) {
    delta = t_new - t_old;
  } else {
    delta = (4294967295 - t_old) + t_new;
  }
  return delta;
}

// ==========================================================================================================================================
// Функция моргания светодиодом активности
void heartIndication(unsigned long ul_newLedTime) {
  unsigned long ul_deltaHeartTime = deltamills(ul_actHeartLedTime, ul_newLedTime);
  if (b_actLedOn) {
    // Если светодиод активности включён, ждём интервала LED_ACTIVITY_ON мс
    if (ul_deltaHeartTime > LED_ACTIVITY_ON) {
      digitalWrite(LED_ACTIVITY, LOW);
      b_actLedOn = false;
      ul_actHeartLedTime = ul_newLedTime;
    }
  } else {
    // Если светодиод активности выключен, ждём интервала LED_ACTIVITY_OFF мс
    if (ul_deltaHeartTime > LED_ACTIVITY_OFF) {
      digitalWrite(LED_ACTIVITY, HIGH);
      b_actLedOn = true;
      ul_actHeartLedTime = ul_newLedTime;
    }
  }
}
// ============================================================================================================================================
// Функция вывода числа на индикатор
// a - число, n - стартовая позиция
void printNumber(float a, int n) {
    int incoming;
    int v1;
    int v2;
    int v3;
    boolean negative;  

    negative = false;  
    if(a < 0) {
        negative = true;
        a = a * (-1);
    }
    incoming = (int)a * 10 ;
    v1 = incoming / 100;
    v2 = incoming % 100 / 10;
    v3 = incoming % 10;
       
    // теперь печатаем цифры на 1-ой, 2-ой и 3-ей позициях:
    lc.setDigit(0,2+n,(byte)v1,false);
    lc.setDigit(0,1+n,(byte)v2,true);
    lc.setDigit(0,0+n,(byte)v3,false);
    
    
    if(negative) {
       lc.setChar(0,3+n,'-',false);
    }
    else {
       // теперь печатаем знак «пробел» на 4-ой позиции:
       lc.setChar(0,3+n,' ',false);
    }
}
// ============================================================================================================================================
void loop() {
  wdt_reset();                         // Обнуляем WDT (сторожевой таймер)

  ul_newTime =  millis();              // Получаем текущее время
  heartIndication(ul_newTime);         // Моргаем светодиодом активности

  sensors.requestTemperatures();
  
  // для холодильника
  f_tempC1 = sensors.getTempC(Thermometer1); // Получаем температуру с датчика холодильника
  Serial.print("Temp C1: ");
  Serial.println(f_tempC1);
  printNumber (f_tempC1, 0); // выводим температуру в холодильнике
   
  // Проверяем работоспособность датчика температуры холодильника
  if (( f_tempC1 > -20.0 ) && ( f_tempC1 < 50.0 )) { // Температурный датчик исправен
    digitalWrite(LED1_ERROR, LOW);        // гасим индикатор ошибки холодильника
    
    if ( b_compressor1Off ) {                 // Если компрессор выключен
      ul_deltaTime1 = deltamills(ul_offTime1, ul_newTime); // Разница времени простоя
      if (ul_deltaTime1 > DELAY_COMPRESSOR) {  // Если разница времени простоя больше разрешенной
        if ( f_tempC1 > TEMPERATURE1_MAX ) {    // Если температура больше максимально допустимой
          digitalWrite(RELE1, LOW);           // Включаем компрессор
          b_compressor1Off = false;
          ul_workTime1 = millis();             // Записываем время включения
        }
      }
    } else {                                  // Если компрессор включен
      ul_deltaTime1 = deltamills(ul_workTime1, ul_newTime); // Разница времени работы
      // Если температура меньше минимально допустимой или время работы больше допустимого
      if ( ( f_tempC1 < TEMPERATURE1_MIN ) || ( ul_deltaTime1 > MAXTIME_COMPRESSOR ) ) {
        digitalWrite(RELE1, HIGH);              // Выключаем компрессор
        b_compressor1Off = true;
        ul_offTime1 = millis();                // Запоминаем время выключения компрессора
      }
    }
  } else {                                    // Температурный датчик неисправен или оборван
    digitalWrite(LED1_ERROR, HIGH);
    if ( b_compressor1Off ) {                  // Если компрессор выключен при неисправном датчике
      ul_deltaTime1 = deltamills(ul_offTime1, ul_newTime); // Разница времени простоя
      if (ul_deltaTime1 > ERROR_COMPRESSOR_OFF) {  // Если разница времени простоя больше разрешенной
        digitalWrite(RELE1, LOW);           // Включаем компрессор
        b_compressor1Off = false;
        ul_workTime1 = millis();             // Записываем время включения
      }
    } else {                                  // Если компрессор включен при неисправном датчике
      ul_deltaTime1 = deltamills(ul_workTime1, ul_newTime);
      if ( ul_deltaTime1 > ERROR_COMPRESSOR_ON ) {
        digitalWrite(RELE1, HIGH);              // Выключаем компрессор
        b_compressor1Off = true;
        ul_offTime1 = millis();                // Запоминаем время выключения компрессора
      }
    }
  }
  // для морозилки
  f_tempC2 = sensors.getTempC(Thermometer2); // Получаем температуру с датчика морозилки
  Serial.print("Temp C2: ");
  Serial.println(f_tempC2);
  printNumber (f_tempC2, 4); // выводим температуру в морозилке

  // Проверяем работоспособность датчика температуры морозилки
  if (( f_tempC2 > -30.0 ) && ( f_tempC2 < 50.0 )) { // Температурный датчик исправен
    digitalWrite(LED2_ERROR, LOW);        // гасим индикатор ошибки холодильника
    
    if ( b_compressor2Off ) {                 // Если компрессор выключен
      ul_deltaTime2 = deltamills(ul_offTime2, ul_newTime); // Разница времени простоя
      if (ul_deltaTime2 > DELAY_COMPRESSOR) {  // Если разница времени простоя больше разрешенной
        if ( f_tempC2 > TEMPERATURE1_MAX ) {    // Если температура больше максимально допустимой
          digitalWrite(RELE2, LOW);           // Включаем компрессор
          b_compressor2Off = false;
          ul_workTime2 = millis();             // Записываем время включения
        }
      }
    } else {                                  // Если компрессор включен
      ul_deltaTime2 = deltamills(ul_workTime2, ul_newTime); // Разница времени работы
      
      // Если температура меньше минимально допустимой или время работы больше допустимого
      if ( ( f_tempC2 < TEMPERATURE2_MIN ) || ( ul_deltaTime2 > MAXTIME_COMPRESSOR ) ) {
        digitalWrite(RELE2, HIGH);              // Выключаем компрессор
        b_compressor2Off = true;
        ul_offTime2 = millis();                // Запоминаем время выключения компрессора
      }
    }
  } else {                                    // Температурный датчик неисправен или оборван
    digitalWrite(LED2_ERROR, HIGH);
    if ( b_compressor2Off ) {                  // Если компрессор выключен при неисправном датчике
      ul_deltaTime2 = deltamills(ul_offTime2, ul_newTime); // Разница времени простоя
      if (ul_deltaTime2 > ERROR_COMPRESSOR_OFF) {  // Если разница времени простоя больше разрешенной
        digitalWrite(RELE2, LOW);           // Включаем компрессор
        b_compressor2Off = false;
        ul_workTime2 = millis();             // Записываем время включения
      }
    } else {                                  // Если компрессор включен при неисправном датчике
      ul_deltaTime2 = deltamills(ul_workTime2, ul_newTime);
      if ( ul_deltaTime2 > ERROR_COMPRESSOR_ON ) {
        digitalWrite(RELE2, HIGH);              // Выключаем компрессор
        b_compressor2Off = true;
        ul_offTime2 = millis();                // Запоминаем время выключения компрессора
      }
    }
  }
  
} // END loop

 

 

Критика приветствуется

pka_ua
Offline
Зарегистрирован: 03.11.2014

Рад, что кому-то пригодился мой проект. Из критики - стоило бы предупредить тех, кто будет повторять Вашу конструкцию о том, что предварительно надо проверить, как конкретный экземпляр Arduino обрабатывает watchdog. Там, к сожалению, могут быть неприятные сюрпризы - сам наступал на эти грабли и пришлось делать второй вариант программы без watchdog-а.

Удачи!

p.s. Мой холодильник до сих пор жив и работает (тьфу-тьфу-тьфу) :)

eugene.volin
Offline
Зарегистрирован: 12.12.2015

Мой холодильник с ардуино отработал два года и продолжает работать.

Конструкцию я описывал ранее: http://arduino.ru/forum/proekty/termorele-dlya-kholodilnika-na-arduino-pro-mini-i-ds18b20?page=1#comment-153530

А вот код:

#include <OneWire.h>

// датчик температуры
#define PIN_SENSOR 8

// реле управления компрессором
#define PIN_COMPRESSOR 9

// индикатор температуры
#define PIN_LED 10

// частота опроса датчика температуры - 30 секунд
#define TIME_SENSOR_INTERVAL 30000

// частота обновления индикатора - 5 секунд
#define TIME_DISPLAY_INTERVAL 5000

// при первом включении отложить запуск компрессора на 10 минут
#define TIME_DELAY 600000

// максимальное время работы компрессора 1 час
#define TIME_MAX 3600000

// режим работы при неисправном датчике температуры 40/40 минут
#define TIME_ONLINE 2400000
#define TIME_OFFLINE 2400000

// температура выключения компрессора
#define TEMPERATURE_MIN -2.0

// температура включения компрессора
#define TEMPERATURE_MAX 5.0


OneWire ds(PIN_SENSOR);

// состояние компрессора
float compressor_online=false;

// температура
float temperature=-999;

// счётчик ошибок
int error_counter=0;

// время последнего измерения температуры
unsigned long time_sensor=0;

// время последнего обновления дисплея
unsigned long time_display=0;

// время последнего включения компрессора
unsigned long time_on=0;

// время последнего выключения компрессора
unsigned long time_off=0;

void setup(){

  pinMode(PIN_COMPRESSOR,OUTPUT);
  digitalWrite(PIN_COMPRESSOR,LOW);

  pinMode(PIN_LED,OUTPUT);
  digitalWrite(PIN_LED,HIGH);

  delay(1000);

}


void loop(){

  unsigned long time_now=millis();
  unsigned long time_delta;

  time_delta=x_time_delta(time_sensor,time_now);
  if(time_delta>TIME_SENSOR_INTERVAL){
    float new_temperature=x_get_temperature();
    if( (new_temperature<-20.0) || (new_temperature>50.0) ) {
      if(error_counter<3) error_counter++;
    }else{
      if(error_counter>0) error_counter--;
      temperature=new_temperature;
    }
    time_sensor=time_now;
  }

  time_delta=x_time_delta(time_display,time_now);
  if(time_delta>TIME_DISPLAY_INTERVAL){
    x_display_data();
    time_display=time_now;
  }

  if( error_counter<3 ){

    if(compressor_online){

      time_delta=x_time_delta(time_on,time_now);
      if( (temperature<TEMPERATURE_MIN) || (time_delta>TIME_MAX) ){
        digitalWrite(PIN_COMPRESSOR,LOW);
        compressor_online=false;
        time_off=time_now;
      }

    }else{

      if(temperature>TEMPERATURE_MAX){
        time_delta=x_time_delta(time_off,time_now);
        if(time_delta>=TIME_DELAY){
          digitalWrite(PIN_COMPRESSOR,HIGH);
          compressor_online=true;
          time_on=time_now;
        }
      }

    }

  }else{

    if(compressor_online){

      time_delta=x_time_delta(time_on,time_now);
      if(time_delta>TIME_ONLINE){
        digitalWrite(PIN_COMPRESSOR,LOW);
        compressor_online=false;
        time_off=time_now;
      }

    }else{

      time_delta=x_time_delta(time_off,time_now);
      if(time_delta>TIME_OFFLINE){
        digitalWrite(PIN_COMPRESSOR,HIGH);
        compressor_online=true;
        time_on=time_now;
      }

    }

  }

}


/**
 * Получает температуру
 */
float x_get_temperature(void){
  byte i;
  byte present=0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float t=-999; // error
  int wd=10;
  while(ds.search(addr)){
    if(OneWire::crc8(addr,7)!=addr[7]){
      return -998; // Error: CRC in not valid
    }
    switch(addr[0]){
      case 0x10:
        type_s=1; // DS18S20 || DS1820
        break;
      case 0x28:
        type_s=0; // DS18B20
        break;
      case 0x22:
        type_s=0; // DS1822
        break;
      default:
        return -997; // Error: unknow chip
    }
    ds.reset();
    ds.select(addr);
    ds.write(0x44,1); // start conversion, with parasite power on at the end
    delay(1000); // maybe 750ms is enough, maybe not
    present=ds.reset();
    ds.select(addr);
    ds.write(0xBE); // read scratchpad
    for(i=0;i<9;i=i+1){
      data[i]=ds.read();
    }
    // convert the data to actual temperature
    int16_t raw=(data[1] << 8) | data[0];
    if(type_s){
      raw=raw<<3; // 9 bit resolution default
      if(data[7]==0x10){
        raw=(raw & 0xFFF0)+12-data[6];
      }
    }else{
      byte cfg=(data[4] & 0x60);
      if(cfg==0x00) raw=raw & ~7;
      else if(cfg==0x20) raw=raw & ~3;
      else if(cfg==0x40) raw=raw & ~1;
    }
    t=(float)raw/16.0;
    wd--;
    if(wd==0) break;
  }
  ds.reset_search();
  return t;
}


/**
 * Выводит информацию на дисплей
 */
void x_display_data(){

  int i;

  if(error_counter==0){
    /* ok */
    if(temperature>0){
      int delta=int(temperature);
      delta=delta+1;
      if(delta<1) delta=1;
      if(delta>10) delta=10;
      for(i=0;i<delta;i=i+1){
        digitalWrite(PIN_LED,HIGH);
        delay(150);
        digitalWrite(PIN_LED,LOW);
        delay(250);
      }
    }else{
      int delta=int(-temperature);
      delta=delta+1;
      if(delta<1) delta=1;
      if(delta>10) delta=10;
      for(i=0;i<delta;i=i+1){
        digitalWrite(PIN_LED,LOW);
        delay(150);
        digitalWrite(PIN_LED,HIGH);
        delay(250);
      }
    }
  }else{
    /* error */
    for(i=0;i<3;i=i+1){
      digitalWrite(PIN_LED,HIGH);
      delay(500);
      digitalWrite(PIN_LED,LOW);
      delay(500);
    }
  }

}


/**
 * Вычисляет разницу между двумя отметками времени в милисекундах
 */
unsigned long x_time_delta(unsigned long time_old,unsigned long time_new){
  unsigned long time_delta;
  if(time_old<=time_new){
    time_delta=time_new-time_old;
  }else{
    time_delta=(4294967295-time_old)+time_new;
  }
  return time_delta;
}

Пожалуй, любопытного в этом коде - только индикатор температуры на одном светодиоде.

Плюсовая температура обозначается короткими вспышками. Сколько вспышек, столько и градусов.

При минусовой температуре светодиод горит постоянно и гаснет на короткие промежутки времени. Опять же, сколько погасаний, столько и градусов.

Такая схема оказалась очень удобной для визуального контроля нормальной работы холодильника.

Еще могу добавить что электронное реле держит температуру в холодильнике гораздо точнее чем механическое. Теперь и в холод, и в жару продукты одинаково холодные. Это хорошо видно по твердности сливочного масла, например.

bit70
Offline
Зарегистрирован: 16.08.2017

А что же в место max7219 LED можно прикрутить I2C 1602 ЖК-дисплей? и сделать типа 

constantinoff
Offline
Зарегистрирован: 27.12.2015

у моего холодильника BOSCH сломалась плата, и теперь работает тольео одна камера из двух, две вместе работать ни как не хотят, вот я и решил пойти по вашим стопам. UNO имеется (была куплена для эксперементов), однако я могу только скопировать чей то проэкт, сам пока создать не могу, не хватает опыта в создпнии скетчей. со всего форума, ваш проэкт мне показался наиболее привлекательным. Но как  понял ваша схема управляет тоько одной камерой. От сюда прозьба к вам выложить принципиальную схему и скетч. заранее благодарем.

constantinoff
Offline
Зарегистрирован: 27.12.2015

eugene.volin пишет:

Эта тема вдохновила меня на ремонт холодильника.

Холодильник Атлант МХМ-1802. Реле ТАМ-133 вышло из строя.

Первоначально блок управления был сделан выносным, имел экран и рисовал графики:

Когда стало понятно что собранное устройство работает стабильно и на гарфики смотреть надоело, все детали были спрятаны в холодильник. Места там достаточно.

1 - светодиод;
2 - arduino uno r3 (китайский клон);
3 - твердотельное реле SSR-25;
4 - зарядное устройство USB 500 мА.

Датчик температуры ds18s20. Провод датчик заведен в холодильник через трубку слива конденсата, которая имеет достаточный диаметр чтобы провод никак не влиял на её функционирование.

Скетч в общих чертах повторяет пример автора темы.

 

у моего холодильника BOSCH сломалась плата, и теперь работает тольео одна камера из двух, две вместе работать ни как не хотят, вот я и решил пойти по вашим стопам. UNO имеется (была куплена для эксперементов), однако я могу только скопировать чей то проэкт, сам пока создать не могу, не хватает опыта в создпнии скетчей. со всего форума, ваш проэкт мне показался наиболее привлекательным. Но как  понял ваша схема управляет тоько одной камерой. От сюда прозьба к вам выложить принципиальную схему и скетч. заранее благодарем.

ogursoft
Offline
Зарегистрирован: 26.06.2017

Тоже приказало долго жить реле у холодильника Стинол. Холодильник старый, лет ему около 20. Модель вроде 102 люкс. Двухкамерный ноуфрост, с одним компрессором. По мотивам скетчей из этой темы запилил свою схему. Решил сделать на WeMos D1 mini. Так как все детали были в наличии решил не покупать новое реле, а сделать электронное управление + контроль работы холодильника по Wifi. Несколько дней допиливал скетч и схему, сегодня все подключил и собрал полность холодильник: прикрутил все панели, верхнюю крышку, прокинул датчик ds18b20, у меня был герметичный, пришелся как раз кстати. Теперь можно заливать прошивку по ОТА, если буду каки-либо изменения. Температуру включения выбрал как у ТС 1..5 градусов, по характеристикам реле, которое стояло у него было 2..8. Решил, что 8 градусов многовато. Проект на githab

neid86@gmail.com
Offline
Зарегистрирован: 28.10.2014

constantinoff пишет:

eugene.volin пишет:

Эта тема вдохновила меня на ремонт холодильника.

Холодильник Атлант МХМ-1802. Реле ТАМ-133 вышло из строя.

Первоначально блок управления был сделан выносным, имел экран и рисовал графики:

Когда стало понятно что собранное устройство работает стабильно и на гарфики смотреть надоело, все детали были спрятаны в холодильник. Места там достаточно.

1 - светодиод;
2 - arduino uno r3 (китайский клон);
3 - твердотельное реле SSR-25;
4 - зарядное устройство USB 500 мА.

Датчик температуры ds18s20. Провод датчик заведен в холодильник через трубку слива конденсата, которая имеет достаточный диаметр чтобы провод никак не влиял на её функционирование.

Скетч в общих чертах повторяет пример автора темы.

 

у моего холодильника BOSCH сломалась плата, и теперь работает тольео одна камера из двух, две вместе работать ни как не хотят, вот я и решил пойти по вашим стопам. UNO имеется (была куплена для эксперементов), однако я могу только скопировать чей то проэкт, сам пока создать не могу, не хватает опыта в создпнии скетчей. со всего форума, ваш проэкт мне показался наиболее привлекательным. Но как  понял ваша схема управляет тоько одной камерой. От сюда прозьба к вам выложить принципиальную схему и скетч. заранее благодарем.

Добрый день! Не могли бы поделиться скетчем по вашему проекту? Я его немного переделаю на дисплей 16*2 без графиков!

eugene.volin
Offline
Зарегистрирован: 12.12.2015

neid86@gmail.com пишет:

Добрый день! Не могли бы поделиться скетчем по вашему проекту? Я его немного переделаю на дисплей 16*2 без графиков!

#include <SPI.h>
#include <OneWire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>


// датчик температуры
#define PIN_SENSOR 11

// ключ управления вентилятором
#define PIN_FAN 10

// реле управления нагревателем
#define PIN_HEATER 9

// частота опроса датчика температуры - 3 секунды
#define TIME_SENSOR_INTERVAL 3000

// разрешение графика температуры по оси x - 1 минута
#define TIME_LOG_INTERVAL 6000

// частота обновления экрана - 3 секунды
#define TIME_DISPLAY_INTERVAL 3000

// при первом включении отложить запуск на 0 минут
#define TIME_DELAY 0

// температура перехода в вентилятора в импульсный режим
#define TEMPERATURE_IMP 25.0

// температура включения нагревателя
#define TEMPERATURE_MIN 25.0

// температура выключения нагревателя
#define TEMPERATURE_MAX 35.0


OneWire ds(PIN_SENSOR);
Adafruit_PCD8544 display=Adafruit_PCD8544(3,4,5,6,7);

float t_log_min[84];
float t_log_max[84];
float t_min=99;
float t_max=-99;

// состояние вентилятора
float fan_online=false;

// состояние нагревателя
float heater_online=false;

// температура
float temperature=-999;

// счётчик ошибок
int error_counter=0;

// время последнего измерения температуры
unsigned long time_sensor=0;

// время последнего сдвига в логе
unsigned long time_log=0;

// время последнего обновления дисплея
unsigned long time_display=0;

// время последнего включения вентилятора
unsigned long time_fan_on=0;

// время последнего выключения вентилятора
unsigned long time_fan_off=0;

// время последнего включения нагревателя
unsigned long time_heater_on=0;

// время последнего выключения нагревателя
unsigned long time_heater_off=0;

// страница
int display_page=0;


void setup(){

  pinMode(PIN_SENSOR,INPUT);
  pinMode(PIN_FAN,OUTPUT);
  pinMode(PIN_HEATER,OUTPUT);

  display.begin();
  display.clearDisplay();
  display.display();
  display.setContrast(50);

  int i;
  for(i=0;i<84;i=i+1){
    t_log_min[i]=99;
    t_log_max[i]=-99;
  }

  delay(1000);

}


void loop(){

  unsigned long time_now=millis();
  unsigned long time_delta;

  time_delta=x_time_delta(time_sensor,time_now);
  if(time_delta>TIME_SENSOR_INTERVAL){
    float new_temperature=x_get_temperature();
    if(new_temperature<-900) {
      if(error_counter<2) error_counter++;
    }else{
      if(error_counter>0) error_counter--;
      temperature=new_temperature;
      x_log_write();
    }
    time_sensor=time_now;
  }

  time_delta=x_time_delta(time_log,time_now);
  if(time_delta>TIME_LOG_INTERVAL){
    x_log_rotate();
    time_log=time_now;
  }

  time_delta=x_time_delta(time_display,time_now);
  if(time_delta>TIME_DISPLAY_INTERVAL){
    x_display_data();
    time_display=time_now;
  }

  if( error_counter<2 ){

    if(!fan_online){
      digitalWrite(PIN_FAN,HIGH);
      fan_online=true;
      time_fan_on=time_now;
    }

    if(heater_online){

      if(temperature>=TEMPERATURE_MAX){
        digitalWrite(PIN_HEATER,LOW);
        heater_online=false;
        time_heater_off=time_now;
      }

    }else{

      if(temperature<TEMPERATURE_MIN){
        digitalWrite(PIN_HEATER,HIGH);
        heater_online=true;
        time_heater_on=time_now;
      }

    }

  }else{

    if(fan_online){
      digitalWrite(PIN_FAN,LOW);
      fan_online=false;
      time_fan_off=time_now;
    }
    if(heater_online){
      digitalWrite(PIN_HEATER,LOW);
      heater_online=false;
      time_heater_off=time_now;
    }

  }

}


/**
 * Получает температуру
 */
float x_get_temperature(void){
  byte i;
  byte present=0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float t=-999; // error
  int wd=10;
  while(ds.search(addr)){
    if(OneWire::crc8(addr,7)!=addr[7]){
      return -998; // Error: CRC in not valid
    }
    switch(addr[0]){
      case 0x10:
        type_s=1; // DS18S20 || DS1820
        break;
      case 0x28:
        type_s=0; // DS18B20
        break;
      case 0x22:
        type_s=0; // DS1822
        break;
      default:
        return -997; // Error: unknow chip
    }
    ds.reset();
    ds.select(addr);
    ds.write(0x44,1); // start conversion, with parasite power on at the end
    delay(1000); // maybe 750ms is enough, maybe not
    present=ds.reset();
    ds.select(addr);
    ds.write(0xBE); // read scratchpad
    for(i=0;i<9;i=i+1){
      data[i]=ds.read();
    }
    // convert the data to actual temperature
    int16_t raw=(data[1] << 8) | data[0];
    if(type_s){
      raw=raw<<3; // 9 bit resolution default
      if(data[7]==0x10){
        raw=(raw & 0xFFF0)+12-data[6];
      }
    }else{
      byte cfg=(data[4] & 0x60);
      if(cfg==0x00) raw=raw & ~7;
      else if(cfg==0x20) raw=raw & ~3;
      else if(cfg==0x40) raw=raw & ~1;
    }
    t=(float)raw/16.0;
    wd--;
    if(wd==0) break;
  }
  ds.reset_search();
  return t;
}


/**
 * Записывает температуру в лог
 */
void x_log_write(void){
  if(error_counter<3){
    t_log_min[0]=min(t_log_min[0],temperature);
    t_log_max[0]=max(t_log_max[0],temperature);
    t_min=min(t_min,temperature);
    t_max=max(t_max,temperature);
  }
}


/**
 * Сдвигает данные в логе
 */
void x_log_rotate(void){
  int i;
  for(i=83;i>0;i=i-1){
    t_log_min[i]=t_log_min[i-1];
    t_log_max[i]=t_log_max[i-1];
  }
  t_log_min[0]=99;
  t_log_max[0]=-99;
}


/**
 * Выводит информацию на дисплей
 */
void x_display_data(){
  int x;
  int y_min;
  int y_max;
  int i;
  String s;

  unsigned long time_now=millis();

  display.clearDisplay();
  display.setTextColor(BLACK);

  // temperature, 0-16
  display.setTextSize(2);
  display.setCursor(0,0);
  if(error_counter==0){
    s=x_temperature_to_string(temperature)+"\xEF"+"C";
  }else{
    s="Error "+String(error_counter);
  }
  display.print(s);

  // 18-38
  t_min=99;
  t_max=-99;
  for(i=0;i<84;i=i+1){
    t_min=min(t_min,t_log_min[i]);
    t_max=max(t_max,t_log_max[i]);
  }
  if(t_min<=t_max){
    for(i=0;i<84;i=i+1){
      x=83-i;
      if(t_log_min[i]<=t_log_max[i]){
        y_min=38-(int)(20*(t_log_min[i]-t_min)/(t_max-t_min));
        y_max=38-(int)(20*(t_log_max[i]-t_min)/(t_max-t_min));
        display.drawLine(x,y_min,x,y_max,BLACK);
      }
    }
  }

  // 40-47
  display_page++;
  display.setTextSize(1);
  display.setCursor(0,40);
  switch(display_page){
    case 0:
      // min..max
      s=x_temperature_to_string(t_min)+".."+x_temperature_to_string(t_max)+"\xEF"+"C";
      break;
    case 1:
      // uptime
      int m=int(time_now/1000/60/60);
      s="Uptime "+String(m)+" hr";
      break;
  }
  display.print(s);
  if(display_page>1) display_page=0;

  display.display();
}


/**
 * Конвертирует температуру в строку вида -21,7
 */
String x_temperature_to_string(float t){
  int a;
  int b;
  String s;
  if(t>=0){
    a=int(t);
    b=int(t*10)-a*10;
    s="+"+String(a)+","+String(b);
  }else{
    t=abs(t);
    a=int(t);
    b=int(t*10)-a*10;
    s="-"+String(a)+","+String(b);
  }
  return s;
}


/**
 * Вычисляет разницу между двумя отметками времени в милисекундах
 */
unsigned long x_time_delta(unsigned long time_old,unsigned long time_new){
  unsigned long time_delta;
  if(time_old<=time_new){
    time_delta=time_new-time_old;
  }else{
    time_delta=(4294967295-time_old)+time_new;
  }
  return time_delta;
}

Но предупреждаю что это был пробный код. А вот рабочий код, который стабильно работает годами, я уже публиковал: http://arduino.ru/forum/proekty/termorele-dlya-kholodilnika-na-arduino-p...