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

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

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

     

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

    Погодная станция на BME280 + DS1820

    Используя раннюю разработку программы Барометр c разными системами измерения давления создаю небольшую, можно сказать, карманную погодную станцию.

    Добавив цифровой датчик ф. Даллас DS18B20 к уже имеющемуся датчику BME280 получаем, что наше устройство может измерять:

    • Абсолютное атмосферное давление (в мм рт. ст. или в кПа).
    • Высоту (относительную, в метрах).
    • Внутреннюю температуру с BME280 (в °С).
    • Относительную влажность (в %).
    • Внешнюю температуру (в °С, через DS18В20).

    Схема погодной станции была создана на основе: Arduino Pro Mini, датчике атмосферного давления и влажности BME280 (не путать с BMP280) и цифровом датчике температуры семейства DS1820.

    Схема погодной станции
    Pic 1. Схема погодной станции

    Датчик ф. Даллас семейства DS1820 и ему подобные имеет достаточную точность в широком диапазоне температур. Такой датчик я уже использовал при разработке МТР-1.2 – хороший, надёжный датчик. Если использовать герметичное исполнение, то можно измерять и температуру жидкостей, к примеру, воды.

    Погодная станция может работать от встроенного аккумулятора Li-Ion +3.7 В, или от внешнего источника напряжением 6...9 В, тогда, в этом случае, напряжение питания необходимо подавать на контакт RAW. При работе от аккумулятора, используется повышающий DC-DC преобразователь MT3608 (можно любой повышающий). На его выходе установлено напряжение 4.5...5 В. Во избежании повреждения Ардуино, BME280, TFT экрана – следует обратить внимание, что перед подключением преобразователя к устройству, необходимо заранее выставить на его выходе указанное напряжение.

    Используемый мной образец BME280 работает в диапазоне напряжений 1.8...5 В, что избавляет от необходимости применять стабилизатор на 3.3 В. Если у вас образец BME280 на напряжение 3.3 В, то добавьте для него стабилизатор на требуемое напряжение.

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

    /*********************************************************
     * 2018-05-27 Mr.ALB Тренировка в программировании Ардуино
     * 
     *  BMP280 I2C:
     *  SCL - A5
     *  SDA - A4
     *  VCC - 3.3V
     *  GND - GND
     *
     * 2018-07-17 v1.2 Добавлен датчик влажности DHT22: 
     *                 между контактом OUT и VCC 179
     *                 подключить 10к
     *                 
     * 2018-08-24 v3.0 Подключение дисплея 
     *                 TFT ST7735 128*160 1,8 дюйма   
     * 2018-09-05 v3.1 Автономная работа от 
     *                 батареии Li-Ion +3.7В 
     * 2018-09-08 v3.2 Перерисовка только меняющихся значений 
     * 2018-11-02 v3.2.1 Минимальная яркость = 1 
     * 2018-11-11 v3.2.2 Прогрессбар подсветки 
     *                   на главной странице   
     *
     * 2019-05-09 v3.3 Использование модуля BME280
     *  BME280 I2C:
     *  SCL - A5
     *  SDA - A4
     *  VCC - 1.8V...5V
     *  GND - GND
     * 2019-12-27 v3.4 Разные системы измерения давления
     *                  (мм | кПа)
     * 2019-12-29 v3.5 Использование датчика
     *                 температуры DS18B20
     * 2020-01-01 v3.5 Незначительное улучшение 
     *
     * Аппаратное подключение TFT:
     * TFT ST7735         ARDUINO
     * Pin 1 RST -[R 1k]- PIN 10
     * Pin 2 CS  -[R 1k]- PIN 9
     * Pin 3 DC  -[R 1k]- PIN 8 
     * Pin 4 DIN -[R 1k]- PIN 11
     * Pin 5 CLK -[R 1k]- PIN 13
     * Pin 6 VCC -        PIN VCC +5V
     * Pin 7 BL  -        PIN 3 - для регулировки подсветки
     *                            использовать ШИМ
     * Pin 8 GND -        PIN GND
     *
     * Контакты TFT 1-5 подключать через резисторы 1к...2к
     *
     *
    **********************************************************/
    // Подключение библиотеки для I2C
    #include <Wire.h>
    
    /* Графический дисплей TFT ST7735 1.8" */
    #include <Adafruit_GFX.h>   // Ядро графической библиотеки
    #include <Adafruit_ST7735.h>// Библиотека для ST7735
    
    #define TFT_RST 10
    #define TFT_CS  9
    #define TFT_DC  8
    
    // Аппаратное подключение TFT
    // Создаём объект tft
    Adafruit_ST7735 tft = Adafruit_ST7735
      (
        TFT_CS,
        TFT_DC,
        TFT_RST
      );
    
    // Подключение библиотеки BME280
    #include <Adafruit_BME280.h>
    /* Чтобы всё заработало необходимо
     *  1.  Сканером I2C найти адрес BME280
     *      или в библиотеке <Adafruit_BME280.h>:
     *      1)  Изменить адрес  #define BME280_ADDRESS (0x77)
     *          на адрес        #define BME280_ADDRESS (0x76)
     *      2)  Закоментировать библиотеку
     *          #include <Adafruit_Sensor.h>
    */
    
    // Создаём объект барометра
    Adafruit_BME280 bme;
    /* мБар       - мм рт. ст.
     * 1013.2472  - 760 k=1.33322
     * 1005.24788 - 754
     */
     
    // Нулевой уровень для давления 754 мм рт.ст.
    // Задайте значение соответствующее вашему положению
    double null_level=1005.24788; // В мБар
    
    // Коэффициент для перевода Па в мм рт.ст.
    float kp=133.322;
    
    // переменные давления
    float press_now,
          press_last,
          press_tmp,
          altit;
    
    // переменные температуры
    float temp,
          temp_last,
          temp_correct=-1;
    
    // переменные влажности
    float humidity_now,
          humidity_last,
          humidity_correct=0;
    
    #include <Buttons.h>        // Подключение библиотеки кнопок
    #define BUTTON_SET_LEVEL 6  // Кнопка "установка уровня 0 м" 
    
    #define BUTTON_LIGHT 5      // Кнопка подсветки дисплея
    
    #define LIGHT_PIN 3   // Вывод PWM для подсветки дисплея
    #define VCC_PIN   A0  // Ввод VCC батареи питания, 
                          // через резистор 1к
    
    // Создание объекта для кнопки "установка уровня 0 м"
    Buttons buttonSetLevel(BUTTON_SET_LEVEL,21);
     
    // Создание объекта для кнопки подсветки
    Buttons buttonLight(BUTTON_LIGHT,21);
    
    // Подключение библиотеки OneWire
    #include <OneWire.h>
    
    // Установка OneWire на Pin4
    #define ONE_WIRE_BUS 4 // Номер пина к которому подключен DS18B20
    OneWire oneWire(ONE_WIRE_BUS);
    
    // Подключение библиотеки Dallas Temperature
    #include <DallasTemperature.h>
    
    // Установка DallasTemperature для работы по OneWire
    DallasTemperature sensors(&oneWire);
    
    // Переменные для DS1820
    float temperature, fahrenheit, last_temperature;
    float temperatureMax=0,temperatureMin=0;
    byte addr[8];
    byte type_s;
    byte resolution;
    
    // Переменные для экрана
    uint8_t bxlz=2*6;    // Позиция заставки
    uint8_t byinfo=27;   // Позиция вывода информации по y
    uint8_t bxinfo=10*6; // Позиция вывода информации по х
    
    // Шаг подсветки 0...10;
    uint8_t count_level_light=1;
    
    // Уровень подсветки 0...250;
    int level_light=count_level_light*25;
    
    // Строка вывода прогресс-бара подсветки
    uint8_t light_str=15;
    
    // Переменные для обновления экрана по времени
    unsigned long time_now,
                  time_check,
                  time_button,
                  time_button_now,
                  time_delta=3000;
    
    char prog_title1[]="BME280";    // Название программы 1
    char prog_title2[]="DS1820";    // Название программы 2
    char author[]="Mr.ALB";         // Автор
    char vers[]="v3.5";             // Версия программы
    char vers_date[]="2020-01-01";  // Дата версии
    
    #define SCREEN_W 160            // Ширина экрана в рх
    #define SCREEN_H 128            // Высота экрана в рх
    uint8_t font_size=1;            // Размер шрифта
    
    /* Флаги */
    // Для обновления экрана по времени
    boolean flagcheck=false;
    // Для вывода надписей после установки яркости
    boolean flagSetLight=true;
    // Для измерения в кило Паскалях (kPa)
    boolean flagPa=false;
    // Для DS1820
    boolean flagDS=false;
    
    /***********************/
    /* Настройка программы */
    /***********************/
    void setup()
    {
      // Порт управления подсветкой экрана
      pinMode(LIGHT_PIN,OUTPUT);
    
      // Порт для измерения батареи питания
      pinMode(VCC_PIN,INPUT);
    
      // Опорный источник - внутренний
      analogReference(DEFAULT);
    
      // Инициируем работу с дисплеем 1.8" TFT
      tft.initR(INITR_BLACKTAB);// initialize a ST7735S chip, black tab
      fnClrScreen();            // Очистить экран
      tft.setRotation(1);       // Поворот экрана:
                                // 0 - 0°   книжный
                                // 1 - 90°  альбомный
                                // 2 - 180° книжный
                                // 3 - 270° альбомный
                                  
      // Установка начальной яркости
      analogWrite(LIGHT_PIN,level_light);
    
      if(!bme.begin()) // Старт датчика давления
      {
        //Если ошибка запуска
        tft.setTextColor(ST7735_RED);
        
        tft.setTextSize(2);
        fnCenter(sizeof("Error!"),2,1,0);
        tft.print("Error!");
    
        tft.setTextSize(1);
        fnCenter(sizeof("Not find BME280 sensor!"),1,7,0);
        tft.print("Not find BME280 sensor!");
        fnCenter(sizeof("Check contacts"),1,9,4);
        tft.print("Check contacts");
        
        fnCenter(sizeof("Click Reset"),1,14,0);
        tft.setTextColor(ST7735_YELLOW);
        tft.print("Click Reset");
        while(1);
      }
    
      // Старт датчика DS1820
      sensors.begin();
      if (!sensors.getAddress(addr, 0)) 
        flagDS=false; // Нет датчика DS1820
      else
      {
        flagDS=true;
        /* Определяем устройство и его параметры */
        //Считываем установленную точность
        resolution=sensors.getResolution();
    
        // Первый байт ROM указывает, какой чип
        switch(addr[0]) 
        {
          case DS18S20MODEL:
            type_s=1;
            break;
          case DS18B20MODEL:
            type_s=2;
            break;
          case DS1822MODEL:
            type_s=3;
            break;
          default:
            type_s=4;
        } 
    
        // Обновление значения датчика
        sensors.requestTemperatures();
        temperature = sensors.getTempC(addr);
        temperatureMax = temperature;
        temperatureMin = temperature;
      }
        
      // Заставка
      fnZastavka();
    
      // Вывод основного текста на экран
      fnPrintText();
    }
    
    /***********************/
    /*  Рабочая программа  */
    /***********************/
    void loop()
    { 
      // Текущее время работы программы в мс
      time_now=millis();
      // Проверка интервала времени для обновления экрана
      if(time_now-time_check>time_delta)
      {
        time_check=time_now;
        flagcheck=true;
      }
    
      buttonSetLevel.scanState();// Считывание состояния кнопки уровня
      buttonLight.scanState();   // Считывание состояния кнопки подсветки
        
      // Было нажатие кнопки подсветки
      if(buttonLight.flagClick==true) 
      {
        buttonLight.flagClick=false;  // Сброс признака клика
        count_level_light++;// Шаг яркости
        if(count_level_light>10)
        {
          count_level_light=0;        // Выключаем подсветку
          level_light=3;              // Минимальная яркость
          tft.fillRect(0, light_str*8+2,160, 3, ST7735_BLACK);
        }
        else
        {
          level_light=count_level_light*25;
        }
        // Установка яркости
        analogWrite(LIGHT_PIN,level_light); 
    
        /* Прогресс бар яркости подсветки */
        uint8_t bar_step=0;
        uint8_t bar_step_const=8*2;
        tft.setTextSize(1);
        for(uint8_t ip=0;ip<count_level_light;ip++)
        {
          tft.fillRect (1+bar_step, 
                        light_str*8+2,
                        bar_step_const-2,
                        3,
                        ST7735_WHITE
                        );
          bar_step+=bar_step_const;
        } 
        flagSetLight=true;
      }
    
      // Было нажатие кнопки "Установка уровня 0"
      if(buttonSetLevel.flagPress==true) 
      {
        time_button=millis();
        // Пока кнопка нажата
        while(buttonSetLevel.flagPress)
          buttonSetLevel.scanState();
        time_button_now=millis();
    
        if(time_button_now-time_button>=time_delta/2) 
        {
          // Если нажатие больше time_delta/2 сек,
          // то смена размерности давления 
          flagPa=!flagPa; // Инверсия флага Па
          fnPrintText();  // Вывод основных надписей
        }
        else
        { 
          // Если нажатие меньше time_delta/2 сек,
          // то обнуление высоты
          if(flagPa)
            null_level=press_now*10;
          else 
            null_level=press_now*kp/100;
        }
        flagcheck=true;
      }
    
      // Измерение параметров с BME280
      press_now=bme.readPressure();
      if(flagPa==false) 
        press_now/=kp;      // Давление в мм рт. ст.
      else press_now/=1000; // Давление в кило Паскалях
    
      temp = bme.readTemperature();     // Температура в °С
      humidity_now = bme.readHumidity();// Влажность в %
      // Конец измерения параметров с BME280
    
      //Применение коррекции влажности
      if(humidity_correct!=0) humidity_now += humidity_correct;
    
      //Применение коррекции температуры
      if(temp_correct!=0) temp += temp_correct;
    
      /*
       * Если давление изменилось  больше чем на 0,1 мм рт.ст.,
       * или на 0,01 кПа, то выводим на дисплей...
       * или если температура изменилась больше чем на 0,1°С
       * или если нажата кнопка обнуления высоты...
       * или если прошёл интервал времени >= 2 сек
       */
     if(
        (flagPa==false)&&((press_now<(press_last-.1)) ||
        (press_now>(press_last+.1))) ||
        (flagPa==true)&&((press_now<(press_last-.01)) ||
        (press_now>(press_last+.01))) ||
        (temp<(temp_last-.1))||(temp>(temp_last+.1)) ||
        flagcheck==true ||
        flagDS && ((last_temperature > temperature + .1) ||
          (last_temperature < temperature - .1))
       )
      {
        flagcheck=false;  // Сброс флага проверки по времени
    
        if(flagSetLight)  // Если была настройка яркости
        {
          tft.fillRect(0, light_str*8+2,160, 3, ST7735_BLACK);
          flagSetLight=false;
        }
    
        // Приблизительная высота в метрах
        altit=bme.readAltitude(null_level);
    
        // Вывод значения давления
        tft.setTextColor(ST7735_YELLOW);
        tft.fillRect(bxinfo, byinfo-2, 6*12, 16, ST7735_BLACK);
        tft.setTextSize(2);
        tft.setCursor(10*6, byinfo-2);
        tft.print(press_now);
    
        // Вывод высоты
        tft.setTextColor(ST7735_WHITE);
        tft.fillRect(bxinfo, byinfo+20, 6*7, 8, ST7735_BLACK);
        tft.setTextSize(1);
        tft.setCursor(bxinfo, byinfo+20);
        tft.print(altit);
    
        // Вывод значения температуры с BME280
        tft.setTextColor(ST7735_ORANGE);
        tft.fillRect(bxinfo, byinfo+36, 6*6, 8, ST7735_BLACK);
        tft.setCursor(bxinfo, byinfo+36);
        if(temp>0) tft.print("+");
        tft.print(temp);
    
        /* Вывод влажности */
        /* Раскрашиваем значение в зависимости от % влажности */
        if(humidity_now<30.0)                       // Сушь
          tft.setTextColor(ST7735_RED);
        if(humidity_now>=30.0 && humidity_now<60.0) // Сухо
          tft.setTextColor(ST7735_YELLOW);
        if(humidity_now>=60.0 && humidity_now<75.0) // Влажно
          tft.setTextColor(ST7735_GREEN);
        if(humidity_now>=75.0)                      // Сыро
          tft.setTextColor(ST7735_BLUE);
        //Очистка места под значение
        tft.fillRect(bxinfo, byinfo+52, 6*12, 16, ST7735_BLACK);
        tft.setTextSize(2);
        tft.setCursor(bxinfo, byinfo+52);
        tft.print(humidity_now);
    
        if(flagDS)
        {
          // Обновление значения датчика DS1820
          sensors.requestTemperatures();
          temperature = sensors.getTempC(addr);
    
          // Вывод значения температуры с DS1820
          tft.setTextColor(ST7735_WHITE);
          tft.fillRect(bxinfo, byinfo+74, 6*12, 16, ST7735_BLACK);
          tft.setTextSize(2);
          tft.setCursor(bxinfo, byinfo+74);
          if(temperature>0) tft.print("+");
          tft.print(temperature);
    
          // Записываем максимальное значение
          if(temperature > temperatureMax) 
            temperatureMax = temperature;
          // Записываем минимальное значение
          if(temperature < temperatureMin)
            temperatureMin = temperature;
        }
    
        /* Проверка напряжения питания */
        int v=analogRead(VCC_PIN);
        float vcc=v*5.0/1024; // Перевод бит в вольты
    
        // Вывод значения напряжения питания батареи
        if(vcc>2.5) // Выводим, если запитываемся от батареи
        {
          uint8_t x_vcc=20*6+3,y_vcc=14;
          tft.fillRect(x_vcc, y_vcc, 6*6, 8, ST7735_BLACK);
          tft.setCursor(x_vcc, y_vcc);
          tft.setTextSize(1);
          if(vcc<3.7) tft.setTextColor(ST7735_YELLOW);
          if(vcc<3.3) tft.setTextColor(ST7735_RED);
          if(vcc>=3.7) tft.setTextColor(ST7735_GREEN);
          tft.print("+");
          tft.print(vcc);
          tft.print("V");
          fnBattary(23*6,3,vcc);//Вывод пиктограммки
        }
        /* Конец проверки питания */
    
        // Перезаписываем бывшие значения
        temp_last=temp;               //BMP280
        press_last=press_now;
        humidity_last=humidity_now;
        last_temperature=temperature; //DS1820
        delay(5);
      }
    }
    
    /* Функция - Вывод °С */
    void fnChrDegree(
                      int16_t x, 
                      int16_t y, 
                      uint16_t color
                    )
    {
      uint8_t radius=2;
      tft.drawCircle(x+=radius*2, y+=radius*2-1, radius, color);
      tft.setCursor(x+3, y);
      tft.setTextColor(color);
      tft.print("C");
    }
    
    /* Функция символа батарейки */
    void fnBattary(
                    int16_t x,
                    int16_t y,
                    float vcc
                  )
    {
      int16_t w=19, h=8;
    
      // Контур батарейки
      tft.drawRect(x, y, w, h, ST7735_WHITE);
      // Пимпочка
      tft.fillRect(x+w, y+2, 2, 4, ST7735_WHITE);
    
      // Вывод квадратиков наполнения
      if(vcc<3.3)
        fnPrintFillRect(x,y,1,ST7735_RED);
      if(vcc>=3.3 && vcc<3.5)
        fnPrintFillRect(x,y,1,ST7735_YELLOW);
      if(vcc>=3.5&&vcc<3.7)
        fnPrintFillRect(x,y,2,ST7735_YELLOW);
      if(vcc>=3.7&&vcc<3.9)
        fnPrintFillRect(x,y,3,ST7735_GREEN);
      if(vcc>=3.9)
        fnPrintFillRect(x,y,4,ST7735_GREEN);
    }
    
    /* Функция вывода квадратиков для символа батарейки*/
    void fnPrintFillRect(
                          int16_t x,
                          int16_t y,
                          uint8_t max_i,
                          int16_t color
                        )
    {
      tft.fillRect(x+1, y+1, 17, 6, ST7735_BLACK);
      for(uint8_t i=0;i<max_i;i++)
      {
        tft.fillRect(x+2+i*4, y+2, 3, 4, color);
      }  
    }
    
    /* Функция - Заставка */
    void fnZastavka()
    {
      fnClrScreen(); // Очистить экран
      tft.setTextWrap(false);
    
      tft.setTextColor(ST7735_ORANGE);
      font_size=3;
      tft.setTextSize(font_size);
      fnCenter(sizeof(prog_title1)-1,font_size,1,0);
      tft.print(prog_title1);
    
      font_size=2;
      tft.setTextSize(font_size);
      fnCenter(sizeof(author)-1,font_size,4,0);
      tft.setTextColor(ST7735_DARKGREEN);
      tft.print(author);
    
      font_size=1;
      tft.setTextSize(font_size);
      fnCenter(sizeof(vers)-1,font_size,11,0);
    
      tft.setTextColor(ST7735_GRAY);
      tft.println(vers);
    
      fnCenter(sizeof(vers_date)-1,font_size,12,2);
      tft.println(vers_date);
    
      delay(3600);
    
      if(flagDS)
      {
        fnClrScreen(); // Очистить экран
        tft.setTextColor(ST7735_ORANGE);
        font_size=3;
        tft.setTextSize(font_size);
        fnCenter(sizeof(prog_title2)-1,font_size,1,0);
        tft.print(prog_title2);
    
        font_size=1;
        tft.setTextSize(font_size);
        switch(type_s) 
        {
          case 1:
            fnCenter
            (
              sizeof("Chip = DS18S20|old DS1820")-1,font_size,7,0
            );
            tft.print("Chip = DS18S20|old DS1820");
            break;
          case 2:
            fnCenter(sizeof("Chip = DS18B20")-1,font_size,7,0);
            tft.print("Chip = DS18B20");
            break;
          case 3:
            fnCenter(sizeof("Chip = DS1822")-1,font_size,7,0);
            tft.print("Chip = DS1822");
            break;
          default:
            fnCenter
            (
              sizeof("is not family of DS18x20")-1,font_size,7,0
            );
            tft.print("is not family of DS18x20");
        }
        fnCenter(sizeof("Resolution =   ")-1,font_size,9,0);
        tft.print("Resolution = ");
        tft.print(resolution);
      }
      delay(3000);
    }
    
    /* Функция - Вывод основных надписей на экран */
    void fnPrintText()
    {
      fnClrScreen();  // Очистить экран
      tft.setTextSize(1);
      tft.setCursor(8, 3);
      tft.setTextColor(ST7735_GREEN);
      tft.print("BME280 ");
      tft.print(vers);
      if(flagDS) tft.print(" DS1820");
    
      /* Вывод давления */
      tft.setTextColor(ST7735_LIGHTGRAY);
      tft.setCursor(0, byinfo);//24
      tft.print("Pressure:");
      tft.setCursor(bxinfo+6*12, byinfo);
      tft.setTextSize(1);
    
      // Вывод размерности давления
      if(flagPa)
        tft.print(" kPa");
      else 
        tft.print(" mm");
    
      /* Вывод высоты */
      tft.setCursor(0, byinfo+20);
      tft.print("Altitude:");
      tft.setCursor(bxinfo+6*8, byinfo+20);
      // Вывод размерности высоты
      tft.print("m");
    
      /* Вывод температуры */
      tft.setCursor(0, byinfo+36);
      tft.print("Temper. :");
      // Вывод размерности температуры
      fnChrDegree(bxinfo+6*7,60,ST7735_LIGHTGRAY);
    
      /* Вывод влажности */
      tft.setCursor(0, byinfo+52);
      tft.print("Humidity:");
      tft.setTextSize(1);     
      tft.setCursor(bxinfo+6*12, byinfo+52);
      // Вывод размерности влажности
      tft.print("%");
    
      /* Вывод температуры с DS1820 */
      if(flagDS)
      {
        //Разделитель влажности и DS1820
        tft.drawFastHLine(0,byinfo+70,160,ST7735_DARKGRAY);
    
        /* Вывод температуры c DS1820 */
        tft.setCursor(0, byinfo+78);
        tft.print("Temper. :");
        // Вывод размерности температуры
        fnChrDegree(bxinfo+6*12,104,ST7735_LIGHTGRAY);
      }
    }
    
    /* Функция - центрирование строки */
    void fnCenter(
                  uint8_t lenght,
                  uint8_t fntsize,
                  uint8_t row,
                  uint8_t offset
                 )
    {
      tft.setCursor
      (
        (SCREEN_W-lenght*fntsize*6)/2+fntsize*6/2,
        fntsize*8*row+offset
      );
    }
    
    /* Функция - Cтирание экрана чёрным цветом */
    void fnClrScreen()
    {
      // Очистить экран, т.е. закрасить чёрным
      tft.fillScreen(ST7735_BLACK);
      // Курсор в начало экрана
      tft.setCursor(0, 0);     
    }
    
    

    Реализация

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

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

    Основой послужила монтажная плата с металлизированными отверстиями, что удобно для двухстороннего монтажа. Печатную плату разрабатывать не стал, сберёг своё личное время улыбка. Это устройство единичное и не имеет смысла делать какие-то печатные платы. Размер печатной платы 63 * 50 мм. Куплена в Китае.

    С нижней стороны платы установлена панелька на 24 контакта для Arduino Pro Mini. Там же смонтирован преобразователь DC-DC MT3608, и плата для зарядки литивого аккумулятора на основе TP4056. Преобразователь использовал покупной, какой был под рукой, но можно использовать любой, хоть бы и самодельный, который выдаёт на выходе напряжение от 4.5 В до 5 В.

    На нижней стороне платы смонтированы и конденсаторы С1 и С2.

    Нижняя сторона платы
    Pic 1. Нижняя сторона платы

    С верхней стороны платы размещены: датчик BME280, TFT экран 1"8, аккумулятор 3,7 В 400 мАч.

    Вся разводка выполнена цветными одножильными монтажными проводками.

    Верхняя сторона платы
    Pic 2. Верхняя сторона платы

    Напоминаю, что перед установкой платы Ардуино, BME280 и TFT экрана, заранее проверьте и выставите напряжение на выходе преобразователя DC-DC, чтобы случайно не повредить компоненты устройства.

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

    Сборка верхней стороны платы
    Pic 3. Сборка верхней стороны платы

    При включении устройства на экране выводится заставка, где указывается дата и версия прошивки. Последняя версия v3.5 2020-01-01.

    Заставка при включении
    Pic 4. Заставка при включении

    Если к погодной станции подключен датчик температуры DS1820, то на второй странице заставки выводится сообщение о подключении. Определяется чип датчика и выводится точность измерения. Максимальная точность – 12 бит. . Если внешний датчик температуры не подключен, то после вывода заставки программа переходит к измерениям текущих параметров с датчика BME280.

    Заставка при подключенном DS1820
    Pic 5. Заставка при подключенном DS1820

    По просьбам читателей, добавил возможность измерения давления в кПа. У нас в РФ атмосферное давление измеряется в мм ртутного столба, а в Европейских странах, в основном, в Барах или Паскалях. Эти единицы измерения подобны и отличаются лишь десятичным разрядом. При измерении в кПа на экране выводится число по размерности соответствующее нашему значению, то есть три десятичных разряда перед запятой и два после.

    Смена единиц измерения давления происходит при удержании кнопки Установка уровня 0 метров. Удерживать 2...3 секунды. При кратком нажатии на кнопку, происходит установка нулевого уровня для текущего атмосферного давления.

    Измерение давления в кПа
    Pic 6. Измерение давления в кПа

    Основной режим измерения задан в мм рт. ст. Если вам необходимо чтобы погодная станция по умолчанию измеряла в кПа, то в программе в строке 184 установите флаг измерения в кПа flagPa=true;.

    Измерение давления в мм рт. ст.
    Pic 7. Измерение давления в мм рт. ст.

    Если подключен внешний датчик температуры DS1820, то на экране внизу дополнительно выводится строчка с измеренным значением с этого датчика. Дополнительно в верху экрана указывается, что используется датчик DS1820 (левее пиктограммы батарейки). Значение температуры с датчика BME280 выводится мелким шрифтом, перед строкой со значением влажности (Humidity).

    Вывод температуры с внешнего датчика
    Pic 8. Вывод температуры с внешнего датчика

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

    В процессе разработки соединений модуля
    Pic 9. В процессе разработки соединений модуля

    Для полного завершения этой конструкции требуется изготовить корпус. Как и прежде, буду его делать из пластика ABS. Когда корпус будет изготовлен, то добавлю фото, а пока так как есть.

    Размеры получившегося модуля: 64 * 50 * 32 мм (ширина * высота * глубина). Потом размеры несколько увеличатся за счёт толщины пластика корпуса.


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

    2020-01-02


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