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

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

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

     

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

    Часы на RTC DS3231, с расширенными функциями

    Этот проект является продолжением раннего проекта часов Часы на RTC DS3231 и TM1637. По просьбе моего знакомого Константина К. добавил вывод на экран дисплея температуру. А потом вспомнил, что читатели сайта просили добавить будильник, что и сделал. Потом дошла очередь и до барометра. Получились не обычные такие часы, а часы с расширенными функциями улыбка.


    При модернизировании предыдущего проекта #8 Часы на RTC DS3231 и TM1637 вышло, что проще написать всё по новому, поэтому программа была написана заново. Схема тоже усложнилась добавлением разными компонентами.

     


    Схема часов

    Схема часов немного сложнее, чем в предыдущем проекте. Добавлен активный Buzzer для сигнала будильника. Добавлен светодиод для индикации активности будильника. Добавлена ещё одна кнопка для установки будильника. Добавлен датчик температуры DS1820. Добавлен модуль абсолютного давления BMP280. Замечу, что для него требуется напряжение питания +3,3В. Если использовать Arduino Uno R3 или Arduino Nano, то у них на платах уже имеется стабилизатор на +3,3В. Если же использовать Arduino Pro Mini, то придётся добавить такой стабилизатор дополнительно или, как вариант, запитать датчик от +5В через два последовательно соединённых диода 1N4148.

    Блок питания используется импульсный, обратноходовый. Выдаёт +6.5 В. Это напряжение подаётся на стабилизатор Arduino Pro Mini – на контакт RAW. Можно использовать БП на +5В, но тогда подавать питание нужно на контакт VCC.

    Выключатель SA2 можно не ставить. Работающий будильник можно отключить нажав на кнопку ALARM.

    Схема электрическая принципиальная для скетча #21
    Pic 1. Схема электрическая принципиальная для скетча #21

    Монтажную схему см. ниже. Резистор R2 можно ставить от 4.7кОм до 12кОм. Чем больше сопротивление, тем тусклее будет светить светодиод HL2. Вполне нормально светит при R2 = 10кОм.

    Схема монтажная для скетча #21
    Pic 2. Схема монтажная для скетча #21


    Скетч часов

    Далее представлен скетч. Рассмотрю некоторые его особенности. В предыдущем проекте у автора для мигания точек используется сигнал с модуля реального времени с контакта SQW, который подаётся на контакт 2 Ардуино. Но оказывается не все модули имеют такой сигнал и чтобы сделать программу более универсальную – отказался от этого и мигание точек делаю за счёт Timer1.

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

    Во время начального теста, если датчик DS1820 не подключен, то на индикаторе выводится 2 секунды тип 3231 встроенного датчика температуры DS3231. Если датчик температуры DS1820 подключен, то выводится его тип 1820 2 секунды. После чего выводится разрешение датчика в 3-м и 4-м разрядах 2 секунды. Максимальное разрешение датчика DS1820 равно 12 бит. Далее, если подключен датчик абсолютного давления BMP280, то на индикаторе на 2 секунды выводится сообщение 280P. Если в схеме нет датчика абсолютного давления BMP280, то программа переходит к выводу времени.

    Весь код подробно закомментирован, с его пониманием, надеюсь, проблем не будет. Хочу лишь обратить внимание, что когда происходит запись значения в EEPROM, то индикатор гашу на 1 секунду, чтобы видеть, что команда записи отработала – индикация записи.

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

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

    /*********************************************************************
       2021-11-30 Mr.ALB Начало проекта
       Создание часов с расширенными функциями:
    
       Часы на 4-х разрядном 7 сегментном индикаторе TM1637
       и модуле реального времени DS3231 + датчик температуры
       встроенный в DS3231 и датчик температуры внешний DS1820
       http://mralb.ru/sections/programming/arduino_21.php
    
       Основа:
       ©2018-11-25 Mr.ALB Часы на RTC DS3231 и TM1637
       http://mralb.ru/sections/programming/arduino_8.php
    
    
       ПОДКЛЮЧЕНИЕ:
    
       Модуль RTC DS3231:
         SCL - A5
         SDA - A4
         VCC - 5V
         GND - GND
    
       Кнопки управления подключить на пины и на GND
    
       Датчик DS1820:
         1 GND - GND
         2 DQ  - через 4.7кОм к VCC, и DQ к pin11
         3 VCC - 5V
    
       Buzzer - любой активный на 5 В. К pin13
    
       ИСТОРИЯ ИЗМЕНЕНИЙ:
    
       2021-11-30 MrALB v2.0 Переделка на библиотеку <DS3231.h>
                  вывод температуры со встроенного датчика температуры
                  модуля времени DS3231
                  вывод SQW не используется, мигание точек через Timer1
       2021-12-01 MrALB Добавлен будильник
       2021-12-02 MrALB v2.1 Добавлен датчик температуры DS1820
                  Примечание: Если нет датчика DS1820, то температура
                              выводится по датчику DS3231
      2021-12-04 Mr.ALB Доработка, отладка
      2021-12-05 Mr.ALB Добавлен модуль давления BMP280
      2021-12-07 Mr.ALB Оптимизация
      2021-12-08 Mr.ALB Оптимизация
      2021-12-22 Mr.ALB Вывод отрицательных температур
                        На ногу 2 присоединить через резистор 1к светодиод,
                        он будет показывать минус,
                        когда температура отрицательная.
                        В библиотеку TM1637 добавлен минус
      2021-12-25 Mr.ALB Оптимизация + переделка сигнала будильника
      2021-12-26 Mr.ALB Оптимизация + вкл/выкл. будильника
      2022-01-02 Константин К. функция проверки сегментов при включении
      2022-01-04 Mr.ALB Оптимизация кода
      2022-01-05 Mr.ALB Константик К. выявил ошибку:
                        При настройке яркости возникает отставание времени
                        из-за обнуления секунд.
                        Ошибка устранена.
    
     ***** ОПИСАНИЕ *****
      КНОПКИ:
      [Set]         - Установка
      [ALARM]       - Будильник
      [H]           - Час
      [M]           - Минута
      [Brightness]  - Яркость
    
      При включении идёт тестирование подключения датчика температуры DS1820.
    
      Если датчик не подключен, то на индикаторе выводится 2 секунды
      тип "3231" встроенного датчика температуры DS3231.
    
      Если датчик температуры DS1820 подключен, то выводится
      его тип "1820" 2 секунды.
      Далее выводится разрешение датчика в 3-м и 4-м разрядах 2 секунды.
    
      Для настройки времени, нажать кнопку [Set] и удерживая её
      нажимать кнопки [H] и [M] для задания требуемого времени.
      В начальный момент настройки на дисплее выводится текущее время.
    
      Для задания уставки будильника нажать кнопку [ALARM] и удерживая её
      нажимать кнопки [H] и [M] для задания требуемого времени
      срабатывания будильника. В начальный момент настройки на дисплее
      выводится заданное ранее время будильника.
    
      Для включения будильника нажать кнопку  [ALARM] 1...2 секунды.
      При включении будильника засветится светодиод HL2 - Будильник установлен.
    
      Для отключения будильника, при светящемся HL2, нажать кнопку  [ALARM]
      1...2 секунды. Индикация отключения будильника - потухший светодиод HL2.
    
      Для установки уровня яркости индикатора, нажать кнопку [Set] и удерживая
      её нажимать кнопку [Brightness]. Всего 7 градаций яркости.
      Изменение идёт по кругу от 1 до 7 и заново.
    
      Примечание: Из-за дребезга кнопок возможно недосрабатывание
      - повторить манипуляции с кнопками.
    
      Архив: 
      Библиотеки https://disk.yandex.ru/d/GAB2psiXtsH8cg
      Скетч https://disk.yandex.ru/d/WRQKZAjv9D3PKw
      
    ******************************************************************/
    
    #include <Wire.h>               // Для I2C
    // Для индикатора 4-х разрядного 7 сегментного + дополнения
    #include "TM1637_mralb.h"       // Изменённая библиотека
    #include <DS3231.h>             // Для часов реального времени
    #include <TimerOne.h>           // Подключение библиотеки Таймер1
    #include <OneWire.h>            // OneWire для DS1820
    #include <EEPROM.h>             // Для EEPROM, запись яркости
    #include <DallasTemperature.h>  // Для DS1820
    #include <Adafruit_BMP280.h>    // для BMP280
    
    // Установка OneWire на Pin11, к которому подключен DS18B20
    #define ONE_WIRE_BUS 11 
    OneWire oneWire(ONE_WIRE_BUS);
    
    // Установка DallasTemperature для работы по OneWire
    DallasTemperature sensors(&oneWire);
    
    // Переменные для DS1820
    float term;
    byte addr[8], type_s;
    byte resolution;
    bool flagDS;                // Флаг наличия DS1820
    bool flagMinusTerm = false; // Флаг отр. темпер.
    
    // 4-х разрядный 7 сигментный индикатор TM1637
    #define CLK 6
    #define DIO 7
    
    TM1637 tm1637(CLK, DIO);    // Создание объекта индикатора
    
    DS3231 clock;               // Создание объекта часов
    RTCDateTime dt;             // Перемен. времени
    RTCAlarmTime da;            // Перем. будильника
    
    /***********************************************************
     Чтобы всё заработало необходимо
     1. Сканером I2C найти адрес BMP280
       или в библиотеке <Adafruit_BMP280.h>
    
      1)  Изменить адрес  #define BMP280_ADDRESS (0x77)
          на адрес        #define BMP280_ADDRESS (0x76)
      2)  Закоментировать библиотеку #include <Adafruit_Sensor.h>
     ***********************************************************/
    Adafruit_BMP280 bmp;// Создаём объект барометра
    
    /*************************************************
       мБар       - мм рт. ст.
       1013.2472  - 760 k=1.33322
       1005.24788 - 754
     *************************************************/
    // Коэффициент для перевода Па в мм рт.ст.
    float kp = 133.322;
    
    // Переменные давления
    float press_now;
    
    // Кнопки установки времени
    #define buttonHour    5   // Часы
    #define buttonMin     4   // Минуты
    #define buttonSet     3   // Установка
    #define buttonBR      8   // Кнопка яркости
    #define buttonAlarm   9   // Кнопка установки будильника
    #define PIN_ALARM_SET 10  // Индикатор установки будильника
    
    byte brightness = 1;      // Яркость, от 1 до 7 2020-01-02
    byte addrBR = 6;          // Адрес в EEPROM для записи яркости
    boolean flag_br = false;  // Флаг для записи яркости
    boolean flag_null = false;// Флаг для гашения незначащего нуля
    
    // Переменная для прерывания мигания точек
    volatile boolean flag;
    
    int8_t TimeDisp[4];       // Массив для цифр индикатора
    
    #define SECTIME 10000000  // 10 секунд
    #define SECTERM 2000000   // 2 секунды
    
    
    bool flag_time = true;
    bool flag_alarm = false;
    bool flag_alarm_set = false;
    int32_t time_now, time_check; // Интервал времени
    
    bool flagInterrupt;       // Флаг прерывания
    bool flagPress = false;   // Флаг давления
    
    byte typeDataDisplay = 0; // Тип выводимых данных:
                              //  0 - время
                              //  1 - температура
                              //  2 - давление
    
    /*********************
       Настройка скетча
     *********************/
    void setup()
    {
      pinMode(buttonHour, INPUT_PULLUP);  // Кнопка изменения часов
      pinMode(buttonMin, INPUT_PULLUP);   // Кнопка изменения минут
      pinMode(buttonSet, INPUT_PULLUP);   // Кнопка разрешения установок
      pinMode(buttonAlarm, INPUT_PULLUP); // Кнопка установок будильника
      pinMode(buttonBR, INPUT_PULLUP);    // Кнопка изменения яркости
      pinMode(LED_BUILTIN, OUTPUT);       // Активный буззер будильника
      pinMode(PIN_ALARM_SET, OUTPUT);     // Светодиод устав.будильника
      digitalWrite(LED_BUILTIN, LOW);     // Выключим светодиод на pin13
    
      clock.begin();                      // Старт часов
    
      tm1637.init();                      // Инициализация индикатора
      tm1637.set(brightness);             // Установка начальной яркости
      fnDisplayTest();                    // Проверка всех сегментов
    
      // Установка значений из EEPROM
      // Считывание яркости из EEPROM 2020-01-02
      byte setBR = EEPROM.read(addrBR);
      if (setBR >= 0 && setBR < 8 && setBR != brightness)
        tm1637.set(setBR);
    
      // Инициализация прерывания на 500 мс
      Timer1.initialize(500000);
      time_now = micros();    // Текущее время
      time_check = time_now;  // Установка начала интервала
    
      // Старт установки датчика DS1820
      sensors.begin();
      flagDS = false;         // Нет датчика DS1820
    
      // Установка в массив типа датчика 3231
      TimeDisp[0] = 3;
      TimeDisp[1] = 2;
      TimeDisp[2] = 3;
      TimeDisp[3] = 1;
    
      // Проверяем наличие DS1820
      if (sensors.getAddress(addr, 0))
      {
        flagDS = true;  // Подключен DS1820
    
        /* Определяем устройство и его параметры */
        //Считываем точность датчика
        resolution = sensors.getResolution();
        if (resolution < 10) sensors.setResolution(10);
    
        // Вывод на индикаторе типа датчика 1820
        TimeDisp[0] = 1;
        TimeDisp[1] = 8;
        TimeDisp[2] = 2;
        TimeDisp[3] = 0;
        fnDisplay(flag_time);
        delay(2000); // 2 секунды
    
        // Вывод разрешения/точности измерения
        TimeDisp[0] = 18; // Пусто
        TimeDisp[1] = 18;
        TimeDisp[2] = resolution / 10;
        TimeDisp[3] = resolution % 10;
      } // End setup DS1820
    
      tm1637.point(POINT_OFF);  // Выключить точки
      fnDisplay(flag_time);     // Вывод на индикатор
      delay(2000);              // 2 секунды
    
      if (bmp.begin())          // Check bmp280
      {
        flagPress = true;       // Подключен датчик BMP280
        // Выводим на индикатор 280P
        TimeDisp[0] = 2;
        TimeDisp[1] = 8;
        TimeDisp[2] = 0;
        TimeDisp[3] = 17; // Символ P
        fnDisplay(flag_time);
        delay(2000);      // 2 секунды
      } // End check bmp280
    
    } // End setup()
    
    
    /**************************
     *** Основная программа ***
     **************************/
    void loop()
    {
      // Читаем время из модуля DS3231
      dt = clock.getDateTime();
    
      // Проверка будильника
      fnCheckAlarms();
    
      // Проверка интервала времени для индикации
      time_now = micros();
      if
      (
        time_now - time_check > SECTIME &&
        typeDataDisplay == 0
      )
      {
        // Переход к индикации температуры
        time_check = time_now;
        flag_time = false;
        typeDataDisplay = 1;
      }
    
      if
      (
        flagPress &&
        (time_now - time_check > SECTERM) &&
        typeDataDisplay == 1
      )
      {
        // Переход к индикации давления
        flag_time = false;
        typeDataDisplay = 2;
      }
    
      if
      (
        (
          flagPress &&
          (time_now - time_check > (SECTERM + SECTERM)) &&
          typeDataDisplay == 2
        ) ||
        (
          !flagPress &&
          (time_now - time_check > SECTERM) &&
          typeDataDisplay == 1
        )
      )
      {
        // Переход к индикации времени
        flag_time = true;
        typeDataDisplay = 0;
      }
    
      fnTimeDisp(flag_time, false);// Заполняем массив
    
      /***************************************************
        Обработка кнопок для установки времени и яркости
        Изменения при одновременном совместном нажитии
        на кнопку buttonSet и кнопки управления H или M<
      */
      while (!digitalRead(buttonSet)) // SET H:M o BR
      {
        dt = clock.getDateTime();
    
        //Заполняем массив значений
        fnTimeDisp(flag_time, false);
        // Выводим на индикатор заполненный массив
        fnDisplay(flag_time);
    
        // 2022-01-05 Mr.ALB устранение ошибки настройки
        if (!digitalRead(buttonBR))
        { // Настройка яркости индикатора
          brightness++;
          if (brightness > 7) brightness = 1;
          tm1637.set(brightness);
          flag_br = true;
        }
        else // Настройка не яркости, а времени
        {
          if (!digitalRead(buttonHour))
          { // Часы
            dt.hour++;         // Прибавляем единицу к часам
            if (dt.hour > 23) dt.hour = 0;
            fnSetTime();      // Установка времени
          }
          if (!digitalRead(buttonMin))
          { // Минуты
            dt.minute++;       // Прибавляем единицу к минутам
            if (dt.minute > 59) dt.minute = 0;
            fnSetTime();       // Установка времени
          }
        }
        delay(200);
      } // End SET H:M o BR
    
    
    
      /***************************************************
        Обработка кнопок для установки будильника
        Изменения при одновременном совместном нажитии
        на кнопку buttonAlarm и кнопки управления H или M
      */
      while (!digitalRead(buttonAlarm))
      {
        da = clock.getAlarm1();
        //Заполняем массив значений будильника
        fnTimeDisp(flag_time, true);
        // Выводим на индикатор
        fnDisplay(flag_time);
    
        if (!digitalRead(buttonHour))
        { // Часы
          da.hour++;  // прибавляем единицу к часам
          if (da.hour > 23) da.hour = 0;
          flag_alarm_set = false;
        }
    
        if (!digitalRead(buttonMin))
        { // Минуты
          da.minute++;
          if (da.minute > 59) da.minute = 0;
          flag_alarm_set = false;
        }
    
        /* Функция установки времени будильника в DS3231 */
        // Установка времени будильника
        clock.setAlarm1
        (
          0,
          da.hour,
          da.minute,
          0,
          DS3231_MATCH_H_M_S
        );
    
        // Вкл./Выкл. будильника
        flag_alarm_set = !flag_alarm_set;
        delay(150);
      }
    
      // Вкл./Выкл. индикации активности будильника
      if (flag_alarm_set && !digitalRead(PIN_ALARM_SET))
        digitalWrite(PIN_ALARM_SET, HIGH);
    
      if (!flag_alarm_set && digitalRead(PIN_ALARM_SET))
      {
        digitalWrite(PIN_ALARM_SET, LOW);
        // Выключаем сигнал, если он есть
        digitalWrite(LED_BUILTIN, LOW);
      }
    
      // Запись значения яркости в EEPROM
      // при отжатой кнопке buttonSet
      if (flag_br == true && digitalRead(buttonSet) == HIGH)
      {
        flag_br = false;
        Timer1.detachInterrupt();     // Остановка прерывания
        EEPROM.write(addrBR, brightness);
    
        // Гашение экрана как индикация записи
        tm1637.clearDisplay();
        delay(100);
        Timer1.attachInterrupt(blink);// Включение прерывания
      }
    
      // Выводим на индикатор массив с данными
      fnDisplay(flag_time);
    }
    
    
    /***********************************************
                   *** Подпрограммы ***
     ***********************************************/
    
    /********************************************
     * Функция установки времени часов в DS3231
     * Секунды сбрасываем в 0
     * 2022-01-04 Mr.ALB
     *******************************************/
    void fnSetTime()
    {
      clock.setDateTime
      (
        dt.year,
        dt.month,
        dt.day,
        dt.hour,
        dt.minute,
        0
      );
    }
    
    /*****************************************
     * Функция проверки всех сегментов
     * тест сегментов, поджигаем все на 2 сек
     * 2022-01-02 Константин К.
     ****************************************/
    void fnDisplayTest()
    {
      TimeDisp[0] = 8;
      TimeDisp[1] = 8;
      TimeDisp[2] = 8;
      TimeDisp[3] = 8;
      tm1637.point(POINT_ON);   // Включить точки
      fnDisplay(flag_time);
      delay(2000);              // 2 секунды горят все сегменты
      tm1637.point(POINT_OFF);  // Выключить точки
      tm1637.clearDisplay();    // Гашение экрана
      delay(200);               // 0.2 секунды
    }
    
    /*************************
     * Функция мигания точек
     ************************/
    void blink()
    {
      flag = !flag;
      tm1637.point(flag);
    }
    
    /**********************
     * Проверка будильника
     * 2021-12-25 Mr.ALB
     **********************/
    void fnCheckAlarms()
    {
      if
      (
        clock.isAlarm1() &&
        flag_alarm == false &&
        flag_alarm_set
      )
      {
        // Сработал будильник
    
        // Заполняем массив значений временем
        // т.к. должны всегда видеть время в
        // момент срабатывания будильника
        fnTimeDisp(true, false);
        tm1637.point(POINT_ON); // Включить точки
        // Выводим на индикатор массив с данными
        fnDisplay(flag_time);
    
        // Поднятие флага будильника
        flag_alarm = true;
    
        // Включаем сигнал
        // Сигнал пульсирующий
        // .5 секунды звук
        // .5 секунды пауза
    
        long t;
        for (byte j = 0; j < 28; j++)
        {
          t = millis();
          while (millis() - t < 500)
          {
            // Звук .5 секунды
            digitalWrite(LED_BUILTIN, HIGH);
            // Если нажата кнопка Будильник
            if (!digitalRead(buttonAlarm))
            {
              flag_alarm = false;
              break;
            }
          }
    
          t = millis();
          while (millis() - t < 500)
          {
            // Пауза .5 секунды
            digitalWrite(LED_BUILTIN, LOW);
            // Если нажата кнопка Будильник
            if (!digitalRead(buttonAlarm))
            {
              flag_alarm = false;
              break;
            }
          }
    
          // Если нажата кнопка Будильник
          if (!digitalRead(buttonAlarm))
          {
            flag_alarm = false;
            break;
          }
        }
    
        if (flag_alarm == false)
          // Выключить звук
          digitalWrite(LED_BUILTIN, LOW);
      }
    }
    
    /**********************
     * Вывод на индикатор
     **********************/
    void  fnDisplay(bool flgT)
    {
      if (!flgT) // Если выводим температуру или давление
        tm1637.point(POINT_OFF);// Выключить точки
    
      // Вывод значений на индикатор
      if (TimeDisp[0] != 0)
      { // Если первое значение не 0, то выводим
        if (flag_null) flag_null = false; // Сбросим флаг нуля
        tm1637.display(0, TimeDisp[0]);   // Вывод первой цифры
      }
      else if (!flag_null)
      {
        // Иначе гашение незначащего нуля
        // Гасим один первый раз при смене на 0
        flag_null = true;             // Выставим флаг нуля
        tm1637.display(0, 18);        //Гасим 0 разряд
      }
    
      tm1637.display(1, TimeDisp[1]); // Вывод второй цифры
      tm1637.display(2, TimeDisp[2]); // Вывод третьей цифры
      tm1637.display(3, TimeDisp[3]); // Вывод четвёртой цифры
    }
    
    /*******************************
     * Массив значений на индикатор
     *******************************/
    void fnTimeDisp(bool flgT, bool flagSetAlarm)
    {
      // Заполняем массив значениями для отпаравки на индикатор
      if (flgT)
      { // Флаг вывода времени
        if (flagInterrupt == false)
        {
          flagInterrupt = true; // Флаг прерывания ON
          // Подключение прерывания для мигания точек
          Timer1.attachInterrupt(blink);
        }
    
        if (flagSetAlarm == true)
        { // Если флаг настройки будильника
          // Заполняем массив значениями будильника
          TimeDisp[0] = da.hour / 10;  // Десятки часов
          TimeDisp[1] = da.hour % 10;  // Единицы часов
          TimeDisp[2] = da.minute / 10;// Десятки минут
          TimeDisp[3] = da.minute % 10;// Единицы минут
          tm1637.point(POINT_ON);// Включить точки
        }
        else
        { // Иначе
          // Заполняем массив значениями времени
          TimeDisp[0] = dt.hour / 10;  // Десятки часов
          TimeDisp[1] = dt.hour % 10;  // Единицы часов
          TimeDisp[2] = dt.minute / 10;// Десятки минут
          TimeDisp[3] = dt.minute % 10;// Единицы минут
        }
      }
      else
      { // Иначе если флаг не времени, то
        // Заполняем массив значениями температуры
        // Остановка прерывания, чтобы точки не мигали
        Timer1.detachInterrupt();
        flagInterrupt = false;
    
        if (typeDataDisplay == 1)
        {
          // Получение значения температуры
          if (flagDS)
          { // Если есть DS1820
            // Обновление значения датчика DS1820
            sensors.requestTemperatures();
            term = sensors.getTempC(addr);
    
            // Обработка отрицательных температур--
            if (term < 0 && flagMinusTerm == false)
              // Выставим флаг отр. температуры
              flagMinusTerm = true;
    
            if (term > 0 && flagMinusTerm == true)
              // Снимаем флаг отр. температуры
              flagMinusTerm = false;
    
            // Значение температуры переводим в
            // Абсолютное значение
            term = abs(term);
            //-------------------------------------
          }
          else
          {
            // Если нет DS1820, то
            // Читаем температуру из DS3231
            term = clock.readTemperature();
          }
    
          // Заполняем массив для вывода на индикатор
          if (flagMinusTerm)
          {
            TimeDisp[0] = 19; //Минус
            if (term < 10)
            {
              TimeDisp[1] = (int)term;// Единицы t°
              TimeDisp[2] = 16;       // Символ ° - градус
              TimeDisp[3] = 12;       // Символ C - Цельсия
              // На индикаторе типа: -9°C
            }
            else
            {
              TimeDisp[1] = (int)term / 10;  // Десятки t°
              TimeDisp[2] = (int)term % 10;  // Единицы t°
              TimeDisp[3] = 16;   // Символ ° - градус
              // На индикаторе типа: -26°
            }
          }
          else
          { // Иначе, если температура положительная
            TimeDisp[0] = (int)term / 10;  // Десятки t°
            TimeDisp[1] = (int)term % 10;  // Единицы t°
            TimeDisp[2] = 16; // Символ ° - градус
            TimeDisp[3] = 12; // Символ C - Цельсия
            // На индикаторе типа: 26°C
          }
        }
    
        if (flagPress && typeDataDisplay == 2)
        { // Если подключен датчик BMP280
          // Считывание давления и переводим в мм рт. ст.
          // +0.5 мм рт.ст. – поправка при калибровке
          // (укажите значение своей поправки)
          press_now = bmp.readPressure() / kp + .5;
    
          // Заполняем массив для вывода на индикатор
          TimeDisp[0] = (int)press_now / 100;
          TimeDisp[1] = (int)(press_now - TimeDisp[0] * 100) / 10;
          TimeDisp[2] = (int)(press_now - TimeDisp[0] * 100) % 10;
          TimeDisp[3] = 17; // Символ P - Давление
          // На индикаторе типа: 754P
        }
      }
    }
    
    

    Перечень элементов

    1. U1 – Arduino UNO R3, Arduino Pro Mini или другое.
    2. U2 – Модуль питания AC-DC на 5...6 В.
    3. U3 – Модуль стабилизатора на +3,3 В, если нет на плате Arduino.
    4. U4 – Модуль датчика абсолютного давления BMP280 (допустимо без него).
    5. DD1 – Датчик температуры семейства DS1820 (допустимо без него).
    6. RTC1 – Модуль реального времени DS3231.
    7. R1 – Резистор 4.7 кОм (при наличии датчика DS1820).
    8. R2 – Резистор 10 кОм (4.7кОм...12кОм).
    9. HL1 – Дисплей 4-х разрядный 7-и сегментный TM1637.
    10. HL2 – Светодиод красный.
    11. SA1 – Выключатель (любой).
    12. SA2 – Выключатель (любой).
    13. SB1...SB5 – Микрокнопка (любая).
    14. BA1 – Buzzer активный.

    Конструкция часов

    Законченной конструкции на данный момент у меня нет. Всё собиралось на макетных панельках с использованием Arduino Uno R3. Возможно, что впоследствии, как будет сделана законченная конструкция, то тут добавлю фото реализации.

    Далее несколько фото макетного варианта.

    Мой макетный вариант. Вывод времени
    Pic 3. Мой макетный вариант. Вывод времени
    Мой макетный вариант. Вывод температуры
    Pic 4. Мой макетный вариант. Вывод температуры
    Мой макетный вариант. Вывод атмосферного давления
    Pic 5. Мой макетный вариант. Вывод атмосферного давления

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

    Часы с mp3 проигрывателем. Вывод времени
    Pic 6. Часы с mp3 проигрывателем. Вывод времени
    Часы с mp3 проигрывателем. Вывод температуры с датчика DS18B20
    Pic 7. Часы с mp3 проигрывателем. Вывод температуры с датчика DS18B20
    Часы с mp3 проигрывателем. Вывод атмосферного давления
    Pic 8. Часы с mp3 проигрывателем. Вывод атмосферного давления

    Далее фото конструкции. Как всё устроено внутри.

    Часы с mp3 проигрывателем. Платы часов
    Pic 9. Часы с mp3 проигрывателем. Платы часов
    Часы с mp3 проигрывателем. Платы часов
    Pic 10. Часы с mp3 проигрывателем. Платы часов
    Часы с mp3 проигрывателем. Задняя крышка снята
    Pic 11. Часы с mp3 проигрывателем. Задняя крышка снята
    Часы с mp3 проигрывателем. Задняя крышка и панель с платами
    Pic 12. Часы с mp3 проигрывателем. Задняя крышка и панель с платами
    Часы с mp3 проигрывателем. Самодельный индикатор
    Pic 13. Часы с mp3 проигрывателем. Самодельный индикатор

    Сзади на крышке установлены кнопки управления и отверстия под звуковой излучатель.

    Часы с mp3 проигрывателем. Вид сзади
    Pic 14. Часы с mp3 проигрывателем. Вид сзади
    Часы с mp3 проигрывателем. Вид индикатора в темноте
    Pic 15. Часы с mp3 проигрывателем. Вид индикатора в темноте

    Часы с mp3 проигрывателем

    Продолжительность фильма 0:39 [мм:сс]

    В этом видео демонстрация работы звукового сигнала в конструкции Константина К.
    . Ссылка: #1



    Доработка

    Переделка на вариант без bmp280. Тогда скетч использует всего 10066 байт и его можно записать в AVR ATMega168P. Этот скетч можно скачать по ссылке ниже.

    Доработка скетча для вывода на индикатор отрицательных температур. Если датчик DS1820 сделать внешним, то можно измерять внешние температуры в диапазоне от -55°С до +125°С. Чтобы этот скетч работал, скачайте изменённую библиотеку TM1637_mralb, которая находится в архиве: my_Clock_Lib.rar

    Константик К. выявил ошибку: При настройке яркости возникает отставание времени из-за обнуления секунд. Ошибка устранена.

    Приложение

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

    2021-12-04
    2021-12-22
    2022-01-05
    Спасибо за внимание!
    Анатолий Беляев

    Yoomoney.ru
    Есть возможность другим способом оказать помощь на развитие сайта


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