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

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

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

     

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

    МТР-1.2
    (Модуль термометр-регулятор)

    На этой странице публикую скетч моего модуля термометра-регулятора (МТР-1.2). Для реализации вначале использовал Arduino UNO, а потом, когда пришла посылка с Arduino Nano, то переделал на него. Вообще можно использовать любой вариант, хоть бы и Arduino Pro Mini, если есть интерес уменьшить габариты.

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

    1. Термометр
    2. Нагреватель
    3. Охладитель
    со световой и звуковой индикацией.

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

    Схема для скетча #6
    Pic 1. Схема для скетча #6

    В качестве индикатора, использую 3-х разрядный 7-сегментный светодиодный индикатор. У меня это 3631AS – с общим анодом. На катоды установлены ограничивающие резисторы 2,2 кОм, чтобы минимизировать ток на сегменты.

    В схеме добавлены два индикаторных светодиода: красный – HL2 – показывает, что включено исполнительное реле К1 на нагрев, а когда модуль работает в режиме охладителя, то индикацию включения реле К1 указывает уже синий светодиод HL3. Сделал это для интуитивного воспринятия режима работы модуля термометра-регулятора. Начальный момент включения регулировки дополнительно сопровождается звуковой индикацией с помощью Buzzer-а (BZ1), для привлечения внимания к моменту включения управляющего сигнала.

    На диодах VD1, VD2 реализовано логическое устройство ИЛИ. Поэтому любой сигнал на нагрев или на охлаждение будет управлять реле К1.

    Датчик температуры использован DS18B20 – очень точный, надёжный и вообще хороший датчик. Никогда у меня с ним не было никаких проблем. Подключается по протоколу одного провода (OneWire). У меня он в качестве микросхемы в типовом корпусе ТО-92, а к нему припаян небольшой трёхжильный кабель. Продаются и влагозащищённые типы, удобны для измерения температуры воды или другой жидкой среды.

    DS18B20 в корпусе TO-92
    Pic 2. DS18B20 в корпусе TO-92
    DS18B20 влагозащищённый
    Pic 3. DS18B20 влагозащищённый

    Модуль К1 – самодельный. Вначале купил на алиэкспрессе модуль реле, но не обратил внимания, что у него управляющий сигнал низкого уровня (ноль). В моей же конструкции программа была написана под управляющий сигнал высокого уровня (единица), поэтому пришлось по-быстрому изготовить себе свой модуль реле. Габариты у него 42 * 16,5 * 16,5 мм, что чуть меньше, чем у покупного. А покупной модуль реле мне ещё пригодится в новых проектах, где будет учтена его особенность по управлению.

    Модули реле: самодельный и покупной
    Pic 4. Модули реле: самодельный и покупной
    Модули реле: самодельный и покупной. Обратная сторона
    Pic 5. Модули реле: самодельный и покупной. Обратная сторона
    Модуль реле самодельный
    Pic 6. Модуль реле самодельный

    Этот модуль реле самодельный, но его легко можно заменить и покупным, учитывая лишь, чтобы управляющий сигнал был высоким уровнем напряжения (единица).

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

    Звуковой излучатель пока – обычная ЗП. Подключен к порту Ардуино и управляется функцией tone(), потом хочу его заменить активным излучателем и управлять уровнем напряжения.

    Начальная реализация скетча #6. Без реле К1
    Pic 7. Начальная реализация скетча #6. Без реле К1

    При работе МТР-1.2 в режиме охладителя, видно как включился модуль реле К1 (индикация светодиода на плате модуля реле) и включился синий светодиод – режим охлаждения.

    Реализация скетча #6. С реле К1.<br>Работа в режиме ОХЛАДИТЕЛЯ
    Pic 8. Реализация скетча #6. С реле К1.
    Работа в режиме ОХЛАДИТЕЛЯ

    Далее переходим к скетчу (программе).

    Скетч модуля МТР-1.2

    Опубликованный скетч модуля можно скопировать (ссылка внизу) и вставить в свой Arduino IDE:

    /**********************************************************************
     * 2018-03-24 Mr.ALB Тренировка в программировании Ардуино
     *
     * Модуль Термометр-Регулятор - 1.x (МТР-1.x) на датчике DS18B20.
     * Значение выводим на индикатор 3631AS (3 разряда)
     ********************************************************
     * 2018-03-24 Mr.ALB MTR-1.0
     * 2018-05-10 Mr.ALB использование библиотеки Led4Digits 
     *                  http://mypractic.ru/ Урок 20
     *
     * 2018-05-11 Mr.ALB MTR-1.1
     * 2018-05-11 Mr.ALB сигнализация при выходе за пределы min и max t°C
     * 2018-05-12 Mr.ALB 1) добавлен гистерезис для min и max
     *                   2) добавлены кнопки:
     *                     а) выбор режима индикации
     *                     б) минус 0.1 к значению
     *                     в) плюс  0.1 к значению
     * 2018-05-15 Mr.ALB добавлена запись уставок в EEPROM... 
     *
     * 2018-05-18 Mr.ALB MTR-1.2  
     * 2018-05-18 Mr.ALB одна температура уставки + 
     *                   дельта + 
     *                   режим регулирования температуры
     *
     * Режим регулирования температуры:
     *   0 - без регулирования,
     *   1 - нагреватель,
     *   2 - охладитель
     *
     * 2018-06-15 Mr.ALB добавлен модуль реле
     * 2018-06-23 Mr.ALB добавлен зуммер
     *
     * Вывод на 3-х разрядный 7 сегментный индикатор 3631AS
     *
     * Соответствие контактов:
     * Ардуино  - 3631AS
     *   10    - DIG.0 pin12
     *   11    - DIG.1 pin9
     *   17(А3)- DIG.2 pin8
     *
     *   9     - A     pin11
     *   8     - B     pin7
     *   7     - C     pin4
     *   6     - D     pin2
     *   5     - E     pin1
     *   4     - F     pin10
     *   3     - G     pin5
     *   2     - DP    pin3
     * 
    **********************************************************************/
    
    /* Подключение библиотек */
    #include <EEPROM.h>    // для EEPROM
    #include <MsTimer2.h>  // для прерывания по таймеру 2
    #include <Led4Digits.h>// для семисегментного индикатора
    #include <Button.h>    // для кнопок
    #include <OneWire.h>   // для OneWire
    #include <DallasTemperature.h> // для Dallas Temperature
    
    /**********************************************************************
     *  Led4Digits 
       (
          byte typeLed, 
          byte digitPin0, byte digitPin1, byte digitPin2, byte digitPin3,
          byte segPinA, byte segPinB, byte segPinC, byte segPinD, 
          byte segPinE, byte segPinF, byte segPinG, byte segPinH
        );
    
    digitPin0 ... digitPin3 - выводы выбора разрядов, = 255 - разряд отключен
    typeLed:
      0 - Общий анод с ключами выбора разряда
      1 - Общий анод
      2 - Общий катод
      3 - Общий катод с ключами выбора разряда
      
    * Тип индикатора 1 - общий анод
    * Выводы разрядов:
    * 17,11,10 => DIG.2,DIG.1,DIG.0,noDIG(255) => (3631AS: 8,9,12,noDIG)
    * Выводы сегментов 9,8,7,6,5,4,3,2 => A,B,C,D,E,F,H,DP
    * 
    **********************************************************************/
    
    // Создаём объект индикатора
    Led4Digits disp(1, 17,11,10,255, 9,8,7,6,5,4,3,2);
    
    // Создаём объект oneWire
    #define ONE_WIRE_BUS 14 // Номер пина 14(A0) к которому подключен DS18B20
    OneWire oneWire(ONE_WIRE_BUS);
    
    // Создаём объект sensors типа DallasTemperature
    DallasTemperature sensors(&oneWire);
    
    // Переменные для DS18x20
    float temperature,// Температура с датчика
           set_temp=21.,// Уставка температуры
           delta_t=1.;// Гистерезис для температуры
    byte  addr[8], type_s;
    boolean flag_alarm;
    
    #define pinBUZZER 15 // ЗП на вывод 15(А1)
    #define pinLedT1  13 // Светодиод для индикации нагревателя
    #define pinLedT2  16 // Светодиод для индикации охладителя на вывод 16(А2)
    
    #define BUTTON_MENU_PIN  18 // номер вывода кнопки меню 18(А4)
    #define BUTTON_MINUS_PIN 19 // номер вывода кнопки уменьшить 19(A5)
    #define BUTTON_PLUS_PIN  12 // номер вывода кнопки увеличить
    
    /**********************************************************************
     * Button(byte pin, byte timeButton)
     * pin - контакт
     * timeButton - время (число) подтверждения
     * 
    **********************************************************************/
    // Создание объектов для кнопкок
    Button buttonMenu(BUTTON_MENU_PIN,18);  // для кнопки menu
    Button buttonMinus(BUTTON_MINUS_PIN,18);// для кнопки Минус
    Button buttonPlus(BUTTON_PLUS_PIN,18);  // для кнопки Плюс
    
    unsigned long tm, next_sec;// Переменные для времени (обновление значения)
    const unsigned int to_sec = 1000;// Обновление температуры через 1 секунду
    byte menu=0;   // Переменная для меню
    byte menu_last;// Переменная предыдущего п. меню
    int  mode_t;   // Режим регулирования температуры:
                    //    0 - без регулирования,
                    //    1 - нагреватель,
                    //    2 - охладитель
    
    // Адреса для сохранения уставок в EEPROM
    byte addrT=0;
    byte addrDeltaT=addrT+4;
    byte addrModeT=addrDeltaT+4;
    boolean flag_eeprom=false;
    
    float temp;// Переменная для временного значения
    
    /**********************************************************************
     * Настроечная функция, выполняется один раз вначале
    **********************************************************************/
    void setup()
    {
     pinMode(pinBUZZER, OUTPUT);
     pinMode(pinLedT1, OUTPUT);
     pinMode(pinLedT2, OUTPUT);
    
     MsTimer2::set(2, timerInterrupt);// прерывание по таймеру 2 мс
     MsTimer2::start();    // разрешение прерывания
     disp.digit[1] |= 0x80;// зажечь точку второго разряда
    
     sensors.begin();            // Старт датчика DS18x20
     sensors.getAddress(addr, 0);// Считывание адреса датчика
    
     // Установка значений из EEPROM
     set_temp = EEPROM_float_read(addrT);
     delta_t = EEPROM_float_read(addrDeltaT);
     mode_t = EEPROM_int_read(addrModeT);
    }
    
    /**********************************************************************
     * Функция loop() выполняется постоянно
    **********************************************************************/
    void loop()
    {
     /* Сканирование кнопок */
     buttonMenu.scanState();
     buttonMinus.scanState();
     buttonPlus.scanState();
    
     // Было нажатие кнопки "menu"
     if(buttonMenu.flagClick == true)
     {
       buttonMenu.flagClick = false;// Сброс признака клика
       menu++;// Переходим на следующий пункт
       if(menu > 3) menu=0;
    /**********************************************************************
        * Всего 4-е пункта меню:
        *  0 - индикация текущей температуры
        *  1 - T°C - уставка температуры
        *  2 - delta T°C - дельта температуры
        *  3 - режим регулирования температуры:
        *        0 - без регулирования, 
        *        1 - нагреватель, 
        *        2 - охладитель
    **********************************************************************/
     }
    
     tm = millis();// Получаем кол-во мс от начала работы программы
    
     if((tm > next_sec) && menu == 0)// Индикация текущей температуры
     {
       disp.digit[1] |= 0x80; // зажечь точку второго разряда
       next_sec = tm + to_sec;// Добавляем 1 секунду
    
       /* Чтение температуры */
       sensors.requestTemperatures();// Обновление значения датчика
       temperature = sensors.getTempC(addr);// Получение t°C
    
       /* Режим регулирования = НАГРЕВАТЕЛЬ */
       if((temperature < (set_temp - delta_t)) && mode_t == 1)
       {
         if(flag_alarm == false)
         {
           tone(pinBUZZER,1000,50);     // Звуковой сигнал
           digitalWrite(pinLedT1,HIGH);// Включение сигнализации нагрева RED
         }
         flag_alarm = true;// Подъём флага сигнализации
       }
       else if(flag_alarm && (temperature > set_temp) && mode_t==1)
       {
         flag_alarm = false;// Сброс флага сигнализации
         digitalWrite(pinLedT1,LOW);// Отключение сигнализации
       }
    
       /* Режим регулирования = ОХЛАДИТЕЛЬ */
       if((temperature > (set_temp + delta_t)) && mode_t == 2)
       {
         if(flag_alarm == false)
         {
           tone(pinBUZZER,1000,50);     // Звуковой сигнал
           digitalWrite(pinLedT2,HIGH);// Включение сигнализации охлаждения BLUE
         }
         flag_alarm = true;// Подъём флага сигнализации
       }
       else if(flag_alarm && (temperature < set_temp) && mode_t == 2)
       {
         flag_alarm = false;// Сброс флага сигнализации
         digitalWrite(pinLedT2,LOW);// Отключение сигнализации
       }
    
    /**********************************************************************
       * Выводим на индикатор текущую температуру:
       * Делаем умножение на 10
       * преобразуем в целое
       * и выводим на индикатор как целое значение
       * точку ставим во втором разряде => 
       * получается на индикаторе число с точкой
       * и десятичным значением после неё
       *
    **********************************************************************/
       disp.print(int(temperature * 10.), 3, 1);
     }
    
     /* Режимы установки параметров */
       if(menu == 1)// Уставка температуры
       {
         if(buttonMinus.flagClick == true)
         {
           buttonMinus.flagClick = false;// Сброс признака клика
           set_temp -= 0.1;
           flag_eeprom = true;// Взводим флаг записи в EEPROM
         }
         if(buttonPlus.flagClick == true)
         {
           buttonPlus.flagClick = false;// Сброс признака клика
           set_temp += 0.1;
           flag_eeprom = true;// Взводим флаг записи в EEPROM
         }
         disp.print(int(temperature * 10.), 3, 1);
       }
    
       if(menu == 2)// Уставка дельты
       {
         if(buttonMinus.flagClick == true)
         {
           buttonMinus.flagClick = false;// Сброс признака клика
           delta_t -= 0.1;
           flag_eeprom = true;// Взводим флаг записи в EEPROM
         }
         if(buttonPlus.flagClick == true)
         {
           buttonPlus.flagClick = false;// Сброс признака клика
           delta_t += 0.1;
           flag_eeprom = true;// Взводим флаг записи в EEPROM
         }
         disp.print(int(delta_t * 10.), 3, 1);// Выводим на индикатор дельту
       }
       if(menu == 3)// Уставка режима регулирования температуры
       {
         if(buttonMinus.flagClick == true)
         {
           buttonMinus.flagClick = false;// Сброс признака клика
           mode_t --;
           if(mode_t < 0) mode_t=2;
           flag_eeprom = true;// Взводим флаг записи в EEPROM
         }
         if(buttonPlus.flagClick == true)
         {
           buttonPlus.flagClick = false;// Сброс признака клика
           mode_t ++;
           if(mode_t > 2) mode_t=0;
           flag_eeprom = true;// Взводим флаг записи в EEPROM
         }
         disp.digit[1] &= 0x7f;// потушить точку второго разряда B01111111
         disp.print(mode_t, 3, 1);// Выводим на индикатор
       }
    
       /* Запись изменённых значений в EEPROM */
       if(flag_eeprom && menu_last != menu)
       {
         switch(menu_last)
         {
           case 1:
             // Чтение значения Т°C из памяти
             temp = EEPROM_float_read(addrT);
             if(set_temp != temp) EEPROM_float_write(addrT, set_temp);
             break;
    
           case 2:
             // Чтение значения delta_t из памяти
             temp = EEPROM_float_read(addrDeltaT);
             if(delta_t != temp) EEPROM_float_write(addrDeltaT, delta_t);
             break;
    
           case 3:
             // Чтение значения mode_t из памяти
             temp = EEPROM_float_read(addrModeT);
             if(mode_t != int(temp)) EEPROM_float_write(addrModeT, mode_t);
             /* При смене mode_t отключаем бывшие оповещения */
             digitalWrite(pinLedT1,LOW);
             digitalWrite(pinLedT2,LOW);
         }
    
         flag_eeprom = false;// Сбрасываем флаг записи в EEPROM
       }
    
       menu_last = menu;// Перезаписываем режим
    
    }// Конец loop()
    
    /* Обработчик прерывания 2 мс */
    void timerInterrupt()
    {
      disp.regen();// регенерация индикатора
    }
    
    /**********************************************************************
     * Функции для работы с EEPROM 
    **********************************************************************/
    /*  Чтение float из EEPROM  */
    float EEPROM_float_read(int addr)
    {
     byte raw[4];
     for(byte i = 0; i < 4; i++)
     {
       raw[i] = EEPROM.read(addr+i);
     }
     float &num = (float&)raw;
     return num;
    }
    
    /*  Запись float в EEPROM  */
    void EEPROM_float_write(int addr, float num)
    {
     byte raw[4];
     (float&)raw = num;
     for(byte i = 0; i < 4; i++)
     {
       EEPROM.write(addr+i, raw[i]);
     }
    }
    
    /*  Чтение int из EEPROM  */
    int EEPROM_int_read(int addr)
    {
     byte raw[2];
     for(byte i = 0; i < 2; i++)
     {
       raw[i] = EEPROM.read(addr+i);
     }
     int &num = (int&)raw;
     return num;
    }
    
    /*  Запись int в EEPROM  */
    void EEPROM_int_write(int addr, int num)
    {
     byte raw[2];
     (int&)raw = num;
     for(byte i = 0; i < 2; i++)
     {
       EEPROM.write(addr+i, raw[i]);
     }
    }
    
    
    

    Код закоментирован достаточно подробно и понятно.

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

    Для управления семисегментным индикатором используется скачанная библиотека Led4Digits.h. В общем мне эта библиотека очень понравилась, с большими возможностями и легко применять. Однако, при такой конструкции, у Ардуино все порты вывода заняты, и в основном этим 3-х разрядным семисегментным индикатором. Подумываю использовать сдвиговые регистры SN74HC595 для управления индикатором и тем самым освободить порты от индикатора... возможно код управления индикатором опубликую на следующих страницах и проектах, а пока так как есть.

    Скетч можно скачать тут: my_MTR-1_2_s.zip

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

    DallasTemperature.zip
    Led4Digits.zip
    LoRa_Node.zip
    MsTimer2.zip
    OneWire.zip

    2018-07-23
    . Mr.ALB
    Предыдущая страница Страница 7 Далее