Разработка и конструирование портативной автономной метеостанции на платформе Arduino Nano

XIX Международный конкурс научно-исследовательских и творческих работ учащихся
Старт в науке

Разработка и конструирование портативной автономной метеостанции на платформе Arduino Nano

Смотраев Н.Н. 1
1МАОУ "СОШ №10"
Пеньшина Г.Н. 1
1МАОУ "СОШ №10"
Автор работы награжден дипломом победителя I степени
Текст работы размещён без изображений и формул.
Полная версия работы доступна во вкладке "Файлы работы" в формате PDF

Введение

Нам хорошо известно влияние микроклимата помещения на здоровье и самочувствие человека. Закономерности и последствия негативного влияние на человека изучают ученые во многих стран мира и предлагают пути решения этой проблемы. В России стандарты микроклимата соответствуют «ГОСТу 30494-2011. Здания жилые и общественные. Параметры микроклимата в помещениях». Для определения параметров микроклимата в помещении я определил для себя тему практической работы - «Создание домашней метеостанции на основе микроконтроллера Arduino Nano».

Цель работы: создание домашней метеостанции на микроконтроллере Arduino Nano.

Задачи:

- изучить литературу по работе микроконтроллеров Arduino;

- научиться пользоваться микроконтроллерами, программировать их в программной оболочке Arduino IDE;

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

В работе использованы следующие методы исследования:

-анализ и синтез информации из Internet-ресурсов, специальной литературы, раскрывающей суть данного вопроса;

- моделирование установки домашней метеостанции;

-проведение исследовательских работ по выявлению оптимальных условий функционирования установки.

Объект исследования: микроклимат помещения.

Предмет исследования: параметры влажности, температуры воздуха, атмосферное давление и изменение СО2.

Гипотеза: измерение параметров микроклимата помещения с помощью домашней метеостанции на Arduino Nano позволяет оперативно отслеживать качество воздуха в помещениях.

1. Теоретические основы метеорологических измерений

1.1. Стандарты микроклимата помещений

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

Межгосударственный стандарт жилых зданий и общественных помещений (ГОСТ 30494—2011) от 01.01.2013 устанавливает общие требования к оптимальным и допустимым показателям микроклимата и качеству воздуха параметры микроклимата в помещениях.

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

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

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

Оптимальные и допустимые нормы температуры и влажности воздуха в помещениях

Период года

Наименование помещения

Температура воздуха, °С

Относительная влажность, %

оптимальная

допустимая

оптимальная

допустимая, не более

Холодный

Жилая комната

20—22

18—24

45—30

60

ЖК в районах с

t ≤ -31°С

21—23

20—24

45—30

60

Помещения для отдыха и учебных занятий

20—22

18—24

45—30

60

Теплый

Жилая комната

22—25

20—28

60—30

65

Оптимальные и допустимые нормы температуры, относительной влажности в школах

Период года

Помещения

Температура воздуха, °С

Относительная влажность, %

оптимальная

допустимая

оптимальная

допустимая, не более

Холодный

учебное

19—21

18—23

45—30

60

спортзал

17—19

15—21

45—30

60

В жилых и общественных зданиях в холодный период года в нерабочее время допускается снижать показатели микроклимата, температуру воздуха не ниже: 15°С — в жилых помещениях; 12°С — в помещениях общественных и административных. Нормируемая температура должна быть обеспечена к началу использования.

Согласно действующим нормативам ГОСТ Р ЕН 13779—2007 для школ следует принимать показатели качества воздуха 1-го класса.


Класс

Качество воздуха в помещении


Допустимое содержание СО2

Оптимальное

Допустимое

1

Высокое

400 и менее

2

Среднее

400—600

3

Допустимое

600—1000

4

Низкое

1000 и более

1.2 Обзор литературы по видам метеостанций

Метеостанция - прибор, предназначенный для ведения наблюдений за погодой. Метеостанции выпускаются как для профессионального, так и для бытового использования.

Профессиональные метеостанции могут быть адаптированы для работы в дорожных условиях, для применения в лесничих хозяйствах, для ведения метеорологических исследований. Они представляют собой сложные цифровые приборы, точность работы которых оказывает заметное влияние на работу различных служб. Их можно встретить на кораблях, нефтяных платформах и в других экстремальных условиях, где они постоянно подвергаются воздействию низких или высоких температур, высокой влажности, ветра [3].

Домашние метеостанцииблагодаря широкому набору возможностеймогут стать полезными в каждом доме [10]. Они появились на рынке сравнительно недавно. Родоначальниками бытовых метеостанций являются обыкновенные барометры. Функциональность домашней метеостанции схожа с метеорологической станцией, только обрабатывается гораздо меньше данных, которые поступают с одного или нескольких датчиков, устанавливаемых за окном и в других помещениях. Домашние метеостанции показывают температуру в помещении, температуру вне помещения, измеряют влажность, атмосферное давление. Они могут работать как от электрической сети, так и от сменных элементов питания [3].

Анализ литературы позволил выделить два типа домашних метеостанций: аналоговые и цифровые.Аналоговые метеостанции состоятиз механических приборов и элементов. Они включают в себя измерители, температуры, давления, относительной влажности воздуха. В некоторые модели встроен хронометр. Цифровые (электронные) метеостанции - портативные приборы, фиксирующие данные о погодных и климатических условиях при помощи электронных датчиков. Для контроля самочувствия у метеочувствительных людей требуется как минимум два прибора - термометр и гигрометр, поэтому обычный бытовой прибор для измерения уровня влажности для этой цели не подходит. Термогигрометр способен комплексно измерять и анализировать показатели влажности для создания комфортного микроклимата, диапазон которых варьируется от 0 до 100% [1].

Анализ литературы позволил выделить разные виды автономных метеостанций, в том числе и портативных.

1.3 Сравнительный анализ портативных автономных метеостанций

В таблице 1 представлены характеристики трёх автономных метеостанций, являющихся аналогами разработанной метеостанции.

Таблица 1

Сравнение существующих метеостанций, позволяющих проводить метеорологические измерения

Функции и

характеристики

GARIN WS-1

SunRoad FR500

RST 02559

Источник питания

2 батареи типа АА (U=1,5В)

1 встроенная батареи L1 (U=12В)

1 батарея CR2032 (U=3В)

Диапазон измерения температуры, оС

от -10 до +50

нет

от -20 до +60

Диапазон измерения относительной влажности воздуха, %

от 20 до 90

от 20 до 95

нет

Диапазон измерения высоты над уровнем моря h, м

нет

от -700 до 9000

нет

Диапазон измерения атмосферного давления p, мм. рт. с

нет

от 225 до 825

от 676 до 812

Водонепроницаемость

нет

да, стандарт IPX4

да

Масса m, г

200

140

105

Отображение текущего времени

есть

есть

нет

Габаритные размеры, мм

35×76×107

100×66×20

163×78×27

Приблизительная стоимость, руб

552

2200

2850

Данные таблицы 1 свидетельствуют о том, что портативные автономные метеостанции GARIN WS-1, SunRoad FR500 и RST 02559 обладают приблизительно одинаковой функциональностью. Анализ справочных данных позволил выделить преимущества и недостатки этих метеостанций.

Отличительной особенностью модели GARIN WS-1 являетсяотносительно невысокая стоимость. Отличительной особенностью модели SunRoad FR500 является наличие высотомера и функция построения графиков проводимых измерений, а также наличие класса влагопылезащиты. Недостатком данной модели является отсутствие возможности измерения температуры и высокая стоимость. Достоинствам модели RST 02559 относится широкий диапазон измерения температур и индикация возможности наступления заморозков. К недостаткам данной модели можно отнести отсутствие возможности измерения относительной влажности воздуха и высокую стоимость.

Портативные автономные метеостанции для получения метеорологических данных, созданные на платформе Arduino, не производятся в промышленных масштабах.

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

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

2. Домашняя метеостанция на базе платформы разработки электронных устройств Arduino Nano

2.1. Ресурсное обеспечение проекта

 

Платформа Nano, построенная на микроконтроллере ATmega328 (Arduino Nano 3.0)

Характеристика:

Микроконтроллер: Atmel ATmega328

Рабочее напряжение: 5 В

14 цифровых выходов и 8 аналоговых входов

Флеш-память32 Кб

ОЗУ 2 Кб

Размеры 1.85 см x 4.2 см

 

Датчик углекислого газа MH-Z19B —  датчик, который детектирует уровень СО2 по принципу недисперсионного инфракрасного излучения (NDIR). Данный датчик имеет внутреннюю температурную компенсацию, может подключаться по 3-м интерфейсам (аналоговый, ШИМ, UART), имеет малые размеры и большой срок службы.

Характеристика:

Рабочее напряжение: от 4.5В до 5В

Потребление тока: <60мА (150мА в пиковой нагрузке)

Диапазон измерений: 0~5000ppm

Интерфейс: UART (3.3В) / ШИМ (3.3В, толерантен к 5В)

Время прогрева датчика: 3мин

Рабочая температура: от 0 до 50℃

Влажность: от 0 до 95%

Вес: 5г

 

Трёхцветный светодиод или RGB-светодиод – это совмещенные в одном корпусе излучающие кристаллы красного, зеленого и синего свечения. Конструкция светодиода имеет четыре вывода: общий (катод или анод), три вывода соответствуют своему определенному цвету.

 

Сенсорный модуль TTP223 (сенсорная кнопка) Ардуино выполнена на базе микросхемы TTP223-BA6 в виде бескорпусного модуля. Датчик имеет площадку на печатной плате в виде металлизированной поверхности с надписью «touch».

Характеристика:

Напряжение питания: 2 – 5,5 Вольт;

Потребляемый ток: 70 — 500 мкА;

Максимальное время срабатывания: 220 мС;

Размеры модуля: 11 x 15 мм.

 

BME280 – высокоточный метеодатчик, позволяет измерять сразу три параметра — температуру, влажность и давление.

Характеристика:

Интерфейс: I2C

Напряжение питания: 5 В

Рабочий ток: 1 мA

Диапазон измерений давления: 300-1100hPa;

Диапазон измерений температуры: -40 - +85 °C;

Диапазон измерений влажности: 0 - 100 %;

Точность измерений: давление - 0.01 hPa ( < 10 cm). Температура - 0.01°C Влажность – 3%

 

Символьный дисплей LCD2004 с голубой подсветкой — жидкокристаллический дисплей (LiquidCrystalDisplay) экран которого способен отображать одновременно до 80 символов (20 столбцов, 04 строки). Подключение к Arduino осуществляется интерфейсу I2C.

Характеристика:

Тип выводимой информации: символьный.

Язык в ПЗУ дисплея: латиница, японский.

Возможность загрузки собственных символов: есть.

Формат выводимой информации: 20×04 символов;

Тип дисплея: LCD.

Тип подсветки: LED.

Цвет подсветки: синий.

Цвет символов: белый.

Контроллер: HD44780.

Интерфейс: синхронный, 8-битный, параллельный.

Напряжение питания 5 В.

Рабочая температура: -20 ... +70 °С.

 

Модуль DS1307 (RTC, ZS-042) — представляет собой плату с чрезвычайно точными часами реального времени (RTC), с температурной компенсацией кварцевого генератора и кристалла. Модуль включает в себя литиевую батарею, которая поддерживает бесперебойную работу, даже при отключении источник питания.

Характеристика:

Напряжение питания: 3.3В и 5В

Чип памяти: AT24C32 (32 Кб);

Точность: ± 0.432 сек в день;

Частота кварца:32.768 кГц;

Поддерживаемый протокол: I2C;

Габариты: 28мм x 25мм x 8мм

 

 

2.2. Блок-схема домашней метеостанции на Arduino Nano

2.3. Создание домашней метеостанции на Arduino Nano

После выбора необходимых компонентов метеостанции, соединим их по схеме. Делаем это с помощью пайки. Я собрал схему вне корпуса, запрограммировал и отладил ее в программе Arduino IDE.

Подготовив корпус, я сделал разметку для установки всех датчиков.

Было вырезано окошко по размерам дисплея. На задней стороне просверлены отверстия для стабильной работы датчиков.

Управление будет происходить с помощью сенсорной кнопки, закрепленной на верхней части корпуса. С помощью данного модуля будет производиться управление метеостанцией. Питание метеостанции я осуществил с разъема Type-C, подав напряжение 5В на контакт VIN и GND. На боковой стороне я сделал окошки для разъёмов питания и программирования.

Собрал корпус, запустил метеостанцию в рабочем режиме.

2.4. Измерения параметров микроклимата домашней метеостанцией

Метеостанция дает большой массив данных­ - на дисплее отражаются показатели:

    • Время (час, минута, секунда)

    • Дата (число, месяц)

    • Температура воздуха (в ˚С)

    • Влажность воздуха (в %)

    • Атмосферное давление (в мм.рт.ст.)

    • Углекислый газ (в ppm)

  • Построение графиков показаний с датчиков за час и сутки

  • Индикация уровня CO2 трёхцветным светодиодом. Световой индикатор загорается в зависимости от содержания углекислого газа в воздухе:

  • Зеленый – нормальные условия (до 800 ppm)

  • Синий – проявляется усталость, сонливость (от 800 до 1200 ppm)

  • Красный – полная потеря работоспособности (свыше 1200 ppm)

По истечению времени составляются графики:

  • Первый график отражает зависимость температуры от времени (за час и за сутки).

  • На втором графике отображена зависимость от времени (за час и за сутки).

  • Третий график отражает уровень углекислого газа (за час и за сутки).

  • Четвертый график показывает прогноз погоды (за час и за сутки).

Определение параметров влажности, температуры воздуха, содержания СО2 в классе школы в течении учебного дня в холодное время года (06 февраля 2023 г.)

Параметры воздуха

В начале учебного дня (8:00)

В конце учебного дня (15:00)

После проветривания (15:00)

 

Измеренные показания

Норма (допустимое)

Вывод

Измеренные показания

Норма (допустимое)

Вывод

Измеренные показания

Норма (допустимое)

Вывод

Температура воздуха (°С)

21

18-23

норма

26

18-23

выше нормы

20

18-23

норма

Влажность воздуха (%)

56

<60

норма

57

<60

норма

58

< 60

норма

Содержание СО2

355

<400

норма

520

<400

выше нормы

300

<400

норма

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

Влажность воздуха в классе (относительная влажность), при температурах 18-23°С должно быть не выше 60 %. Повышение влажности увеличивает теплоотдачу организма. В кабинетах с большим количеством цветов, влажность имеет оптимальные значения, а значит, благоприятна для здоровья учащихся и педагогов.Понизить влажность до нормы можно, смешивая влажный воздух помещения с сухим уличным, т.е. путём проветривания помещения.

Выводы из проведенных исследований:

1. В начале дня в кабинете температура, влажность воздуха, содержание СО2 соответствует нормам.

2. К концу учебного дня значения параметров воздуха в кабинете повышаются.

Для улучшения состояния микроклимата в кабинете рекомендуется:

1. Опрыскивание. С помощью этого простого и действенного метода можно увеличить влажность воздуха.

2. Увеличить в кабинетах количество зеленых насаждений. Листья зеленых растений испаряют воду и способствуют повышению влажности воздуха, а это улучшает самочувствие людей.

3. Проветривать помещение в течении учебного дня.

Рекомендации по использованию домашней метеостанции

Условия работы и особенности использования метеостанции:

  • Домашняя метеостанция предназначена для работы при температурах от - 5 ˚С до +40 ˚С .

  • Относительная влажность до 90% при температуре +25ОС.

  • Не допускается попадания на прибор соляных брызг, кислотных и окислительных газов;

  • Прибор нужно использовать вдали от источников тепла и воздействия прямых солнечных лучей.

Заключение

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

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

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

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

Работа может быть продолженаусовершенствованием изготовленнойметеостанции: добавлением Bluetooth модуля для возможности отображения показаний датчиков на смартфоне, добавлением часов реального времени и датчика измерения атмосферного давления для расширения функционала метеостанции, улучшением дизайна.

Цель работы достигнута. Задачи выполнены.

Используемая литература

  1. http://arduino.ru/ - материалы по Arduino на русском языке;

  2. http://amperka.ru/ - интернет-магазин, материалы по Arduino в свободном доступе;

  3. https://123d.circuits.io/lab -лаборатория электроники, здесь можно собрать схему на монтажной плате, запрограммировать её и проверить в работе ;

  4. https://www.youtube.com/playlist?list=PLfDmj22jP9S759DT250VVzfZs_4

  5. VnJqLa - видеоуроки Джереми Блума на русском языке (перевод Amperka.ru);

  6. http://arduino.ru/forumy/proekty- проекты на Arduino — описание.

  7. https://vash.market/bytovaya-tehnika/klimaticheskaya-tehnika/vidy-tsifrovyh-i-bytovyh-meteostantsij.html.

  8. https://usamodelkina.ru/9703-domashnyaya-meteostanciya-na-baze-arduino.html. - домашняя метеостанция на базе Ардуино.

  9. https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%B5%D0%BE%D1%81%D1%82%D0%B0%D0%BD%D1%86%D0%B8%D1%8F.

  10. https://radioded.ru/proekty-na-arduino/meteostantsiya-na-arduino.-Метеостанция портативная GARIN WS

  11. -https://www.lacrossetechnology.ru/meteostantsiya-portativnaya-garin-ws-1.html. - Метеостанция RST 02559.

  12. http://www.meteo-station.ru/goods/rst-02559.html.

  13. GitHub https://github.com/Norovl/meteoClock/

  14. https://alexgyver.ru/meteoclock/

  15. https://habr.com/ru/post/425901/

  16. https://electricdoma.ru/umniidom/проект-простейшей-метеостанции-на-ар/

  17. https://роботехника18.рф/метеостанция-на-ардуино-с-дисплеем/

  18. https://soltau.ru/index.php/themes/diy/item/436-kak-sdelat-pogodnuyu-stantsiyu-na-arduino

Приложение Код программы

#define RESET_CLOCK 0 // сброс часов на время загрузки прошивки.

#define SENS_TIME 3000 // время обновления показаний сенсоров на экране, миллисекунд

#define LED_MODE 0 // тип RGB светодиода: 0 - главный катод, 1 - главный анод

#define LED_BRIGHT 255 // яркость светодиода СО2 (0 - 255)

#define BLUE_YELLOW 0 // жёлтый цвет вместо синего (1 да, 0 нет)

#define DISP_MODE 2 // в правом верхнем углу отображать: 0 - год, 1 - день недели, 2 - секунды

#define WEEK_LANG 1 // язык дня недели: 0 - английский, 1 - русский (транслит)

#define DISPLAY_TYPE 1 // тип дисплея: 1 - 2004 (большой), 0 - 1602 (маленький)

// пределы отображения для графиков

#define TEMP_MIN 15

#define TEMP_MAX 35

#define HUM_MIN 0

#define HUM_MAX 100

#define PRESS_MIN -100

#define PRESS_MAX 100

#define CO2_MIN 300

#define CO2_MAX 2000

// пины

#define MHZ_RX 2

#define MHZ_TX 3

#define LED_COM 7

#define LED_R 9

#define LED_G 6

#define LED_B 5

#define BTN_PIN 4

// библиотеки

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

#if (DISPLAY_TYPE == 1)

LiquidCrystal_I2C lcd(DISPLAY_ADDR, 20, 4);

#else

LiquidCrystal_I2C lcd(DISPLAY_ADDR, 16, 2);

#endif

#include "RTClib.h"

RTC_DS3231 rtc;

DateTime now;

#include <Adafruit_Sensor.h>

#include <Adafruit_BME280.h>

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme;

#if (CO2_SENSOR == 1)

#include <MHZ19_uart.h>

MHZ19_uart mhz19;

#endif

#include <GyverTimer.h>

GTimer_ms sensorsTimer(SENS_TIME);

GTimer_ms drawSensorsTimer(SENS_TIME);

GTimer_ms clockTimer(500);

GTimer_ms hourPlotTimer((long)4 * 60 * 1000); // 4 минуты

GTimer_ms dayPlotTimer((long)1.6 * 60 * 60 * 1000); // 1.6 часа

GTimer_ms plotTimer(240000);

GTimer_ms predictTimer((long)10 * 60 * 1000); // 10 минут

#include "GyverButton.h"

GButton button(BTN_PIN, LOW_PULL, NORM_OPEN);

int8_t hrs, mins, secs;

byte mode = 0;

/*

0 часы и данные

1 график температуры за час

2 график температуры за сутки

3 график влажности за час

4 график влажности за сутки

5 график давления за час

6 график давления за сутки

7 график углекислого за час

8 график углекислого за сутки

*/

// переменные для вывода

float dispTemp;

byte dispHum;

int dispPres;

int dispCO2;

int dispRain;

// массивыграфиков

int tempHour[15], tempDay[15];

int humHour[15], humDay[15];

int pressHour[15], pressDay[15];

int co2Hour[15], co2Day[15];

int delta;

uint32_t pressure_array[6];

uint32_t sumX, sumY, sumX2, sumXY;

float a, b;

byte time_array[6];

// символы

// график

byte row8[8] = {0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};

byte row7[8] = {0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};

byte row6[8] = {0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};

byte row5[8] = {0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};

byte row4[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111};

byte row3[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111};

byte row2[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111};

byte row1[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111};

// цифры

uint8_t LT[8] = {0b00111, 0b01111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};

uint8_t UB[8] = {0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000};

uint8_t RT[8] = {0b11100, 0b11110, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};

uint8_t LL[8] = {0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b01111, 0b00111};

uint8_t LB[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111};

uint8_t LR[8] = {0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11110, 0b11100};

uint8_t UMB[8] = {0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111};

uint8_t LMB[8] = {0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111};

void drawDig(byte dig, byte x, byte y) {

switch (dig) {

case 0:

lcd.setCursor(x, y); // set cursor to column 0, line 0 (first row)

lcd.write(0); // call each segment to create

lcd.write(1); // top half of the number

lcd.write(2);

lcd.setCursor(x, y + 1); // set cursor to colum 0, line 1 (second row)

lcd.write(3); // call each segment to create

lcd.write(4); // bottom half of the number

lcd.write(5);

break;

case 1:

lcd.setCursor(x + 1, y);

lcd.write(1);

lcd.write(2);

lcd.setCursor(x + 2, y + 1);

lcd.write(5);

break;

case 2:

lcd.setCursor(x, y);

lcd.write(6);

lcd.write(6);

lcd.write(2);

lcd.setCursor(x, y + 1);

lcd.write(3);

lcd.write(7);

lcd.write(7);

break;

case 3:

lcd.setCursor(x, y);

lcd.write(6);

lcd.write(6);

lcd.write(2);

lcd.setCursor(x, y + 1);

lcd.write(7);

lcd.write(7);

lcd.write(5);

break;

case 4:

lcd.setCursor(x, y);

lcd.write(3);

lcd.write(4);

lcd.write(2);

lcd.setCursor(x + 2, y + 1);

lcd.write(5);

break;

case 5:

lcd.setCursor(x, y);

lcd.write(0);

lcd.write(6);

lcd.write(6);

lcd.setCursor(x, y + 1);

lcd.write(7);

lcd.write(7);

lcd.write(5);

break;

case 6:

lcd.setCursor(x, y);

lcd.write(0);

lcd.write(6);

lcd.write(6);

lcd.setCursor(x, y + 1);

lcd.write(3);

lcd.write(7);

lcd.write(5);

break;

case 7:

lcd.setCursor(x, y);

lcd.write(1);

lcd.write(1);

lcd.write(2);

lcd.setCursor(x + 1, y + 1);

lcd.write(0);

break;

case 8:

lcd.setCursor(x, y);

lcd.write(0);

lcd.write(6);

lcd.write(2);

lcd.setCursor(x, y + 1);

lcd.write(3);

lcd.write(7);

lcd.write(5);

break;

case 9:

lcd.setCursor(x, y);

lcd.write(0);

lcd.write(6);

lcd.write(2);

lcd.setCursor(x + 1, y + 1);

lcd.write(4);

lcd.write(5);

break;

case 10:

lcd.setCursor(x, y);

lcd.write(32);

lcd.write(32);

lcd.write(32);

lcd.setCursor(x, y + 1);

lcd.write(32);

lcd.write(32);

lcd.write(32);

break;

}

}

void drawdots(byte x, byte y, boolean state) {

byte code;

if (state) code = 165;

else code = 32;

lcd.setCursor(x, y);

lcd.write(code);

lcd.setCursor(x, y + 1);

lcd.write(code);

}

void drawClock(byte hours, byte minutes, byte x, byte y, boolean dotState) {

// чисти чисти!

lcd.setCursor(x, y);

lcd.print(" ");

lcd.setCursor(x, y + 1);

lcd.print(" ");

//if (hours > 23 || minutes > 59) return;

if (hours / 10 == 0) drawDig(10, x, y);

else drawDig(hours / 10, x, y);

drawDig(hours % 10, x + 4, y);

// тут должны быть точки. Отдельной функцией

drawDig(minutes / 10, x + 8, y);

drawDig(minutes % 10, x + 12, y);

}

#if (WEEK_LANG == 0)

static const char *dayNames[] = {

"Sund",

"Mond",

"Tues",

"Wedn",

"Thur",

"Frid",

"Satu",

};

#else

static const char *dayNames[] = {

"BOCK",

"POND",

"BTOP",

"CPED",

"4ETB",

"5YAT",

"CYBB",

};

#endif

void drawData() {

lcd.setCursor(15, 0);

if (now.day() < 10) lcd.print(0);

lcd.print(now.day());

lcd.print(".");

if (now.month() < 10) lcd.print(0);

lcd.print(now.month());

if (DISP_MODE == 0) {

lcd.setCursor(16, 1);

lcd.print(now.year());

} else if (DISP_MODE == 1) {

lcd.setCursor(16, 1);

int dayofweek = now.dayOfTheWeek();

lcd.print(dayNames[dayofweek]);

}

}

void drawPlot(byte pos, byte row, byte width, byte height, int min_val, int max_val, int *plot_array, String label) {

int max_value = -32000;

int min_value = 32000;

for (byte i = 0; i < 15; i++) {

if (plot_array[i] > max_value) max_value = plot_array[i];

if (plot_array[i] < min_value) min_value = plot_array[i];

}

lcd.setCursor(16, 0); lcd.print(max_value);

lcd.setCursor(16, 1); lcd.print(label);

lcd.setCursor(16, 2); lcd.print(plot_array[14]);

lcd.setCursor(16, 3); lcd.print(min_value);

for (byte i = 0; i < width; i++) { // каждыйстолбецпараметров

int fill_val = plot_array[i];

fill_val = constrain(fill_val, min_val, max_val);

byte infill, fract;

// найти количество целых блоков с учётом минимума и максимума для отображения на графике

if (plot_array[i] > min_val)

infill = floor((float)(plot_array[i] - min_val) / (max_val - min_val) * height * 10);

else infill = 0;

fract = (float)(infill % 10) * 8 / 10; // найти количество оставшихся полосок

infill = infill / 10;

for (byte n = 0; n < height; n++) { // длявсехстрокграфика

if (n < infill && infill > 0) { // пока мы ниже уровня

lcd.setCursor(i, (row - n)); // заполняем полными ячейками

lcd.write(0);

}

if (n >= infill) { // если достигли уровня

lcd.setCursor(i, (row - n));

if (fract > 0) lcd.write(fract); // заполняемдробныеячейки

else lcd.write(16); // если дробные == 0, заливаем пустой

for (byte k = n + 1; k < height; k++) { // всё что сверху заливаем пустыми

lcd.setCursor(i, (row - k));

lcd.write(16);

}

break;

}

}

}

}

void loadClock() {

lcd.createChar(0, LT);

lcd.createChar(1, UB);

lcd.createChar(2, RT);

lcd.createChar(3, LL);

lcd.createChar(4, LB);

lcd.createChar(5, LR);

lcd.createChar(6, UMB);

lcd.createChar(7, LMB);

}

void loadPlot() {

lcd.createChar(0, row8);

lcd.createChar(1, row1);

lcd.createChar(2, row2);

lcd.createChar(3, row3);

lcd.createChar(4, row4);

lcd.createChar(5, row5);

lcd.createChar(6, row6);

lcd.createChar(7, row7);

}

#if (LED_MODE == 0)

#define LED_ON (LED_BRIGHT)

#else

#define LED_ON (255 - LED_BRIGHT)

#endif

void setLED(byte color) {

// сначалавсёвыключаем

if (!LED_MODE) {

analogWrite(LED_R, 0);

analogWrite(LED_G, 0);

analogWrite(LED_B, 0);

} else {

analogWrite(LED_R, 255);

analogWrite(LED_G, 255);

analogWrite(LED_B, 255);

}

switch (color) { // 0 выкл, 1 красный, 2 зелёный, 3 синий (илижёлтый)

case 0:

break;

case 1: analogWrite(LED_R, LED_ON);

break;

case 2: analogWrite(LED_G, LED_ON);

break;

case 3:

if (!BLUE_YELLOW) analogWrite(LED_B, LED_ON);

else {

analogWrite(LED_R, LED_ON - 50); // чуткауменьшаемкрасный

analogWrite(LED_G, LED_ON);

}

break;

}

}

void setup() {

Serial.begin(9600);

pinMode(LED_COM, OUTPUT);

pinMode(LED_R, OUTPUT);

pinMode(LED_G, OUTPUT);

pinMode(LED_B, OUTPUT);

setLED(0);

digitalWrite(LED_COM, LED_MODE);

lcd.init();

lcd.backlight();

lcd.clear();

#if (DEBUG == 1 && DISPLAY_TYPE == 1)

boolean status = true;

setLED(1);

#if (CO2_SENSOR == 1)

lcd.setCursor(0, 0);

lcd.print(F("MHZ-19... "));

Serial.print(F("MHZ-19... "));

mhz19.begin(MHZ_TX, MHZ_RX);

mhz19.setAutoCalibration(false);

mhz19.getStatus(); // первый запрос, в любом случае возвращает -1

delay(500);

if (mhz19.getStatus() == 0) {

lcd.print(F("OK"));

Serial.println(F("OK"));

} else {

lcd.print(F("ERROR"));

Serial.println(F("ERROR"));

status = false;

}

#endif

setLED(2);

lcd.setCursor(0, 1);

lcd.print(F("RTC... "));

Serial.print(F("RTC... "));

delay(50);

if (rtc.begin()) {

lcd.print(F("OK"));

Serial.println(F("OK"));

} else {

lcd.print(F("ERROR"));

Serial.println(F("ERROR"));

status = false;

}

setLED(3);

lcd.setCursor(0, 2);

lcd.print(F("BME280... "));

Serial.print(F("BME280... "));

delay(50);

if (bme.begin(&Wire)) {

lcd.print(F("OK"));

Serial.println(F("OK"));

} else {

lcd.print(F("ERROR"));

Serial.println(F("ERROR"));

status = false;

}

setLED(0);

lcd.setCursor(0, 3);

if (status) {

lcd.print(F("All good"));

Serial.println(F("All good"));

delay(1000);

lcd.clear();

} else {

lcd.print(F("Check wires!"));

Serial.println(F("Check wires!"));

delay(1000);

while (1);

}

#else

#if (CO2_SENSOR == 1)

mhz19.begin(MHZ_TX, MHZ_RX);

mhz19.setAutoCalibration(false);

#endif

rtc.begin();

bme.begin(&Wire);

#endif

bme.setSampling(Adafruit_BME280::MODE_FORCED,

Adafruit_BME280::SAMPLING_X1, // temperature

Adafruit_BME280::SAMPLING_X1, // pressure

Adafruit_BME280::SAMPLING_X1, // humidity

Adafruit_BME280::FILTER_OFF );

if (RESET_CLOCK || rtc.lostPower())

rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

now = rtc.now();

secs = now.second();

mins = now.minute();

hrs = now.hour();

bme.takeForcedMeasurement();

uint32_t Pressure = bme.readPressure();

for (byte i = 0; i < 6; i++) { // счётчикот 0 до 5

pressure_array[i] = Pressure; // забить весь массив текущим давлением

time_array[i] = i; // забить массив времени числами 0 - 5

}

if (DISPLAY_TYPE == 1) {

loadClock();

drawClock(hrs, mins, 0, 0, 1);

drawData();

}

readSensors();

drawSensors();

}

void loop() {

if (sensorsTimer.isReady()) readSensors(); // читаемпоказаниядатчиковспериодом SENS_TIME

#if (DISPLAY_TYPE == 1)

if (clockTimer.isReady()) clockTick(); // дваразавсекундупересчитываемвремяимигаемточками

plotSensorsTick(); // тут внутри несколько таймеров для пересчёта графиков (за час, за день и прогноз)

modesTick(); // тут ловим нажатия на кнопку и переключаем режимы

if (mode == 0) { // в режиме "главного экрана"

if (drawSensorsTimer.isReady()) drawSensors(); // обновляем показания датчиков на дисплее с периодом SENS_TIME

} else { // в любом из графиков

if (plotTimer.isReady()) redrawPlot(); // перерисовываем график

}

#else

if (drawSensorsTimer.isReady()) drawSensors();

#endif

}

Просмотров работы: 175