Блок с датойБлок с временемБлок с возрастом сайта
Mr.ALB

    Анатолий Беляев (aka Mr.ALB). Персональный сайт

    Да пребудут с вами Силы СВЕТА!

     

    Ардуино (Arduino). #13

    Терморегулятор TR-2 для холодильника

    Отказал терморегулятор в холодильнике Атлант МХМ-161-0. Купил новый, а он оказался не рабочим, очевидно бракованный. Решил сделать электронный на Ардуино. Далее, что получилось.

    Терморегулятор TR-2
    Терморегулятор TR-2

    Подразделы


     

    Описание

    Терморегулятор имеет датчик температуры из терморезистора MF52-10k, по которому измеряется температура в холодильной объёме. При достижении пороговой уставки, компрессор холодильника отключается. При превышении температуры выше уставки порога отключения + дельта, компрессор включается. На экране TFT 0.96" показывается:

    • Общее время работы холодильника.
    • Температура в Вольтах и отсчётах.
    • Уставка порога отключения в Вольтах и отсчётах.
    • Коэффициент производительности компрессора.
    • Время работы цикла в минутах.
    • Время отдыха цикла в минутах.

     

    Схема Терморегулятора

    Схема собрана на Arduino Pro Mini (можно использовать любую: Arduino UNO, Arduino Nano и подобные им). Датчик температуры – терморезистор MF52-10k.

    Для индикации режимов работы используется экран HL1 типа TFT 0.96" ST7735. Попутно замечу, что этот экземпляр экрана у меня какой-то неправильный. У него коды цвета зеркальные, поэтому пришлось определить нестандартные коды цвета. Если использовать такой же тип экрана, но правильный, то дополнительное определение цветов не потребуется. Попробовал использовать руссификацию этого экрана, но c этим экраном тоже что-то не пошло. Собственно, делал на том, что было улыбка. Экран подключен к Ардуино по аппаратной схеме, для быстроты работы. Напряжение питания экрана поступает через небольшой стабилизатор на +3,3 В.

    По схеме: конденсаторы C1...C5 блокировочные от помех. Резисторы R2, R3 подстроечные. С помощью R2 устанавливается порог отключения копрессора. С помощью R3 можно смещать характеристику терморезистора. Терморезистор R1 включен между питанием VCC и портом измерения A0, поэтому если температура в холодильном объёме растёт, то и напряжение на измерительном порте A0 тоже растёт.

    Чтобы иметь стабильное напряжение на VCC – используется стабилизатор Ардуино. Напряжение питания всего терморегулятора подаётся на контакт RAW. Это же напряжение 9 В поступает и на стабилизатор 78L05, с которого уже 5 В поступает на исполнительное реле, срабатывающее от 5 Вольт. Так сделано, чтобы разгрузить стабилизатор Ардуино и уменьшить влияние реле К1. Реле управляется через порт D3 с помощью транзистора VT1. В коллекторе транзистора VT1, кроме реле К1, включен индикаторный светодиод HL2 синего цвета (можно любой).

    В качестве кнопки управления яркостью экрана использована сенсорная кнопка. У неё отсутствует дребезг сигнала на выходе и скетч упрощается. Нет надобности использовать дополнительные библиотеки.

    Терморегулятор TR-2. Схема электрическая принципиальная
    Pic 1. Терморегулятор TR-2. Схема электрическая принципиальная

     

    Скетч

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

    Скетч и библиотеку можно скачать в подразделе Приложение.

    /**********************************************************
     * 2020-02-11 Mr.ALB Тренировка в программировании Ардуино
     **********************************************************
     * 2020-02-11 v2.0 Терморегулятор для холодильника 
     *    Экран 0.96" TFT ST7735
     *    включает и выключает компрессор 
     *    в диапазоне значений vterm...vterm_reg+vdelta,
     *    значения температуры условные, в Вольтах, 
     *    с терморезистором MF52-10k, 
     *    MF52-10k подключить к VCC и через резистор 20к к GND
     *    Имеется уставка для задания температуры включения
     *            
     *  Подключение  дисплея аппаратно:
     *  TFT ST7735  ARDUINO
     *  GND       – GND
     *  VCC       – 3.3V
     *  SCL       – pin13 через резистор 1-2k
     *  SDA       – pin11 через резистор 1-2k
     *  RES       – pin9  через резистор 1-2k
     *  DC        – pin8  через резистор 1-2k
     *  CS        – pin10 через резистор 1-2k
     *  BLK       – pin7
     * 
     * 2020-02-13 v2.1 Управление с помощью реле. 
     *                 Управляющий сигнал HIGH.
     *                 Кнопка подсветки сенсорная TTP223
     * 2020-02-17 v2.2 Расчёт производительности компрессора
     * 2020-02-18 v2.3 Оптимизация кода
    **********************************************************/
    // Программа: Автор, Версия, Дата, Название
    char* prog[]={"Mr.ALB ","v2.3","2020-02-18","TR-2 "};
    
    #include <Adafruit_GFX.h>   // Графическая библиотека
    #include <Adafruit_ST7735.h>// Библиотека для ST7735
    #include <SPI.h>
    
    #define TFT_CS  10  // CS
    #define TFT_RST 9   // RES
    #define TFT_DC  8   // DC
                        // SCL – Подключить к pin13
                        // SDA – Подключить к pin11
                          
    // Создание объекта tft. Аппаратное подключение
    Adafruit_ST7735 tft = Adafruit_ST7735
      (
        TFT_CS,
        TFT_DC,
        TFT_RST
      );
      
    /* Определение цветов,
     * значения зеркальные к значениям ST7735_COLOR */
    #define C_BLACK     0x0000
    #define C_BLUE      0xF100
    #define C_RED       0x008F
    #define C_ORANGE    0x0ACF
    #define C_DARKGREEN 0x0240
    #define C_CYAN      0xFD60
    #define C_YELLOW    0x0E7F
    #define C_WHITE     0xFFFF
    #define C_GRAY      0x455A
    #define C_DARKGRAY  0xBCA5
    #define C_LIGHTGRAY 0x99CE
    
    #define PIN_TERM    A0// Вывод для измерения температуры
    #define PIN_REG     A1// Вывод для регулировки температуры
    #define PIN_OUT     3 // Вывод для включения компрессора
    #define BUTTON_BLK  4 // Кнопка подсветки дисплея
    #define PIN_BLK     6 // Вывод PWM для подсветки дисплея
    
    #define DELAY_RUN 180000 // Задержка запуска компрессора
    #define DELAY_CHECK 3000 // Интервал между измерениями 
    #define DARK_LIGHT 30000 // Задержка гашения экрана
    
    uint8_t count_blk_level=1;
    //При уровне подсветки blk_level==0 -подсветка выключена
    uint8_t blk_level=count_blk_level*25;
    boolean flag_blk=false;
    
    uint8_t font_size=1;  // Размер шрифта
    
    /* Переменные для времени */
    uint32_t t1,t2,t3,t4,t_display,dt;
    
    /* Переменные счётчика времени */
    byte  sec_time=0,
          min_time=0,
          hour_time=0,
          day_time=0;
    
    /* Переменные времени работы */
    uint32_t  t_work_stop,t_work_start,
              t_work, t_rest;
    byte      k_work;
    
    int term, term_old; // Переменные температуры
    
    #define SCREEN_W 160  // Ширина экрана в px
    #define SCREEN_H 80   // Высота экрана в px
    
    byte x_info=36; //Позиция вывода информации
    byte y_term=18; //Позиция вывода температуры
    byte y_term_reg=y_term+18;//Позиция вывода уставки
    byte y_work=y_term_reg+21;//Позиция вывода производительности
    byte y_width=SCREEN_W-x_info;//Ширина экрана вывода информации
    
    float vcc=5.0;    // vcc – Напряжение VCC Ардуино
    float vdelta=.12; // Дельта гистерезиса в Вольтах
    float vterm=0, vterm_reg=0; // Напряжение датчика и уставки
    
    boolean flag_run=false;     // Флаг управления компрессором
    boolean flag_first_run=true;// Флаг первого запуска
    
    /***********************/
    /* Настройка программы */
    /***********************/
    void setup(void) 
    {
      pinMode(PIN_BLK,OUTPUT);  // Порт управления подсветкой экрана
      pinMode(PIN_OUT,OUTPUT);  // Порт управления компрессором
      pinMode(BUTTON_BLK,INPUT);// Порт кнопки управления подсветкой
      
      tft.initR(INITR_MINI160x80);// Инициал. экрана 0.96" TFT ST7735
      tft.setRotation(3); // Поворот экрана
                          // .setRotation(uint8_t r)
                          // где r:
                          // 0 – вертикально.   поворот на 0°
                          // 1 – горизонтально. поворот на 90°
                          // 2 – вертикально.   поворот на 180°
                          // 3 – горизонтально. поворот на 270°
      
      analogWrite(PIN_BLK,144); // Яркость заставки
      fnZastavka();             // Заставка
      analogWrite(PIN_BLK,blk_level); // Яркость на начальную
      fnPrintText();  // Вывод основных постоянных надписей
    }
    
    /***********************/
    /*  Рабочая программа  */
    /***********************/
    void loop() 
    {
      t1=millis();  // Текущее время работы программы в мс
      
      if(flag_first_run)  //Первый запуск
      {
        flag_first_run=false;
        t4=t1;
      }
      
      // Установка минимальной яркости через 30 секунд
      if(t1-t_display>DARK_LIGHT)
      {
        t_display=t1;
        count_blk_level=0;
        analogWrite(PIN_BLK,3);// Минимум яркости
      }
        
      /* Счётчик времени работы */
      if((t1-dt)>1000) // Прошла секунда
      {
        fnWorkTimer
        (
          0,            // x_time
          0,            // y_time
          1,            // font_size
          C_GRAY        // color
        );
        dt=t1;
      }
      
      // Проверка времени обновления параметров
      if((t1-t3)>DELAY_CHECK)
      {
        t3=t1;
        /* Измерение температуры */
        term=analogRead(PIN_TERM);
        if(term!=term_old)
        {
          // Напряжение с датчика температуры
          term=fnAnalogMeasure(PIN_TERM, 10);
          vterm=(float)term*vcc/1024.0;
          
          /* Вывод температуры на экан */
          font_size=2;
          tft.setTextSize(font_size);
          tft.fillRect
          (
            x_info,
            y_term,
            SCREEN_W-x_info,
            font_size*8*2,
            C_BLACK
          );
          tft.setCursor(x_info, y_term);
          tft.setTextColor(C_YELLOW);
          if(vterm>0)tft.print("+");
          // Температура в V
          tft.print(vterm,3);
          tft.print("V ");
          tft.setTextColor(C_GRAY);
          font_size=1;
          tft.setTextSize(font_size);
          tft.print(term);// Температура в Отсчётах
    
          term_old=term;  // Сохраняем значение
    
          /* Измерение уставки */
          // Напряжение по Уставке
          term=fnAnalogMeasure(PIN_REG, 10);
          vterm_reg=(float)term*vcc/1024.0;
    
          /* Вывод уставки на экан */
          font_size=2;
          tft.setTextSize(font_size);
          tft.fillRect
          (
            x_info,
            y_term_reg,
            SCREEN_W-x_info,
            font_size*8,
            C_BLACK
          );
          tft.setCursor(x_info, y_term_reg);
          tft.setTextColor(C_BLUE);
          if(vterm_reg>0)tft.print("+");
          // Уставка температуры в V
          tft.print(vterm_reg,3);
          tft.print("V ");
          tft.setTextColor(C_GRAY);
          font_size=1;
          tft.setTextSize(font_size);
          tft.print(term);// Уставка в Отсчётах
        }
      }
      
      /***************************************/
      /* Управление компессором холодильника */
      /* Включаем компрессор */
      if
      (
        vterm>vterm_reg+vdelta &&
        flag_run==false &&
        (t1-t4)>DELAY_RUN
      )
      {
        // Задержка запуска (для открывания двери)
        t4=t1;
        flag_run=true;
        digitalWrite(PIN_OUT,HIGH);   //Включаем реле
        t_work_start=t1;              // Старт времени работы
        t_rest=(t1-t_work_stop)/1000; // Время отдыха в сек
      }
      /* Выключаем компрессор */
      if(vterm<vterm_reg && flag_run==true)
      {
        digitalWrite(PIN_OUT,LOW);
        flag_run=false; 
        t_work_stop=t1;   // Стоп времени работы
        
        /* Выводим коэффициент производительности компрессора */
        // Вычисляем коэффициент производительности компрессора
        // Время работы в сек
        t_work=(t_work_stop-t_work_start)/1000;
        
        // Коэф. производительности в %
        k_work=(float)t_work*100/(t_work+t_rest);
        
        /* Раскрасим коэф. k_work по значению */
        if(k_work<=26)              // Хорошо
          tft.setTextColor(C_DARKGREEN);
        if(k_work>26 && k_work<=60) // Норма
          tft.setTextColor(C_CYAN);
        if(k_work>60)               // Плохо
          tft.setTextColor(C_RED);
        font_size=1;
        tft.setTextSize(font_size);
        tft.fillRect
        (
          x_info+8,
          y_work,
          SCREEN_W-x_info,
          font_size*8,
          C_BLACK
        );
        tft.setCursor(x_info+8, y_work);
        tft.print(k_work);
        tft.print("% [");
        tft.print(t_work/60); // Время работы в мин
        tft.print("; ");
        tft.print(t_rest/60); // Время отдыха в мин
        tft.print("]");      
      }
    
      /* Стираем с экрана прогресс бар подсветки,
       * если прошло 3 секунды
       */
      if((t1-t2)>DELAY_CHECK)
      {
        tft.fillRect(0, 9*8+2,SCREEN_W, 3, C_BLACK);
        flag_blk=false;
      }
      
      // Считывание состояния кнопки подсветки
      if(digitalRead(BUTTON_BLK) == HIGH)
      { // Было нажатие кнопки подсветки
        t2=t1;
        count_blk_level++;    // Шаг яркости
        if(count_blk_level>10)
        {
          count_blk_level=0;  // Выключаем подсветку
          blk_level=3;        // Минимум яркости
          tft.fillRect(0, 9*8+2,SCREEN_W, 3, C_BLACK);
        }
        else
        {
          blk_level=count_blk_level*25;
          //Максимальная яркость
          if(blk_level == 250) blk_level=255;  
        }
        // Установка яркости
        analogWrite(PIN_BLK,blk_level); 
        
        /* Прогресс бар яркости подсветки */
        uint8_t bar_step=0;
        uint8_t bar_step_const=8*2;
        for(uint8_t ip=0;ip<count_blk_level;ip++)
        {
          tft.fillRect
          (
            1+bar_step,
            9*8+2,
            bar_step_const-2,
            3,
            C_WHITE
          );
          bar_step+=bar_step_const;
        }
        delay(500);
      } 
      delay(5);
    }
    
    /****************************************
     *                ФУНКЦИИ
     ****************************************/
    /* Функция – Заставка */
    void fnZastavka()
    {
      fnClrScreen(); // Очистить экран
      tft.setTextWrap(false);
      tft.setTextColor(C_ORANGE);
      font_size=2;
      tft.setTextSize(font_size);
      fnCenter(prog[3],font_size,1,0);
      tft.print(prog[3]);
    
      font_size=2;
      tft.setTextSize(font_size);
      fnCenter(prog[0],font_size,2,0);
      tft.setTextColor(C_DARKGREEN);
      tft.print(prog[0]);
      
      font_size=1;
      tft.setTextSize(font_size);
      tft.setTextColor(C_GRAY);
      fnCenter(prog[1],font_size,6,0);
      tft.println(prog[1]);
      
      fnCenter(prog[2],font_size,7,2);
      tft.print(prog[2]);
    
      delay(5200);
    }
    
    /* Функция – центрирование строки */
    void fnCenter(
                  char* string,
                  uint8_t fntsize,
                  uint8_t row,
                  uint8_t offset
                 )
    {
      // Подсчёт количества символов в строке
      boolean flag=true;
      byte i=0;
      while(string[i]!='\0')i++;
      
      // Установка позиции вывода строки
      tft.setCursor
      (
        (SCREEN_W-i*fntsize*6)/2+fntsize*6/2,
        fntsize*8*row+offset
      );
    }
    
    /* Функция стирания экрана чёрным цветом */
    void fnClrScreen()
    {
      // Очистить экран, т.е. закрасить чёрным
      tft.fillScreen(C_BLACK);
      // Курсор в начало экрана
      tft.setCursor(0, 0);
    }
    
    /* Функция – Вывод основных надписей на экран */
    void fnPrintText()
    {
      fnClrScreen();  // Очистить экран
      font_size=1;
      tft.setTextSize(font_size);
      tft.setTextColor(C_DARKGRAY);
      
      /* Вывод температуры */
      tft.setCursor(0, y_term+4);
      tft.print("Term:");
      
      /* Вывод уставки температуры */
      tft.setCursor(0, y_term_reg+4);
      tft.print("TReg:");
    
      /* Вывод Времён цикла */
      tft.setCursor(0, y_work);
      tft.print("K_work:");
    }
    
    /* Функция измерения с аналогового порта
     * Усредняем по n значениям
    */
    int fnAnalogMeasure(byte pin, byte n)
    {
      uint16_t p=0;
      for (int i=0;i<n;i++) p+=analogRead(pin);
      return p/n;  // Среднее арифметическое
    }
    
    /* Функция – Вывод на экран времени работы программы */
    void fnWorkTimer
    (
      byte x_time, byte y_time, byte font_size, int color
    )
    {
      font_size=1;
      tft.setTextSize(font_size);
      tft.setTextColor(color);
      /* Очистка места под индикацию времени работы */
      tft.fillRect
      (
        x_time,
        y_time,
        SCREEN_W/font_size*6,
        font_size*8,
        C_BLACK
      );
      tft.setCursor(x_time,y_time);
      
      sec_time++;     
      if(sec_time>59)   // Ограничение секунд
      {
        sec_time=0;     // Обнуление счётчика секунд
        min_time++;     // Инкремент минут
      }
      if(min_time>59)   // Ограничение минут
      {
        min_time=0;     // Обнуление счётчика минут
        hour_time++;    // Инкремент часов
      }
      if(hour_time>24)  // Ограничение часов
      {
        hour_time=0;    // Обнуление счётчика часов
        day_time++;     // Инкремент дней
      }  
      // Вывод часов и дней
      // Если появились часы и дни, то выводим на экран
      // а пока нет часов и дней – выводим только мин и сек
      if(day_time>0) 
      {
        tft.print(day_time);
        tft.print(" days ");
      }
      if(hour_time>0) 
      {
        if(hour_time<10)tft.print("0");
        tft.print(hour_time);
        tft.print(":");
      }  
      // Вывод минут  
      if(min_time<10)tft.print("0");
      tft.print(min_time);
      tft.print(":");
      // Вывод секунд
      if(sec_time<10)tft.print("0");
      tft.print(sec_time);
    }
    

     

    Реализация

    Терморегулятор выполнен в виде единого блока. В нём две платы. Первая – сам терморегулятор. Вторая плата – блок питания на 9 В. Платы установлены на одном шасси из пластика ABS, с разделяющей их перегородкой. Общие размеры устройства: 96 * 60 * 33 мм.

    Напряжение питания ~220 В взято от холодильника через клеммную колодку.

    Ниже на фото процесс изготовления терморегулятора.

    Вначале макетирование и написание базовой программы, чтобы всё вместе как-то работало, основные узлы.

    На фото видно, что подключен зуммер. Использовал его для звуковой индикации, потом эти коды из скетча удалил.

    Макетирование
    Pic 1. Макетирование

    Когда программа в основном была закончена, то перешёл к изготовлению устройства на плате. Плата с односторонней металлизацией. Размеры 5 * 7 см.

    Ниже на фото компоненты устройства перед сборкой.

    Вид с верхней стороны
    Pic 2. Вид с верхней стороны

    Печатную плату не делаю, не имеет смысла.

    На сенсорную кнопку вначале припаивал конденсатор 30 пФ для уменьшения чувствительности кнопки... потом его снял.

    Вид с нижней стороны
    Pic 3. Вид с нижней стороны

    После того, как устройство собрал, то промерил токи потребления в различных режимах. Наименьший ток 26,6 мА.

    Наименьший ток потребления
    Pic 4. Наименьший ток потребления

    Наибольший ток потребления составил 120,3 мА. Это при включенном реле, индикаторе включения компрессора и при ярком режиме экрана. После этого были внесены изменения в схему – добавил стабилизатор 78L05 для отдельного питания реле.

    Наибольший ток потребления
    Pic 5. Наибольший ток потребления

    На фото виден уже установленный стабилизатор 78L05, слева вверху от экрана.

    Общий вид. Реле включено
    Pic 6. Общий вид. Реле включено

    На этом фото стабилизатор 78L05 лучше виден.

    На экране информация пока выводится без коэффициента производительности компрессора. В окончательном варианте скетча вывод информации несколько по другому.

    Общий вид. Реле выключено
    Pic 7. Общий вид. Реле выключено

    А вот и зачинщик проекта улыбка. Наш холодильник Атлант МХМ-161-0. До момента отказа терморегулятора отработал почти 23 года. Магнитик с видами Новой Земли привёз сын из армии... там служил.

    Холодильник <q>Атлант МХМ-161-0</q>
    Pic 8. Холодильник Атлант МХМ-161-0

    Снята крышка с отсека управления. Хорошо видно два терморегулятора. Слева – подаёт сигнал на красный светодиод, если в морозильной камере повышенная температура. Справа – отказавший терморегулятор, который отвечает за цикличность работы холодильника. Поддерживает заданную температуру в холодильном отделении. К этому терморегулятору идёт крутилка, для установки требуемой температуры в холодильном отделении.

    Снята крышка с отсека управления
    Pic 9. Снята крышка с отсека управления

    Снят испорченный терморегулятор. К проводам подсоединён клеммник. От него идут провода ~220 В для питания собранного терморегулятора и от терморегулятора провода на управление компрессором холодильника.

    Подключение клеммника к проводам
    Pic 10. Подключение клеммника к проводам

    Изучив внутреннее расположение частей отсека управления холодильником, нашёл очень удачное место для установки моего терморегулятора. Габариты этого места определили размеры создаваемого терморегулятора.

    Место под терморегулятор
    Pic 11. Место под терморегулятор

    В это место и установил свой терморегулятор. Попутно можно заметить о попавшем в кадр кронштейне, который отключает в холодильнике освещение, если дверь закрыта. Это что-то!!! Он самый первый сломался, давно, почти сразу как купили холодильник. Пришлось его чуток переделать. Укрепить пластмассовыми распорками. Конструкция крайне плохая, посмотреть бы на того, кто это придумал улыбка. За давностью времён как-то подзабылось.

    Pic 12.

    Терморегулятор включен, датчик температуры заведён в холодильное отделение через штатное отверстие задней стороны холодильника. Идёт режим ожидания или отдыха компрессора.

    Режим ожидания. Компрессор выключен
    Pic 13. Режим ожидания. Компрессор выключен

    Терморегулятор включен. Идёт режим работы компрессора. Видно по свечению синего светодиода.

    Режим работы. Компрессор включился
    Pic 14. Режим работы. Компрессор включился

    Кроме индикации текущего времени работы, на экран выводится напряжение с терморезистора и напряжение уставки порога отключения компрессора. Дополнительной строчкой ниже выводится коэффициент производительности компрессора. Он расчитывается по формуле:

    K = Twork / (Twork + Trest), где
        
    K     – коэффициент производительности,
    Twork – время работы компрессора,
    Trest – время отдыха компрессора.
    

    Считается, что K должен быть в диапазоне 0,2...0,6, при этом чем меньше K, тем более эффективно работает компрессор. Для лучшего восприятия вывел значения коэффициента в %. Тогда диапазон будет: 20%...60%.

    Понаблюдал за работой нашего холодильника. В зависимости от того как часто открывается дверь, коэффициент был от 20% до 43%, что вполне приемлемо. Удобно по этому коэффициенту оценивать общую работу холодильника.

    Ранее уже делал терморегулятор (TR-1) для холодильника. В нём использовался цифровой датчик DS1820. В этом варианте (TR-2) несколько улучшений и использую доступный и недорогой терморезистор. Можно использовать не только MF52-10k, но и любой подходящий терморезистор.

    2020-02-18
    Анатолий Беляев.

     

    Приложение

    Используемые библиотеки и программы:


    . Mr.ALB
    Предыдущая страница Страница 14 Далее