Умный термостат, проветривание и управление освещением с помощью Bluetooth
Компоненты и расходные материалы
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
Приложения и онлайн-сервисы
| ||||
|
Об этом проекте
Введение
Простой, но полезный проект DIY Arduino Thermostat с Bluetooth.
Интеллектуальная программа термостата управляет газовым котлом обогревателя, а система переключает освещение на кухне и вентилятор в ванной с помощью реле - можно управлять кнопками и устройством Android или компьютером через Bluetooth. Цельсия и по Фаренгейту версия также доступна! Все детали ручной работы.
Разработан на плате Arduino Nano (или выше), использует датчик температуры Dallas DS18B20, адаптер Bluetooth HC-05/06, двухцветный OLED-дисплей I2C 128X64 - вы можете выбрать другой ЖК-дисплей / OLED-дисплей, u8glib поддерживает множество типов.
Видео
Видео показывает все важные способы работы, дает идеи, как построить проект с самого начала.
Режим работы обогревателя
1. Режим однократного нагрева (15 минут) по времени . полезно весенними / осенними вечерами
2: Режим термостата (более высокий приоритет) , настроенная целевая температура сохраняется в памяти EEPROM
Алгоритм сохранения котла
Частые, кратковременные переключения сократят срок службы газового котла нагревателя, чтобы избежать этого, программа использует значения коррекции - они декларируют степень перегрева и обратного охлаждения. Более низкая температура требует больших значений коррекции, потому что стены холоднее и лучше адсорбируют тепло свежего нагретого воздуха, поэтому описанный выше эффект будет сильнее.
Обнаружение открытого окна
Программа определяет, открыто ли окно, таким образом, температура падает минимум на -0,2 ° C (-0, 36F) за одну минуту - нагреватель останавливается или не запускается, а вентилятор проветривания включается, чтобы помочь освежить воздух. Когда воздух станет теплее как минимум на +0,12 ° C (+0, 216F) из-за теплоемкости окружающей среды, система вернется в нормальный режим, и событие «Window Alert» будет отклонено.
Обнаружение ошибок
Измеренная температура ниже 0 ° C (32F) или выше 40 ° C (104F) будет оценена как неисправность или другая проблема (ошибка, разбитое окно, пожар и т. Д.), И все устройства отключатся.
Связь по Bluetooth
Приложение Android GUI имеет 8 кнопок, отправляет заглавные и строчные буквы для включения ('A') или выключения ('a') подогревателя по времени, 'B' и 'b' включают проветривание, 'C 'и' c 'огни…
Еще одна сильная сторона моего проекта - это использование для друга-компьютерщика последовательного терминала Bluetooth. Просто поговорите с системой через Bluetooth, используя последовательный терминал - это может быть приложение для Android, но подойдет даже обычный ПК - например, Serial Monitor в Arduino IDE.
Контроллер автоматически отправляет отчеты о температуре каждую минуту, а также мгновенные отчеты обо всех событиях, например, о включении / выключении подключенного устройства, активации процедуры термостата и т. Д.
Контрольные коды
Он принимает контрольные коды и отправляет подтверждающие сообщения. Моя структура команд основана на двухзначных числах, таких как «XY» - где;
«X» - это код устройства, а «Y» - это код операции
30, 31, 32:подсветка выключена / включена / логическое состояние переключения
40, 41, 42:логическое состояние выключения / включения / переключения трансляции
50, 51, 52:логическое состояние выключения / включения / переворота программы одноразового нагревателя
10–24 числа будут приняты в качестве целевой температуры для функции термостата
‘R’ - отчет о рабочем состоянии контролируемых устройств
‘W’ - вручную отключает событие «уведомление об окне», если вы не хотите ждать его автоматического закрытия
‘A, a… H, h’ - буквы принимаются так, как если бы приложение с графическим интерфейсом отправляло
Версия по Фаренгейту
Я преобразовал все корректирующие переменные, эталонные и передаточные значения, поэтому система сохранила свои расчетные и рабочие особенности.
Всего несколько модификаций. Новые коды устройств версии по Фаренгейту:
1 - Освещение (10:выключено, 11:включено, 12:перевернуто)
2 - Выход в эфир
3 - Нагреватель
50–76 чисел - целевые значения температуры
Продолжение
ОБНОВЛЕНИЕ:полная система домашней автоматизации с внутренней связью Bluetooth и голосовым управлением!
Библиотеки и ссылки
DallasTemperature, elapsedMillis, OneWire, SoftwareSerial, olikraus / u8glib
Если вы используете разные кнопочные резисторы или вам нужно проверить показания A0, я предлагаю проверить это:
http://blog.codebender.cc/2015/07/20/tutorial-multiple-buttons-on-1-analog-pin/
Код
- Термостат v11 - версия Celsius.ino
- Термостат v11 - версия по Фаренгейту.ino
Термостат v11 - версия по Цельсию .ino Arduino
Программный код объясняет сам себя, полезно для новичков. Хорошо прокомментированы, описаны все важные шаги; что, почему и как. Разделены на модули по функциям, поэтому их легко просматривать.// Celsius version v1.1 // Программный код интеллектуального термостата Arduino для умного дома, // на основе платы Arduino Nano (или выше), термодатчика DS18B20, Адаптер Bluetooth HC-05, двухцветный OLED-дисплей I2C 128X64 .// Системой можно управлять с помощью кнопок и смартфона Android через Bluetooth. .// Обогреватель имеет два режима работы. 1:Режим однократного нагрева (15 минут) по времени, 2:Режим термостата (более высокий приоритет). Настроенная целевая температура // хранится в EEPROM. Программа обнаруживает аппаратные ошибки и открывание окон - в этих случаях обогреватель останавливается и / или не запускается .//// Разработано и запрограммировано Дьюла Оси .// Все права защищены .// --------- -------------------------------------------------- -------------------------------------------------- ----------------------- // ---- Отображение шины I2C, SDA (TX) -> A4, SCL (RX) -> A5 # include "U8glib.h" U8GLIB_SSD1306_128X64 u8g (U8G_I2C_OPT_NONE); // отображаем конструкторbyte frame =0; // указатель начального логотипа // ---- Порты и соответствующие объявленияconst byte buzzer =9; // зуммер для D9int btnVal; // запоминает аналоговые значения с кнопокconst byte relayA =11; // airingbool aState =0; bool aStateByCmd; // если "оконное предупреждение" исчезло, управление трансляцией возвращается в исходное состояниеconst byte relayL =13; // световой сигнал lState =0; const byte relayH =10; // байт состояния нагревателя ledH =6; // Порты ШИМ позволяют регулировать уровень выходного сигнала, используемый для изменения яркости .const byte ledA =5; const byte ledL =3; const byte bright [3] ={0, 10, 100}; byte brightHeat =bright [2]; # define ledInterval 1000 // интервал мигания светодиода нагревателяunsigned long prev =0; // ---- Строки для отображения и последовательных отчетов #define STATE_ITEMS 3 // строки индикатора состояния устройства для выходов // i -> 0 1 2const String state_str [STATE_ITEMS] ={"on.", "Off.", "Auto."}; String HeatingState; String airingState; String lightingState; #define FUNCT_ITEMS 11 // i -> 0 1 2 3 4 5 6 7 8 9 10 String funct_str [FUNCT_ITEMS] ={«Нагреватель есть», «Проветривание есть», «Освещение есть», «Окно Предупреждение! "," Ошибка оборудования! "," Нажмите клавишу>> "или" или отправьте код! "," Target tempr ="," Temperature ="," * "," - "}; // - - Функции измерения температуры и нагревателя # включаютelapsedMillis timer0; // 8-битный таймер ШИМ, используемый функцией elapsedMillis () # define sftyTmrInterval 15 * 60000 // одноразовый нагрев (15 минут) интервал временного режима [мс] bool sftyTmrEnded; // логический запуск, таймер 0 закончился # include byte tTarget; // скорректированный целевой temprconst int addr =0; // текущий адрес переменной tTarget в EEPROM memorybool hState =0; // нагреватель логический statebool hThermostat =0; // логическое состояние термостата # include "OneWire.h" #include "DallasTemperature.h" #define DS18B20 2 // настройка шины OneWire на D2OneWire temprWire (DS18B20); // настраиваем DS18B20 для работы с шиной OneWire Датчики температуры Даллас (&temprWire); float tempr; // измеренное значение float temprPrev; // копия измеренного значения для анализа тренда bool windowAlrt =0; // указанная степень tempr dropbool mesError =0; // измеренное значение температуры вне диапазона, указанного как normalconst long temprInterval =60000; // интервал циклического измерения температуры [мс] unsigned long temprTmrPrev =0; // прошедшее время будет предыдущим при вызове temprMeas () float heatCorrVal; // объявляет степень перегрева и охлаждения, см. функцию tempMeas () // ---- Конфигурация последовательной связи на виртуальном RXD / TXD # include // SW последовательные выводы RX и TX для HC-05const int RX1 =8; const int TX1 =4; SoftwareSerial sUART (RX1, TX1); char RX [2]; // сохранить полученный серийный пул данных errMsgSentBySys =0; bool startup =1; // постоянно избегать дублирования отчета BT при запускеconst uint8_t frame1 [] U8G_PROGMEM ={// Карта XBM 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF , 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF , 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF , 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07FF, 0xFF, 0xFF , 0x7F, 0x00, 0xFC, 0xFF, 0x7F, 0xF0, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0x7F, 0xFFF0, 0x8F , 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFFFF, 0xFF, 0xFF, 0x1F, 0xFFFF, 0xFF, 0xFF, 0xFFF, 0xFF, 0xFF , 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0x1F, 0x7F, 0x8C , 0x3F, 0x1E, 0xFF, 0x00, 0xFE, 0x1F, 0xFF, 0xF1, 0x00, 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x7F, 0x8C, 0x3F, 0x1E, 0xFF, 0x00, 0xFE, 0x1F, 0x1F , 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x1F, 0x0C, 0x3E, 0x1E, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x8F, 0xFF, 0x1x3, 0x0E, 0x1FE, 0x1FE , 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x7, 0x, 0xFE, 0x1F, 0x7, 0x, 0xFE , 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x7C, 0x30, 0xFE, 0x7F, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x3, 0x, 0x0C, 0x1F, 0x3, 0x, 0x0C , 0xF8, 0x1F, 0x7C, 0xF0, 0x00, 0x7E, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x0x, 0x00x, 0x7C, 0xF0, 0x0x, 0x0x , 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1x3, 0x1E, 0x3E, 0x1E, 0x1E , 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF078, 0x3F, 0x078, 0x3F, 0xF078, 0x3F, 0xF078, 0x3F, 0xF078, 0x3F 0x7E, 0x00, 0x3C, 0x80, 0x07, 0xF0, 0x00, 0xF8, 0x7F, 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0x3F, 0x00, 0x7E, 0x00, 0x3C, 0x80, 0x07, 0xF0x, 0x8F0 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0xFF, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFFFF, 0xFF, 0xFF, 0xFF, 0xFFFF, 0xFF, 0xFF 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x7E, 0x06, 0xE6, 0x3F, 0x06, 0xC6, 0x7F, 0xFE, 0xE7, 0x3F, 0x7E, 0xFE, 0xC7, 0x7F, 0x00, 0x00, 0x30, 0x06x, 0x06, 0x06, 0x06 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x60, 0x06 0x00, 0x00, 0x30, 0x1E, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x3E, 0x66, 0x60, 0x66, 0x06 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0xE6, 0x61, 0x1E, 0 xC7, 0x3F, 0x70, 0xE0, 0x3F, 0x3C, 0xFE, 0xC3, 0x3F, 0x00, 0x00, 0x3C, 0x7E, 0xE6, 0x61, 0x1E, 0xC7, 0x3F, 0x70, 0xE0, 0x3F, 0x3, 0x3C, 0x3F 0x00, 0x00, 0x3C, 0xDE, 0xE7, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x1D, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE7, 0x170, 0x61 0x70, 0xE0, 0x31, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0x1x70, 0x00, 0x00, 0x1E, 0x00, 0x00 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x7F, 0x1E, 0xE6, 0x3F, 0xFC 0x3, 0xE3 0x61, 0x7E, 0xFE, 0xE7, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00,}; установка void () {sUART.begin (9600); pinMode (relayH, ВЫХОД); relayHandlerH (4); // получить рабочее состояние pinMode (ledH, OUTPUT); pinMode (relayA, ВЫХОД); relayHandlerA (4); pinMode (ledA, ВЫХОД); pinMode (relayL, ВЫХОД); relayHandlerL (4); pinMode (ledL, ВЫХОД); pinMode (зуммер, ВЫХОД); sensor.begin (); // запускаем DS18B20 temprMeas (); // не ждем таймера, вызываем функцию один раз при запуске tTarget =EEPROM.read (addr); // считываем ранее сохраненное значение tTarget из текущего адреса EEPROM при запуске startup =0; если (! MeasError) {sTX (8); // вызов мгновенного отчета о рабочем состоянии после запуска} else {sTX (2); }} недействительный цикл () {temprTimer (); ledHandler (); btnReadings (); sRX (); securityTmr (); u8g.firstPage (); // цикл scr do {draw (); } while (u8g.nextPage ()); если (кадр ==0) {задержка (3000); frame =1; clrScr (); }} void btnReadings () {// --------- Показания Btn btnVal =analogRead (A0); // чтение аналогового значения из A0 if (btnVal> =510 &&btnVal <=516) {// btn Lighting delay (100); // btn debounce buzz (3, 1); relayHandlerL (2); // вызываем правильную функцию с кодом операции переворота логического состояния в качестве параметра} else if (btnVal> =849 &&btnVal <=855) {// btn Airing if (windowAlrt ==1) {// если система находится в режиме Window Alert, отключить его windowAlrt =0; гудение (4, 3); relayHandlerA (3); } else {// else включить / выключить задержку проветривания вентилятора (100); гудение (3, 1); relayHandlerA (2); }} else if (btnVal> =927 &&btnVal <=933) {// btn Одноразовый нагрев (15 минут), задержка режима по времени (100); гудение (3, 1); relayHandlerH (2); } else if (btnVal> =767 &&btnVal <=777) {// btn уменьшить задержку tTarget (100); tTargetHandler (0); } else if (btnVal> =687 &&btnVal <=697) {// btn увеличивает задержку tTarget (100); tTargetHandler (1); } else if (btnVal> =856 &&btnVal <=862) {// одновременно увеличиваем и уменьшаем биты tTarget =14; // <====начальное значение - нажимайте эти кнопки при самом первом включении! }} void sRX () {// ------------- Получение последовательных данных while (sUART.available ()> 0) {// если данные доступны для чтения для (byte i =0; я <2; я ++) {RX [я] =sUART.read (); }} int iRX [2]; для (байт i =0; i <2; i ++) {iRX [i] =RX [i] - '0'; } switch (RX [0]) {// ------------ принять ОДИН БУКВЕННЫЙ управляющий код case 'A':relayHandlerH (1); // 1 =при перерыве; case 'a':relayHandlerH (0); // 0 =выключить перерыв; // Полученные последовательные данные могут быть одной буквой алфавита из Android-приложения «Arduino case 'B':// Bluetooth Control Device». Если правильный алфавитный relayHandlerA (1); // приходит символ, программный код не дождется второго, break; // но вызывает соответствующую функцию с правильным кодом операции. case 'b':// Случаи объединения числовых данных можно увидеть ниже. relayHandlerA (0); ломать; case 'C':relayHandlerL (1); ломать; case 'c':relayHandlerL (0); ломать; case 'D':case 'd':tTarget =21; tTargetEEPROM (); гудение (3, 1); ломать; case 'E':case 'e':tTarget =19; tTargetEEPROM (); гудение (3, 1); ломать; case 'F':case 'f':tTarget =14; tTargetEEPROM (); гудение (3, 1); ломать; case 'R':// вызов обзорного отчета об управляемых устройствах case 'r':sTX (8); ломать; case 'W':// отключить состояние оповещения окна case 'w':windowAlrt =0; гудение (4, 3); relayHandlerA (3); ломать; } // ----------------------- принять КОМБИНИРОВАННЫЕ ЧИСЛОВЫЕ контрольные коды // В этом случае приходит двузначный числовой контрольный код в символьном формате, // например, из последовательного приложения Bluetooth для Android. После преобразования символа // в целое число (только если первый символ равен '1' или '2') последует процесс слияния, // и система условий и операторов примет решение и выполнит его. // Соответствующие числовые коды:// // ---------------- Целевая температура:// 10 - 24 значения будут приняты в качестве целевой температуры для функции термостата. // // ---------------- Коды управления устройством:// Первый =код устройства, Второй =код оператора // 30, 31, 32 включает освещение:30 =выключено, 31 =вкл. // 32 =переключить логическое состояние (вкл. -> выкл. / Выкл. -> вкл.) // 40, 41, 42 будут делать то же самое с проветривателем // 50, 51, 52 обрабатывает одноразовый обогрев (15 mins) программа подогрева по времени, как указано выше // // ---------------- Коды секретных операторов:// X3, X4 классифицируются, используются только для вызовов функций внутренними последовательностями программы if ( RX [0] =='3') {relayHandlerL (iRX [1]); } если (RX [0] =='4') {relayHandlerA (iRX [1]); } если (RX [0] =='5') {relayHandlerH (iRX [1]); } if ((iRX [0] * 10 + iRX [1] <=24) &&(iRX [0] * 10 + iRX [1]> =10)) {// принимаем только числовые значения от 10 до 24 tTarget =iRX [0] * 10 + iRX [1]; // объединить два целых числа и установить tTarget tTargetEEPROM (); // после установки вызвать функцию-обработчик EEPROM и buzz (3, 1); // записываем значение tTarget в соответствующий байт EEPROM} if (RX [0] =='0') {// проверяем (byte i =1; i <5; i ++) {buzz (5, 2); }} for (byte i =0; i <2; i ++) {// очищаем все переменные получателя сообщения и преобразования RX [i] ='Z'; }} void relayHandlerL (byte lOperator) {// Последовательность обработчика освещения // операторы:0 =выключено, 1 =включено, 2 =перевернуто состояние, 4 =заполнено / повторно заполнено состояние освещения char var. если ((measureError) &&((lOperator ==1) || (lOperator ==2))) {sTX (4); возвращение; } if ((lOperator ==2) || (lOperator ==0) &&(lState) || (lOperator ==1) &&(! lState)) {lState =! lState; digitalWrite (relayL, lState); гудение (2, 1); } if (lOperator> =0) {// заполняем график рабочего состояния соответствующей строкой индикатора состояния if (lState) {lightingState =state_str [0]; } еще {lightingState =state_str [1]; } если (! запуск) {sTX (7); }}} void relayHandlerA (byte aOperator) {// Последовательность обработчика трансляции if ((MeasError) &&((aOperator ==1) || (aOperator ==2))) {// операторы:0 =off, 1 =on, 2 =перевернуть состояние, sTX (4); // 3 =вызывается функцией temprMeas (), 4 =заполнять / пополнять состояние трансляции char var. возвращение; } aState =digitalRead (relayA); если (! windowAlrt) {если ((aOperator ==2) || (aState) &&(aOperator ==0) || (! aState) &&(aOperator ==1)) {aState =! aState; digitalWrite (relayA, aState); aStateByCmd =digitalRead (relayA); гудение (2, 1); }} if (aOperator ==3) {// вызывается функцией temprMeas (), windowAlrt завершается или запускается if ((! aState) &&(windowAlrt) || (aState) &&(! windowAlrt) &&(! aStateByCmd )) {digitalWrite (relayA, windowAlrt); }} aState =digitalRead (relayA); if (aOperator> =0) {if (aState) {если (windowAlrt) {airingState =state_str [2]; } еще {airingState =state_str [0]; }} еще {airingState =state_str [1]; }} если (! запуск) {sTX (6); }} void relayHandlerH (byte hOperator) {// Последовательность обработчика нагревателя // следующие операторы:0 =выключено, 1 =включено, 2 =перевернуто состояние, // 3 =вызвано функцией temprMeas (), 4 =заполнение / заполнение состояние обогревателя char var. если ((measureError) &&((hOperator ==1) || (hOperator ==2))) {sTX (4); возвращение; } if ((! hThermostat) &&(! windowAlrt) &&(! MeasError)) {// включение / выключение временного режима одноразового нагрева (15 минут) if ((hOperator ==2) || (hOperator ==1 ) &&(! hState) || (! hOperator) &&(hState)) {buzz (2, 1); hState =! hState; sftyTmrEnded =0; timer0 =0; digitalWrite (relayH, hState); }} если (windowAlrt) {sTX (3); } if (hOperator ==3) {// эта функция вызывается функцией temprMeas () (op 3) // для проверки логических значений windowAlrt и MeasError if ((windowAlrt) &&(hState)) {// окно открыт и нагреватель работает digitalWrite (relayH, 0); гудение (5, 3); } if ((! windowAlrt) &&(! MeasError)) {if ((hThermostat) || (! hThermostat) &&(hState) &&(sftyTmrEnded)) {digitalWrite (relayH, hThermostat); // продолжаем выполнение команды процедуры термостата}}} hState =digitalRead (relayH); если (hOperator> =0) {если (hState) {если (hThermostat) {heatingState =state_str [2]; } еще {heatingState =state_str [0]; }} еще {heatingState =state_str [1]; } если ((((! windowAlrt) &&(hOperator! =3)) || (hState)) &&(! запуск)) {sTX (5); }}} voidsecurityTmr () {// Таймер для режима одноразового нагрева (15 минут) if ((hState) &&(! sftyTmrEnded) &&(timer0> sftyTmrInterval) &&(! hThermostat)) {sftyTmrEnded =1; relayHandlerH (0); для (байт я =1; я <5; я ++) {шум (я, 2); }}} void temprTimer () {// Циклический таймер для temprMeas () unsigned long temprTmrCurr =millis (); если (интервал времени <=темпрТмрКурр - темпрТмрПрев) {темпрТмрПрев =темпрТмрКурр; temprMeas (); }} void temprMeas () {// ----------- Последовательность измерения и сравнения температуры temprPrev =tempr; // сохраняем значение для следующего сравнения sensor.requestTemperatures (); // обновить показания датчика tempr =sizes.getTempCByIndex (0); // считываем температуру if ((tempr> =40) || (tempr <=0)) {// крайние измеренные значения:if (! errMsgSentBySys) {// -127, -196.60 - это HW-ошибки, +85 - обычно SW ошибка, но sTX (4); // может быть пожар или разбитое окно} errMsgSentBySys =1; hThermostat =0; если (hState) {relayHandlerH (0); } если (состояние) {relayHandlerA (0); } если (lState) {relayHandlerL (0); } mesError =1; for (байт i =1; i <10; i ++) {buzz (4, 1); задержка (50); }} еще {temprPrev =tempr; mesError =0; errMsgSentBySys =0; } if (! measureError) {// ------------ Начало последовательности анализа температуры if (tempr <=17) {// Частое, кратковременное переключение газового котла нагревателя прервется его время жизни heatCorrVal =0,5; // Значение heatCorrVal помогает избежать этого. Объявляет степень перегрева и охлаждения обратно. } // Более низкая температура требует большего значения heatCorrVal, потому что стены холоднее и лучше адсорбируют if ((tempr> 17) &&(tempr <19)) {// тепло от только что нагретого воздуха, поэтому описанный выше эффект будет более эффективно. heatCorrVal =0,4; } if (tempr> =19) {heatCorrVal =0,3; } if (tTarget - tempr> =heatCorrVal) {// вычитаем измеренное значение из целевого, если разница равна или больше heatCorrVal sftyTmrEnded =1; // деактивируем временную программу одноразового нагрева (15 минут), если она работает hThermostat =1; // включаем жужжание термостата (1, 1); } if ((tTarget - tempr <=-1 * heatCorrVal) &&(hThermostat)) {hThermostat =0; } if ((temprPrev - tempr> =0.2) &&(! windowAlrt) &&(tempr <=20)) {// в цикле измерения и в отопительный сезон температура windowAlrt =1; // пропадает, оценивается как открытое окно sftyTmrEnded =1; for (байт i =1; i <5; i ++) {buzz (4, 1); задержка (50); } relayHandlerA (3); // вызываем функцию трансляции (opcode =3), чтобы освежить воздух} if ((temprPrev - tempr <=-0.12) &&(windowAlrt)) {// tempr. падение закончилось, воздух стал теплее windowAlrt =0; // из-за теплоемкости окружающей среды buzz (4, 3); // так что вернемся в нормальный режим relayHandlerA (3); } relayHandlerH (3); // функция проверит параметр вызывающего абонента param (3) &windowAlrt &MeasError логические if (! windowAlrt) {sTX (1); } }}void tTargetHandler (bool set) { // set the needed tempr by increasing or decreasing if (!set) { // incr if (tTarget <24) { // until it reaches the upper limit tTarget++; buzz(3, 1); } else { buzz(2, 3); } } else { // decr if (tTarget> 10) { tTarget--; buzz(3, 1); } else { buzz(2, 3); } } tTargetEEPROM();}void tTargetEEPROM() { EEPROM.write(addr, tTarget); // after incr/decr/set, write the tTarget value to the appropriate byte of the EEPROM delay(10); sTX(2);}void draw(void) { // logo handler if (frame ==0) { u8g.drawXBMP( 0, 0, 128, 64, frame1); } else if (frame ==1) screenFunctState(); } void screenFunctState(void) { // function state screen temprWriteOut(0, 64); u8g.drawHLine(0, 46, 128); u8g.setFont(u8g_font_unifont); if (!windowAlrt) { u8g.setPrintPos( 0, 14); u8g.print(funct_str[0]); u8g.setPrintPos(84, 14); u8g.print(heaterState); } else { u8g.setPrintPos( 0, 14); u8g.print(funct_str[3]); } u8g.setPrintPos( 0, 28); u8g.print(funct_str[1]); u8g.setPrintPos(88, 28); u8g.print(airingState); u8g.setPrintPos( 0, 42); u8g.print(funct_str[2]); u8g.setPrintPos(95, 42); u8g.print(lightingState); if ((!hState) &&(!aState) &&(!lState)) { screenStndby(); // if all of controlled devices are in off, call standby screen }}void screenStndby() { // standby scr u8g.firstPage(); do { u8g.setFontRefHeightText(); u8g.setFont(u8g_font_unifont); if (!measError) { u8g.setPrintPos(33, 52); u8g.print(funct_str[5]); u8g.setPrintPos( 8, 64); u8g.print(funct_str[6]); } else { u8g.setPrintPos( 4, 48); u8g.print(funct_str[4]); } temprWriteOut(0, 16); } while( u8g.nextPage() );}void temprWriteOut (byte tX, byte tY) { // draw tempr &tTarget variables onto different coordinates u8g.setFont(u8g_font_courB14);//u8g.setFont(u8g_font_6x12); // you can save ~10% of prog.memory using this font with 2x2 scale char buftTarget[9]; sprintf (buftTarget, "%d", tTarget); // int to char//u8g.setScale2x2();//tY =tY / 2; u8g.setPrintPos(tX, tY); u8g.print(buftTarget); u8g.setPrintPos(tX+18, tY); u8g.print(funct_str[9]); u8g.setPrintPos(tX+50, tY); u8g.print(tempr); u8g.print(char(176)); u8g.print("C");//u8g.undoScale();}void clrScr(){ u8g.firstPage(); do { } while( u8g.nextPage() );}void ledHandler() { // the brightness of a led is low, if the indicated device is off, and high, if its on if (aState) { analogWrite(ledA, bright[2]); } else { analogWrite(ledA, bright[1]); } if (lState) { analogWrite(ledL, bright[2]); } else { analogWrite(ledL, bright[1]); } if (hState) { if (!hThermostat) { ledBlnk(); // the heater led blinks when the One Time Heating (15 mins) timed mode is activated, } else { brightHeat =bright[2]; // and constant bright, if the thermostat routine is active } } else { brightHeat =bright[1]; } analogWrite(ledH, brightHeat);}void ledBlnk() { unsigned long curr =millis(); if (ledInterval <=curr - prev) { // subtract prev value from current, if the difference equals or greater than ledInterval const. prev =curr; // overwrite the earlier value with the current and flip brightness level if (brightHeat ==bright[1]) { brightHeat =bright[2]; } else { brightHeat =bright[1]; } } analogWrite(ledH, brightHeat);}void buzz(byte b, byte d) { // call with frequency and delay parameters tone(buzzer, b * 1000); delay(d * 100); noTone(buzzer);}void sTX(byte reportTX) { // sending serial reports switch (reportTX) { case 0:for (byte i =0; i <9; i++) { sUART.print(funct_str[10]); } sUART.println(funct_str[10]); ломать; case 1:sUART.print(funct_str[8]); // Tempr. sUART.print(tempr); sUART.print(char(176)); sUART.println("C"); ломать; case 2:sUART.print(funct_str[7]); // TTemp sUART.print(tTarget); sUART.print(char(176)); sUART.println("C"); ломать; case 3:sUART.print(funct_str[3]); // Window Alert sUART.print(funct_str[9]); sUART.print(tempr); sUART.print(char(176)); sUART.println("C"); ломать; case 4:sUART.println(funct_str[4]); // Error report break; case 5:sUART.print(funct_str[0]); // Working state of devices sUART.println(heaterState); ломать; case 6:sUART.print(funct_str[1]); sUART.println(airingState); ломать; case 7:sUART.print(funct_str[2]); sUART.println(lightingState); ломать; case 8:// Overview report sTX(0); relayHandlerH(4); relayHandlerA(4); relayHandlerL(4); sTX(2); if (measError) { sTX(4); } ломать; }}
Thermostat v11 - Fahrenheit version.inoArduino
The program code explains itself, useful for beginners. Well commented, describes every important steps; what, why and how. Divided into modules by functions, that’s why easy to overview.Works in Fahrenheit, I changed only the Target temperature values (50-76), and the device codes (1, 2 and 3).
// Fahrenheit version v1.1// Program code of an intelligent Arduino smarthome thermostat solution, // based on Arduino Nano (or higher) board, DS18B20 thermo sensor, HC-05 Bluetooth adapter, I2C 128X64 bicolor OLED display.// The system can be controlled by buttons and Android smartphone via bluetooth.//// It handles the HEATER gas boiler, the bathroom AIRING ventilator and the kitchen LIGHTING - swithed with relays.// The heater has two working ways. 1:One Time Heating (15 mins) timed mode, 2:Thermostat mode (higher priority). The adjusted target tempr.// stored in EEPROM. The program detects hardware errors and window opening - in these cases the heater stops and/or will not start.//// Designed and programmed by Gyula Osi.// All rights reserved.// ------------------------------------------------------------------------------------------------------------------------------------// ---- Display I2C Bus, SDA(TX) -> A4, SCL(RX) -> A5#include "U8glib.h"U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // display constructorbyte frame =0; // start logo pointer// ---- Ports and related declarationsconst byte buzzer =9; // buzzer to D9int btnVal; // stores analog values from buttonsconst byte relayA =11; // airingbool aState =0;bool aStateByCmd; // if "window alert" is gone, the airing control goes back to the original stateconst byte relayL =13; // lightingbool lState =0;const byte relayH =10; // heaterconst byte ledH =6; // PWM ports allow output level adjustment used to change brightnessconst byte ledA =5; const byte ledL =3;const byte bright[3] ={0, 10, 100};byte brightHeat =bright[2];#define ledInterval 1000 // heater led blinking intervalunsigned long prev =0;// ---- Strings for Display and Serial Reports #define STATE_ITEMS 3 // device state indicator strings for outputs// i -> 0 1 2const String state_str[STATE_ITEMS] ={"on.", "off.", "auto."}; String heaterState; String airingState;String lightingState;#define FUNCT_ITEMS 11// i -> 0 1 2 3 4 5 6 7 8 9 10 String funct_str[FUNCT_ITEMS] ={"Heater is ", "Airing is ", "Lighting is ", "Window Alert!", "Hardware Error!", "Hit a Key>>", "or send a Code!", "Target tempr =", "Temperature =", " * ", " -"};// ---- Temperature Measurement and Heater Related Features#includeelapsedMillis timer0; // 8-bit, PWM timer, used by function elapsedMillis()#define sftyTmrInterval 15 * 60000 // one Time Heating (15 mins) timed mode interval [ms]bool sftyTmrEnded; // boolean startup, the timer0 has ended#include byte tTarget; // adjusted target temprconst int addr =0; // the current address of the tTarget variable in the EEPROM memorybool hState =0; // heater boolean statebool hThermostat =0; // thermostat boolean state#include "OneWire.h" #include "DallasTemperature.h"#define DS18B20 2 // setup the OneWire bus on D2OneWire temprWire(DS18B20); // setup DS18B20 to work on the OneWire busDallasTemperature sensors(&temprWire);float tempr; // measured valuefloat temprPrev; // copy of measured value for trend analysisbool windowAlrt =0; // specified degree of tempr dropbool measError =0; // measured tempr value is out of the range specified as normalconst long temprInterval =60000; // cyclic tempr measurement interval [ms]unsigned long temprTmrPrev =0; // the elapsed will be the previous when temprMeas() calledfloat heatCorrVal; // declares the degree of overheating and cooling back, see tempMeas() function// ---- Configuration of Serial Communication on virtual RXD/TXD#include // SW serial RX &TX pins for HC-05const int RX1 =8;const int TX1 =4;SoftwareSerial sUART(RX1,TX1); char RX[2]; // store received serial databool errMsgSentBySys =0; bool startup =1; // keep avoid a duplicate BT report at startupconst uint8_t frame1[] U8G_PROGMEM ={ // XBM map 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0x7F, 0xF0, 0x3F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFC, 0xFF, 0x7F, 0xF0, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0x1F, 0x7F, 0x8C , 0x3F, 0x1E, 0xFF, 0x00, 0xFE, 0x1F, 0xFF, 0xF1, 0x00, 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x7F, 0x8C, 0x3F, 0x1E, 0xFF, 0x00, 0xFE, 0x1F, 0xFF, 0xF1, 0x00, 0x18, 0xC0, 0x8F, 0xFF, 0x1F, 0x1F, 0x0C, 0x3E, 0x1E, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x8F, 0xFF, 0x1F, 0x1F, 0x0C, 0x3E, 0x1E, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0x31, 0xFE, 0x7F, 0xFC, 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x7C, 0x30, 0xFE, 0x7F, 0xF0, 0x0F, 0x0E, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0xFC, 0x00, 0xF8, 0x1F, 0x7C, 0x30, 0xFE, 0x7F, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x00, 0x7E, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x00, 0x7E, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x0F, 0xFE, 0x18, 0x1F, 0x0C, 0x3E, 0x1E, 0x3C, 0x3E, 0xF8, 0x1F, 0x7C, 0xF0, 0x3F, 0x78, 0xF0, 0x3F, 0x00, 0x7E, 0x00, 0x3C, 0x80, 0x07, 0xF0, 0x00, 0xF8, 0x7F, 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0x3F, 0x00, 0x7E, 0x00, 0x3C, 0x80, 0x07, 0xF0, 0x00, 0xF8, 0x7F, 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0xFF, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x06, 0xE6, 0x3F, 0x06, 0xC6, 0x7F, 0xFE, 0xE7, 0x3F, 0x7E, 0xFE, 0xC7, 0x7F, 0x00, 0x00, 0x30, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x06, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x1E, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x30, 0x3E, 0x66, 0x60, 0x06, 0x66, 0x00, 0x60, 0x60, 0x60, 0x30, 0x06, 0x60, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0xE6, 0x61, 0x1E, 0 xC7, 0x3F, 0x70, 0xE0, 0x3F, 0x3C, 0xFE, 0xC3, 0x3F, 0x00, 0x00, 0x3C, 0x7E, 0xE6, 0x61, 0x1E, 0xC7, 0x3F, 0x70, 0xE0, 0x3F, 0x3C, 0xFE, 0xC3, 0x3F, 0x00, 0x00, 0x3C, 0xDE, 0xE7, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x1D, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE7, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x31, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x3C, 0x1E, 0xE6, 0x61, 0x1E, 0x07, 0x70, 0x70, 0xE0, 0x61, 0x3C, 0x1E, 0x00, 0x70, 0x00, 0x00, 0x7F, 0x1E, 0xE6, 0x3F, 0xFC, 0xE3, 0x3F, 0x70, 0xE0, 0x61, 0x7E, 0xFE, 0xE7, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };void setup() { sUART.begin(9600); pinMode(relayH, OUTPUT); relayHandlerH(4); // get the working state pinMode(ledH, OUTPUT); pinMode(relayA, OUTPUT); relayHandlerA(4); pinMode(ledA, OUTPUT); pinMode(relayL, OUTPUT); relayHandlerL(4); pinMode(ledL, OUTPUT); pinMode (зуммер, ВЫХОД); sensor.begin (); // start DS18B20 temprMeas(); // do not wait for the meas.timer, call the function once at startup tTarget =EEPROM.read(addr); // read the previously stored tTarget value from the current address of the EEPROM at startup startup =0; if (!measError) { sTX(8); // call for instant report of working states after startup } else { sTX(2); }}void loop() { temprTimer(); ledHandler(); btnReadings(); sRX(); safetyTmr(); u8g.firstPage(); // scr loop do { draw(); } while( u8g.nextPage() ); if (frame ==0) { delay(3000); frame =1; clrScr(); }}void btnReadings() { // --------- Btn Readings btnVal =analogRead(A0); // read analog val from A0 if (btnVal>=510 &&btnVal <=516) { // btn Lighting delay(100); // btn debounce buzz(3, 1); relayHandlerL(2); // call proper function with logical state flip opcode as parameter } else if (btnVal>=849 &&btnVal <=855){ // btn Airing if (windowAlrt ==1) { // if the system is in Window Alert mode, disable it windowAlrt =0; buzz(4, 3); relayHandlerA(3); } else { // else turn on/off the airing ventilator delay(100); buzz(3, 1); relayHandlerA(2); } } else if (btnVal>=927 &&btnVal <=933){ // btn One Time Heating (15 mins) timed mode delay(100); buzz(3, 1); relayHandlerH(2); } else if (btnVal>=767 &&btnVal <=777) { // btn decrease tTarget delay(100); tTargetHandler(0); } else if (btnVal>=687 &&btnVal <=697) { // btn increase tTarget delay(100); tTargetHandler(1); } else if (btnVal>=856 &&btnVal <=862) { // inc &dec btns at the same time tTarget =14; // <====initial value - press these buttons at the very first powerup! }}void sRX() { // ------------- Receive Serial Data while (sUART.available()> 0) { // if data is available to read for (byte i =0; i <2; i++) { RX[i] =sUART.read(); } } int iRX[2]; for (byte i =0; i <2; i++) { iRX[i] =RX[i] - '0'; } switch (RX[0]) { // ------------ accept SINGLE ALPHABETICAL control codes case 'A':relayHandlerH(1); // 1 =on break; case 'a':relayHandlerH(0); // 0 =off break; // Received serial data can be a single alphabetical letter from "Arduino case 'B':// Bluetooth Control Device" Android app. If a proper alphabetical relayHandlerA(1); // character arrives, the program code will not wait for the second one, break; // but calls the applicable function with a proper operation code. case 'b':// Cases of combined numeric data can be seen below. relayHandlerA(0); ломать; case 'C':relayHandlerL(1); ломать; case 'c':relayHandlerL(0); ломать; case 'D':case 'd':tTarget =21; tTargetEEPROM(); buzz(3, 1); ломать; case 'E':case 'e':tTarget =19; tTargetEEPROM(); buzz(3, 1); ломать; case 'F':case 'f':tTarget =14; tTargetEEPROM(); buzz(3, 1); ломать; case 'R':// call for an overview report about controlled devices case 'r':sTX(8); ломать; case 'W':// disable Window Alert state case 'w':windowAlrt =0; buzz(4, 3); relayHandlerA(3); ломать; } // ----------------------- accept COMBINED NUMERIC control codes // In this case a two-digit numeric control code arrives in char format, // from an Android bluetooth serial app for instance. After a char to integer // conversion (only if the first char is '1' or '2') a merge-process will follow, // and the system of conditions and statements will make a decision and execute it. // Appropriate numeric codes are:// // ---------------- Target Temperature:// 50 - 76 values will be accepted as a target temperature for the thermostat function. // // ---------------- Device Control Codes:// First =device code, Second =operator code // 10, 11, 12 turns the lighting:10=off, 11=on // 12=flip logical state (on -> off / off -> on) // 20, 21, 22 will do the same to the airing ventilator // 30, 31, 32 handles the One Time Heating (15 mins) timed heater program as above // // ---------------- Classified Operator Codes:// X3, X4 are classified, used only for function calls by inner program sequences if (RX[0] =='1') { relayHandlerL(iRX[1]); } if (RX[0] =='2') { relayHandlerA(iRX[1]); } if (RX[0] =='3') { relayHandlerH(iRX[1]); } if ((iRX[0] * 10 + iRX[1] <=76) &&(iRX[0] * 10 + iRX[1]>=50)) { // accept only numeric values between 50 &76 tTarget =iRX[0] * 10 + iRX[1]; // merge two integers and set tTarget tTargetEEPROM(); // after set, call the EEPROM handler function, and buzz(3, 1); // write the tTarget value to the appropriate byte of the EEPROM } if (RX[0] =='0') { // test for (byte i =1; i <5; i++) { buzz(5, 2); } } for (byte i =0; i <2; i++) { // empty all message receiver and conversion variables RX[i] ='Z'; } }void relayHandlerL(byte lOperator) { // Lighting Handler Sequence // operators are:0=off, 1=on, 2=flip the state, 4=fill/refill the lighting state char var. if ((measError) &&((lOperator ==1) || (lOperator ==2))) { sTX(4); возвращение; } if ((lOperator ==2) || (lOperator ==0) &&(lState) || (lOperator ==1) &&(!lState)) { lState =!lState; digitalWrite(relayL, lState); buzz(2, 1); } if (lOperator>=0) { // fill up the working state char with the proper state indicator string if (lState) { lightingState =state_str[0]; } else { lightingState =state_str[1]; } if (!startup) { sTX(7); } }}void relayHandlerA(byte aOperator) { // Airing Handler Sequence if ((measError) &&((aOperator ==1) || (aOperator ==2))) { // operators are:0=off, 1=on, 2=flip the state, sTX(4); // 3=called by temprMeas() funct., 4=fill/refill the airing state char var. возвращение; } aState =digitalRead(relayA); if (!windowAlrt) { if ((aOperator ==2) || (aState) &&(aOperator ==0) || (!aState) &&(aOperator ==1)) { aState =!aState; digitalWrite(relayA, aState); aStateByCmd =digitalRead(relayA); buzz(2, 1); } } if (aOperator ==3) { // called by the temprMeas() function, 'windowAlrt' ended or started if ((!aState) &&(windowAlrt) || (aState) &&(!windowAlrt) &&(!aStateByCmd)) { digitalWrite(relayA, windowAlrt); } } aState =digitalRead(relayA); if (aOperator>=0) { if (aState) { if (windowAlrt) { airingState =state_str[2]; } else { airingState =state_str[0]; } } else { airingState =state_str[1]; } } if (!startup) { sTX(6); }} void relayHandlerH(byte hOperator) { // Heater Handler Sequence // operators are:0=off, 1=on, 2=flip the state, // 3=called by temprMeas() funct., 4=fill/refill the heater state char var. if ((measError) &&((hOperator ==1) || (hOperator ==2))) { sTX(4); возвращение; } if ((!hThermostat) &&(!windowAlrt) &&(!measError)) { // turn on/off the One Time Heating (15 mins) timed mode if ((hOperator ==2) || (hOperator ==1) &&(!hState) || (!hOperator) &&(hState)) { buzz(2, 1); hState =!hState; sftyTmrEnded =0; timer0 =0; digitalWrite(relayH, hState); } } if (windowAlrt) { sTX(3); } if (hOperator ==3) { // this function called by the temprMeas() function (op 3) // in order to examine windowAlrt &measError booleans if ((windowAlrt) &&(hState)) { // a window is open and the heater is running digitalWrite(relayH, 0); buzz(5, 3); } if ((!windowAlrt) &&(!measError)) { if ((hThermostat) || (!hThermostat) &&(hState) &&(sftyTmrEnded)) { digitalWrite(relayH, hThermostat); // proceed the command of the Thermostat Routine } } } hState =digitalRead(relayH); if (hOperator>=0) { if (hState) { if (hThermostat) { heaterState =state_str[2]; } else { heaterState =state_str[0]; } } else { heaterState =state_str[1]; } if ((((!windowAlrt) &&(hOperator !=3)) || (hState)) &&(!startup)) { sTX(5); } }}void safetyTmr () { // Timer for the One Time Heating (15 mins timed) mode if ((hState) &&(!sftyTmrEnded) &&(timer0> sftyTmrInterval) &&(!hThermostat)) { sftyTmrEnded =1; relayHandlerH(0); for (byte i =1; i <5; i++) { buzz(i, 2); } }}void temprTimer() { // Cyclic Timer for temprMeas() unsigned long temprTmrCurr =millis(); if (temprInterval <=temprTmrCurr - temprTmrPrev) { temprTmrPrev =temprTmrCurr; temprMeas(); } }void temprMeas() { // ----------- Temperature Measurement &Comparison Sequence temprPrev =tempr; // save the value for next comparison sensors.requestTemperatures(); // update sensor readings tempr =sensors.getTempFByIndex(0); // read remperature if ((tempr>=104) || (tempr <=32)) { // extreme meas values:if (!errMsgSentBySys) { // -127, -196.60 are HW errors, +85 is tipically SW error, but sTX(4); // can be fire, or a broken window } errMsgSentBySys =1; hThermostat =0; if (hState) { relayHandlerH(0); } if (aState) { relayHandlerA(0); } if (lState) { relayHandlerL(0); } measError =1; for (byte i =1; i <10; i++) { buzz(4, 1); задержка (50); } } else { temprPrev =tempr; measError =0; errMsgSentBySys =0; } if (!measError) { // ------------ Start of Temperature Analysis Sequence if (tempr <=62.6) { // Frequent, short-term switching of the heater gas boiler would cut short its lifetime, the heatCorrVal =0.9; // heatCorrVal value helps to keep avoid it. Declares the degree of overheating and cooling back. } // Lower temperature demands greater heatCorrVal, because the walls are colder and adsorb better the if ((tempr> 62.6) &&(tempr <66.2)) { // warmth from the freshly heated-up air, so the above described effect would more effective. heatCorrVal =0.72; } if (tempr>=66.2) { heatCorrVal =0.54; } if (tTarget - tempr>=heatCorrVal) { // subtract measured value from target, if the difference equals or greater than heatCorrVal sftyTmrEnded =1; // deactivate the One Time Heating (15 mins) timed program if it is running hThermostat =1; // turn on the thermostat buzz(1, 1); } if ((tTarget - tempr <=-1 * heatCorrVal) &&(hThermostat)) { hThermostat =0; } if ((temprPrev - tempr>=0.36) &&(!windowAlrt) &&(tempr <=68)) { // in a measurement cycle and in heating season the temperature windowAlrt =1; // drops, it will evaluate as a window is open sftyTmrEnded =1; for (byte i =1; i <5; i++) { buzz(4, 1); задержка (50); } relayHandlerA(3); // call airing function (opcode =3), to help refresh the air } if ((temprPrev - tempr <=-0.216) &&(windowAlrt)) { // the tempr. falling is over, the air became warmer windowAlrt =0; // due to the heat capacity of the environment, buzz(4, 3); // so switch back to normal mode relayHandlerA(3); } relayHandlerH(3); // the function will examine caller param(3) &windowAlrt &measError booleans if (!windowAlrt) { sTX(1); } }}void tTargetHandler (bool set) { // set the needed tempr by increasing or decreasing if (!set) { // incr if (tTarget <76) { // until it reaches the upper limit tTarget++; buzz(3, 1); } else { buzz(2, 3); } } else { // decr if (tTarget> 50) { tTarget--; buzz(3, 1); } else { buzz(2, 3); } } tTargetEEPROM();}void tTargetEEPROM() { EEPROM.write(addr, tTarget); // after incr/decr/set, write the tTarget value to the appropriate byte of the EEPROM delay(10); sTX(2);}void draw(void) { // logo handler if (frame ==0) { u8g.drawXBMP( 0, 0, 128, 64, frame1); } else if (frame ==1) screenFunctState(); } void screenFunctState(void) { // function state screen temprWriteOut(0, 64); u8g.drawHLine(0, 46, 128); u8g.setFont(u8g_font_unifont); if (!windowAlrt) { u8g.setPrintPos( 0, 14); u8g.print(funct_str[0]); u8g.setPrintPos(84, 14); u8g.print(heaterState); } else { u8g.setPrintPos( 0, 14); u8g.print(funct_str[3]); } u8g.setPrintPos( 0, 28); u8g.print(funct_str[1]); u8g.setPrintPos(88, 28); u8g.print(airingState); u8g.setPrintPos( 0, 42); u8g.print(funct_str[2]); u8g.setPrintPos(95, 42); u8g.print(lightingState); if ((!hState) &&(!aState) &&(!lState)) { screenStndby(); // if all of controlled devices are in off, call standby screen }}void screenStndby() { // standby scr u8g.firstPage(); do { u8g.setFontRefHeightText(); u8g.setFont(u8g_font_unifont); if (!measError) { u8g.setPrintPos(33, 52); u8g.print(funct_str[5]); u8g.setPrintPos( 8, 64); u8g.print(funct_str[6]); } else { u8g.setPrintPos( 4, 48); u8g.print(funct_str[4]); } temprWriteOut(0, 16); } while( u8g.nextPage() );}void temprWriteOut (byte tX, byte tY) { // draw tempr &tTarget variables onto different coordinates u8g.setFont(u8g_font_courB14);//u8g.setFont(u8g_font_6x12); // you can save ~10% of prog.memory using this font with 2x2 scale char buftTarget[9]; sprintf (buftTarget, "%d", tTarget); // int to char//u8g.setScale2x2();//tY =tY / 2; u8g.setPrintPos(tX, tY); u8g.print(buftTarget); u8g.setPrintPos(tX+18, tY); u8g.print(funct_str[9]); u8g.setPrintPos(tX+50, tY); u8g.print(tempr); //u8g.print(char(176)); u8g.print("F");//u8g.undoScale();}void clrScr(){ u8g.firstPage(); do { } while( u8g.nextPage() );}void ledHandler() { // the brightness of a led is low, if the indicated device is off, and high, if its on if (aState) { analogWrite(ledA, bright[2]); } else { analogWrite(ledA, bright[1]); } if (lState) { analogWrite(ledL, bright[2]); } else { analogWrite(ledL, bright[1]); } if (hState) { if (!hThermostat) { ledBlnk(); // the heater led blinks when the One Time Heating (15 mins) timed mode is activated, } else { brightHeat =bright[2]; // and constant bright, if the thermostat routine is active } } else { brightHeat =bright[1]; } analogWrite(ledH, brightHeat);}void ledBlnk() { unsigned long curr =millis(); if (ledInterval <=curr - prev) { // subtract prev value from current, if the difference equals or greater than ledInterval const. prev =curr; // overwrite the earlier value with the current and flip brightness level if (brightHeat ==bright[1]) { brightHeat =bright[2]; } else { brightHeat =bright[1]; } } analogWrite(ledH, brightHeat);}void buzz(byte b, byte d) { // call with frequency and delay parameters tone(buzzer, b * 1000); delay(d * 100); noTone(buzzer);}void sTX(byte reportTX) { // sending serial reports switch (reportTX) { case 0:for (byte i =0; i <9; i++) { sUART.print(funct_str[10]); } sUART.println(funct_str[10]); ломать; case 1:sUART.print(funct_str[8]); // Tempr. sUART.print(tempr); //sUART.print(char(176)); sUART.println("F"); ломать; case 2:sUART.print(funct_str[7]); // TTemp sUART.print(tTarget); //sUART.print(char(176)); sUART.println("F"); ломать; case 3:sUART.print(funct_str[3]); // Window Alert sUART.print(funct_str[9]); sUART.print(tempr); //sUART.print(char(176)); sUART.println("F"); ломать; case 4:sUART.println(funct_str[4]); // Error report break; case 5:sUART.print(funct_str[0]); // Working state of devices sUART.println(heaterState); ломать; case 6:sUART.print(funct_str[1]); sUART.println(airingState); ломать; case 7:sUART.print(funct_str[2]); sUART.println(lightingState); ломать; case 8:// Overview report sTX(0); relayHandlerH(4); relayHandlerA(4); relayHandlerL(4); sTX(2); if (measError) { sTX(4); } ломать; }}
Схема
For jumper wire test... You have to solder itПроизводственный процесс
- Контроль доступа с помощью QR, RFID и проверки температуры
- Универсальный пульт дистанционного управления с использованием Arduino, 1Sheeld и Android
- Управление монетоприемником с помощью Arduino
- Автоматическая система полива растений с Arduino
- Arduino с Bluetooth для управления светодиодом!
- Умная обувь (автоматическая шнуровка и выработка электроэнергии)
- Arduino Nano:управление двумя шаговыми двигателями с помощью джойстика
- Управление серводвигателем с помощью Arduino и MPU6050
- Устройства с голосовым управлением Bluetooth с OK Google
- Управление автомобилем с помощью Arduino Uno и Bluetooth