Введение
Нам хорошо известно влияние микроклимата помещения на здоровье и самочувствие человека. Закономерности и последствия негативного влияние на человека изучают ученые во многих стран мира и предлагают пути решения этой проблемы. В России стандарты микроклимата соответствуют «ГОСТу 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-го класса.
|
|
Качество воздуха в помещении |
|
|
|
Оптимальное |
Допустимое |
||
|
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 модуля для возможности отображения показаний датчиков на смартфоне, добавлением часов реального времени и датчика измерения атмосферного давления для расширения функционала метеостанции, улучшением дизайна.
Цель работы достигнута. Задачи выполнены.
http://arduino.ru/ - материалы по Arduino на русском языке;
http://amperka.ru/ - интернет-магазин, материалы по Arduino в свободном доступе;
https://123d.circuits.io/lab -лаборатория электроники, здесь можно собрать схему на монтажной плате, запрограммировать её и проверить в работе ;
https://www.youtube.com/playlist?list=PLfDmj22jP9S759DT250VVzfZs_4
VnJqLa - видеоуроки Джереми Блума на русском языке (перевод Amperka.ru);
http://arduino.ru/forumy/proekty- проекты на Arduino — описание.
https://vash.market/bytovaya-tehnika/klimaticheskaya-tehnika/vidy-tsifrovyh-i-bytovyh-meteostantsij.html.
https://usamodelkina.ru/9703-domashnyaya-meteostanciya-na-baze-arduino.html. - домашняя метеостанция на базе Ардуино.
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.
https://radioded.ru/proekty-na-arduino/meteostantsiya-na-arduino.-Метеостанция портативная GARIN WS
-https://www.lacrossetechnology.ru/meteostantsiya-portativnaya-garin-ws-1.html. - Метеостанция RST 02559.
http://www.meteo-station.ru/goods/rst-02559.html.
GitHub https://github.com/Norovl/meteoClock/
https://alexgyver.ru/meteoclock/
https://habr.com/ru/post/425901/
https://electricdoma.ru/umniidom/проект-простейшей-метеостанции-на-ар/
https://роботехника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
}