Мониторинг железа ПК с помощью Arduino. Получение данных отправленных из «Монитора порта» в Arduino

Доброе время суток, читатели и просто сюда зашедшие. Я являюсь подписчиком канала на Ютубе AlexGyver и увидев видео о «Мониторинг железа ПК»,

решил повторить эту самоделку, т.к. она мне показалась довольно интересной, да и всегда хотелось отображение состояние системы хардварным способом, на дополнительном экране, а не на мониторе компьютера. Делать из компа новогоднюю елку я не захотел, по этому решил не ставить RGB-подсветку, а так же решил отказаться от самодельного реобаса, т.к. моя мать Gigabyte прекрасно умеет управлять оборотами вентиляторов и без всяких посредников средствами BOIS.

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

  1. ATmega 328 https://goo.gl/DkWhmU
  2. Соединительные провода https://goo.gl/NHmQqs
  3. Экран на 4 строки 20 символов https://goo.gl/4MAowg

Это все заказывал у одного продавца что бы пришло вместе, одной посылкой. И небольшой лайф хак: если накидывать все в корзину, от одного продавца, у которого есть плата за доставку, а потом единожды оплачивать, то плата за пересылку возьмется 1 раз. (А не за каждый из 3-х товаров).

4. Мини ЮСБ провод я не заказывал и припаял на прямую к Ардуинке и подсоединил проводами (из пункта 2) к внутреннему ЮСБ разъему. Но вам можно не мучаться и заказать https://goo.gl/LA7sb3 так проще

И начал ждать. Пришло все довольно быстро, через 15 дней. В схеме есть ещё кнопка, при замыкании которой переключаются экраны с информацией о состоянии системы. Сначала я взял такую:

но идея оказалась не очень, т.к. её нечем было закрепить на лицевой панели компьютера. По этому в местном магазине радиоэлектронике было выбрана кнопка без фиксации, с удобным креплением в корпус, а так же тумблер, для выключения сего «чуда» на ночь. Т.к. все что подключено к ЮСБ-порту, моего компьютера, постоянно запитано и имеет свойство светиться и мигать, выключаясь только отключением компа от розетки.

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

Ну получилось довольно не плохо, почти как я хотел. Осталось устранить небольшие проблемки в софте, передающий температуры. Они почему-то передаются максимальные из: датчик мат. платы CPU, GPU, Motherboard что мешает мониторить комп в спокойном состоянии, когда температуры простоя не высоки.

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

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

Изменения в программе OpenHardwareMonitor:

  • как температура CPU теперь передается не температура самого горячего ядра, а температура датчика CPU с матери;
  • как температура GPU теперь передается не максимальная температура между Motherboard и GPU , а температура GPU с датчика видеокарты;
  • как температура MotherBoard теперь передается не максимальная температура между: материнская плата, GPU и датчик температуры CPU с матери, а температура MotherBoard с датчика;
  • так же в 12 и 13 значениях из OpenHardwareMonitor теперь передаются не флаги ручного управления вентиляторов и подсветки, а скорость вращения вентилятора CPU и MotherBoard соответственно.

Изменения в скетче для Ардуино:

  • убрано отслеживание нажатия второй кнопки которая меняла экраны в обратном порядке;
  • на втором экране заменен вывод информации, теперь вместо температуры 2-х внешних датчиков температуры (TMP1, TMP2) вывожу скорость вращения вентилятора CPU (FanC) и MotherBoard (FanM).
  • убрано отслеживание включения ручного управления вентиляторами и подсветкой.

Архив со всеми изменениями и исходниками можно скачать тут (Как удалось выяснить, эмпирическим путем, изменения в OpenHardwareMonitor прекрасно работают на матерях Gigabyte, как у меня, и, скорее всего, будут ошибки на матерях других производителей).

Всем зимы и котиков!

Удачных экспериментов!

Это совместный проект. Ссылки на каналы, сайт и архив авторов будут в конце описания. Создаётся блочная система управления ВетроСолнечной электростанции. Имеем два дачных участка с альтернативным энергообеспечением. На одном участке есть внешнее электричество, на втором полное отсутствие такового. Участки находятся в разных регионах России. На первом участке установлен самодельный ветрогенератор мощностью 1кВт, 6 стационарных солнечных панелей, по 100Вт каждая, соединённых последовательно по две штуки на 24В и 6 самодельных панелей, соединённых также на 24 вольта, установленных на солнечном треккере. На втором участке, установленные стационарно, 4 панели по 100Вт и 2 самодельных по 60 Вт подключенных также на 24 вольтовую систему. Проект позволят подключать как 12 вольтовую так и 24 вольтовую системы без механических изменений. Система состоит из пяти самостоятельных блоков. Связь межу блоками осуществляется по радиоканалу через модули NRF24L01 (с внешней антенной).

  1. Модуль «Блок управлени» на базе ARDUINO MEGA2560 — осуществляет сбор всей информации и вывод на ЖК дисплей IIC/I2C 2004 4Х20, управление блоками, устройствами и ввод различных настроечных параметров с помощью матричной клавиатулы 4Х4. Температур, влажности, давления (датчик давления bmp180 ), дата, время (часы DS3231 ). Вся настроечная информация вводися через меню и сохраняется в EEPROM. После установки всех необходимы поправочных коэффициентов в режиме отладки эти данные по радиоканалу отправляются в свои блоки, что позволяет точно настроить все данные. (Блок продолжает развиваться).
  2. Модуль «Блок ваттметра» на базе ARDUINO NANO совместно с силовым блоком- производит замер и расчет входящих и исходящих токов, напряжений используя измерительную планку с установленными на неё датчиками тока ACS712 30А и ACS754SCU 100А, АЦП ADS1015 12 бит , резистивных делителей напряжения . Кроме того регулирует установленное в параметрах выдаваемое ветрогенератором напряжение с помощью балластной нагрузки, греет воду с защитой от закипания на базе герметичного датчика DS18B20 . Отключает инвертор при разряде аккумуляторов ниже % установленного в параметрах. Включает систему охлаждения трёхфазного диодного моста.(Датчик DS18B20 ).
  3. Модуль «Блок ветрогенератора» на базе ARDUINO NANO — Состоит из двух блоков:
  • Непосредственно «Блока ветрогенератора»- производит замер и передачу: оборотов генератора (датчик Холла), температуры обмоток генератора, температуры и влажности отсека генератора(DS18B20 и DHT22 ), определение дня и ночи (фоторезисторы ). Положение хвоста ветрогенератора. А так же, в целях безопасности, трёхлучевой светодиодный маяк (мачта ветрогенератора высотой 17м).
  • «Блок анемометра»- Замер скорости ветра (датчик Холла) указатель направления ветра (датчики Холла, расширитель цифровых портов IIC I2C MCP23017 ).

4. Модуль «WEB сервер» на базе ARDUINO MEGA 2560 и интернет шилда W5100 Ethernet — выводит на сайт всю информацию об электростанции для возможности контролировать показания удалённо.

5. Модуль «Солнечный треккер»- управление положением солнечных панелей на солнце и по времени в случае отсутствия такового, управление с помощью ИК пульта, автоматическое возвращение треккера в положение на Восток после наступления ночи. Установка треккера в положение «ветрозащита» в случае превышения скорости ветра выше установленной. Управление приводами треккера. Блок реально работает уже год. Пока нет в архиве, т.к. идет его внедрение в общую блочную схему.

Начинался проект с использованием монитора NEXTION (прекрасная вещь обязательно где нибудь его используем), но потом мы отказались от этого, в виду больших тормозов из-за обьёма передаваемой информации и решения сделать систему модульной.

Так же все ARDUINO NANO прошиваются через WiFi с использованием ESP8266-01 . Это чтобы обновлять прошивку, в случае коррекции скетча, не снимая блоки с мест монтажа. Есть пока проблема с MEGA2560, в чём причина знаем, но пока не можем решить. Но это отдельная история.

Скетчи в формате FLProg, печатные платы в формате Sprint-Layout в регулярно обновляемом

В которой описывалось создание устройства для мониторинга параметров ПК. Сразу захотелось что-то подобное. Но так как опыта программирования PIC контроллеров у меня маловато, зато имеется Arduino, решил собирать на нем.

Основа устройства – Freeduino, в качестве индикатора применен LCD (16х2) дисплей с контроллером H44780 на борту, для подачи звукового сигнала использован пьезоэлектрический капсуль, снятый с китайского мультиметра. Связь полученного устройства и ПК осуществляется посредством USB.

Фото «готового» устройства:

Вот полный список деталей для сборки:
- Arduino Uno, Freeduino и т. п.
- LCD дисплей с контроллером H44780
- Пьезоэлектрический излучатель (подойдет любой, даже тот, что используется в китайских игрушках)
- Резистор 10-30 Ом
- Подстроечный резистор 10кОм

Соединяем детали по такой схеме:

Загружаем в Arduino скетч под названием “Lcd_Ram.ino” (лежит в прикрепленном к статье архиве), подключаем к ПК через кабель USB.

На дисплее устройства должна появиться такая картинка:

Если картинка не появилась, то существует четыре причины:
1) Нет питания (поврежден USB шнур);
2) Поврежден шлейф LCD (дисплей не прошел инициализацию);
3)Неисправен Arduino;
4) Недостаточная контрастность дисплея (эта причина устраняется путем изменения сопротивления подстроечного резистора);

Данное устройство способно выводить на LCD информацию о загрузке оперативной памяти и процессора (больше не позволил размер самого LCD).

Если оперативная память загружена более чем на 70%, то устройство будет подавать звуковой сигнал, а на LCD будет выводиться такой значок:

Подача звукового сигнала может выключаться из программы на Windows. Если звук включен, то на LCD выводится иконка:

Главное окно данной программы:

Для соединения с Arduino откройте в программе вкладку «COM порт» --> “Настройка COM”, и выберите виртуальный COM порт, "принадлежащий" Arduino (если вы первый раз подключаете Arduino к ПК, то будет необходимо установить драйвера FTDI) . После соединения на дисплее должна быть похожая картина.

Продолжаем развивать нашу метеостанцию.

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

Мне написал один из наших коллег с вопросом, по какой причине введен сторожевой таймер?

Сторожевой таймер стоит на случай ч.п. Как показывает практика, ENC28J60 не тянет более (если не подводит память) 4 одновременных соединений. Учитывая сколько служебных соединений, постоянно происходит для поддержания работы самой сети, и просто левый трафик, создаваемый всяческими домашними игрушками (например, современные телевизоры, сканируют доступные хосты в сети и открытые у них порты) конструкция попросту уходит в ступор. ENC28J60 не умеет самостоятельно работать с сетевыми протоколами и все реализовано в библиотеках. Возможно дело именно в них.
Проверял все доступные библиотеки и разные модули (вдруг брак), но добиться стабильной работы в течении длительного времени у меня не получилось. Максимальный срок был порядка 3-4 недель.
Именно для этого там крутится "пес" и в случае чего дергает контроллер. После этого проблема ушла.
Также не отрицаю, что возможно в моей домашней сети есть определенные нюансы или проблемы. Но раз проблема была у меня, она может выплыть и у другого человека. Я пока нашел только такое решение.
Насколько мне известно, на чипах от Wiznet (W5100 и выше) этого нет, ну или просто плохо искали.

Переходим к обновлению

Самое главное, мы уходим от чипа ENC28J60 и переходим на W5100 . Я пытался реализовать все на старом чипе, но не хватает памяти микроконтроллера из-за очень больших библиотек для ENC28J60 . При использовании нового чипа, стандартной библиотеки от разработчика и всех внесенных изменений, остается еще более 20% свободной памяти микроконтроллера ATMega328 . А это, новые плюшки!

В этой версии (назовем её второй) добавлена возможность передачи показаний с датчиков по беспроводной связи используя частоту 433 мГц . Сами модули я брал у Китайцев, маркировка XY-MK-5V . Хочу отметить, что качество передачи далеко от совершенства. Возможны потери сигнала, шумы, не возможность одновременной передачи и т.д и т.п. Но их цена (менее $1 за комплект) компенсируют эти недостатки. Скажу Вам по секрету, что именно эти (самые дешевые) модули стоят во многих фирменных метеостанциях для домашнего использования. Ого, неожиданно?

Начнем с базовой станции

Мы переходим на Arduino UNO и Ethernet Shield (первой версии) на базе чипа W5100 . Это бутерброд и описывать его нету смысла. Я опишу только дополнительно задействованные контакты для модулей XY-MK-5V .

Модуль передатчика использует питание 5V , GND (куда без матушки то) и D2 пин на контроллере. Изменить контакт D2 (DATA) можно, используя функцию vw_set_tx_pin из библиотеки vw.

В отличии от предыдущего скетча, в этом задействованы две дополнительные библиотеки:

#include #include

Сам скетч

Скрытый текст

#include #include #include #include #include #include #include #include #define DHTTYPE DHT22 #define DHTPIN 5 DHT dht(DHTPIN, DHTTYPE); byte mac = {0x54, 0x34, 0x31, 0x31, 0x31, 0x31}; char server = "narodmon.ru"; int port = 8283; IPAddress ip(192,168,0,201); EthernetClient client; BMP085 dps = BMP085(); long Temperature = 0, Pressure = 0; float H, dP, dPt; bool interval = true; EasyTransferVirtualWire ET; struct SEND_DATA_STRUCTURE{ byte ID; // Идентификатор устройства int Temperature; // Температура float Pressure; // Давление float Humidity; // Влажность float dewPoint; // Точка росы/инея }; SEND_DATA_STRUCTURE broadcast; void setup() { // Инициализация сторожевого таймера (Watchdog timer) wdt_disable(); delay(8000); wdt_enable(WDTO_8S); // Инициализация консоли Serial.begin(9600); // Инициализация датчика DHT dht.begin(); // Инициализация модуля 433 мГц ET.begin(details(broadcast)); vw_set_ptt_inverted(true); vw_set_tx_pin(2); vw_setup(2000); // Стартуем сеть, если не дождались данных с DHCP сервера то // присваеваем себе адрес самостоятельно if (Ethernet.begin(mac) == 0) Ethernet.begin(mac, ip); // Инициализация 1-Wire Wire.begin(); delay(200); // Инициализация BMP180 с корректировкой высоты // dps.init(MODE_STANDARD, 3200, true); // Инициализация BMP180 dps.init(); Serial.println(Ethernet.localIP()); // Отправляем первые данные сразу после включения устройства send_info(true); } // dewPoint function NOAA // reference (1) : http://wahiduddin.net/calc/density_algorithms.htm // reference (2) : http://www.colorado.edu/geography/weather_station/Geog_site/about.htm double dewPoint(double celsius, double humidity) { // (1) Saturation Vapor Pressure = ESGG(T) double RATIO = 373.15 / (273.15 + celsius); double RHS = -7.90298 * (RATIO - 1); RHS += 5.02808 * log10(RATIO); RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1/RATIO))) - 1) ; RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1) ; RHS += log10(1013.246); // factor -3 is to adjust units - Vapor Pressure SVP * humidity double VP = pow(10, RHS - 3) * humidity; // (2) DEWPOINT = F(Vapor Pressure) double T = log(VP/0.61078); // temp var return (241.88 * T) / (17.558 - T); } void send_info(bool eth) { bool fail = true; while(fail) { // Пытаемся считать данные с датчика влажности DHT до тех пор, пока не получим // результат. В 90% случаев все работает нормально, но нам нужны 100% if((H = dht.readHumidity()) >= 0) { // Получение влажности и температуры с датчика BMP180 dps.getPressure(&Pressure); dps.getTemperature(&Temperature); // Подсчитываем точку росы, если температура на улице выше 0 градусов Цельсия // и ожидаем результат выше 0, в противном случае выводим 0. Это необходимо // чтобы не вводить в заблуждения в зимее время года. // dP = Temperature>0?((dPt=dewPoint(Temperature*0.1, H))<0?0:dPt):0; dP = dewPoint(Temperature*0.1, H); // Отправляем данные в эфир 433 мГц broadcast.ID = 1; broadcast.Temperature = floor(Temperature*0.1); broadcast.Pressure = floor(Pressure/133.3*10)/10; broadcast.Humidity = floor(H*10)/10; broadcast.dewPoint = floor(dP*10)/10; ET.sendData(); delay(250); if(eth) { // Подключаемся к серверу "Народный мониторинг" if(client.connect(server, port)) { // Начинаем передачу данных // адрес_устройства_в_проекте, имя_устройства, GPS широта, GPS долгота client.print(F("#fe-31-31-0e-5a-3b#Arduino Uno#71.344699#27.200014\n")); // Температура client.print(F("#T0#")); client.print(Temperature*0.1); client.print(F("#Температура\n")); // Давление client.print("#P1#"); client.print(Pressure/133.3); client.print(F("#Давление\n")); // Влажность client.print("#H1#"); client.print(H); client.print(F("#Влажность\n")); // Точка росы\инея client.print("#T1#"); client.print(dP); client.print((dP <= 0)? F("#Точка инея\n"):F("#Точка росы\n")); //client.print(F("#Точка росы\n")); // Отправляем конец телеграммы client.print("##"); // Даем время отработать Ethernet модулю и разрываем соединение delay(250); client.stop(); } } // Останавливаем цикл, если передача завершена fail = !fail; break; } delay(250); } } void loop() { // Каждые 4 секунды сбрасываем сторожевой таймер микроконтроллера // Каждые 6 минут отправляем данные на "Народный мониторинг" // Каждые 30 секунд отсылаем данные в эфир 433 if(!(millis()%1000)) wdt_reset(); if(!(millis()%360000)) send_info(true); if(!(millis()%30000)) send_info(false); }

К самим модулям необходимо добавить антенну. Для 433 мГц достаточно обычного медного провода длинной 17 см . Без антенны можете забыть о нормальной работе.

Переходим к самой важной части этого обновления - локальная беспроводная станция

Для её реализации (на коленке) я использовал аналог Arduino NANO (на базе ATMega328 ) и TFT дисплей на чипе ST7735S с разрешением 128 x 160

Скрытый текст



Распиновка дисплей -> контроллер

============================= LED | 3.3V SCK | SCK (13) SDA | MOSI (11) A0 | DC (9) RESET | RST (8) CS | CS (10) GND | GND VCC | 5V ============================

Модуль приемник подключается также как передатчик, только DATA к пину D7 .

Пару снимков, как это выглядит:

Скрытый текст

Скетч приемника

Скрытый текст

#include #include #include #include int x, y; int w = 128, h = 160; int size; // 433 EasyTransferVirtualWire ET; struct SEND_DATA_STRUCTURE{ byte ID; // Идентификатор устройства int Temperature; // Температура float Pressure; // Давление float Humidity; // Влажность float dewPoint; // Точка росы/инея }; SEND_DATA_STRUCTURE broadcast; int Log_Temperature = -1; float Log_Pressure = -1; float Log_Humidity = -1; float Log_dewPoint = -1; // TFT #define cs 10 #define dc 9 #define rst 8 char Temperature, Pressure, Humidity, dewPoint; String info; TFT TFTscreen = TFT(cs, dc, rst); void setup(){ Serial.begin(9600); // Инициализация модуля 433 мГц ET.begin(details(broadcast)); vw_set_ptt_inverted(true); vw_set_rx_pin(7); vw_setup(2000); vw_rx_start(); // Инициализация и начальная настройка дисплея TFTscreen.begin(); TFTscreen.setRotation(2); TFTscreen.background(0, 0, 0); // Рисуем статические элементы // 1. Заходите к нам в гости TFTscreen.stroke(255, 255, 255); TFTscreen.setTextSize(1); TFTscreen.text(" ", 10, 10); // 2. Описание показаний с датчиков TFTscreen.text("mmHg", w/2+5, 80); TFTscreen.text("%", w/2+5, 100); TFTscreen.text("C", w/2+5, 120); broadcast.Temperature = 0; broadcast.Pressure = 0; broadcast.Humidity = 0; broadcast.dewPoint = 0; TFTPrint(); } void loop(){ if(ET.receiveData()){ if(broadcast.ID == 1) TFTPrint(); /* Serial.println(broadcast.Temperature); Serial.println(broadcast.Pressure); Serial.println(broadcast.Humidity); Serial.println(broadcast.dewPoint); Serial.println(); */ } } void changes(int size, int x, int y, bool up, bool clear = false) { if(clear) TFTscreen.stroke(0, 0, 0); else { changes(size, x, y, !up, true); TFTscreen.stroke((up)?0:255, 0, (up)?255:0); } if((size%2) == 0) size++; while(size > 0) { TFTscreen.line(x, y, x+(size--), y); ++x, (up)?--y:++y, --size; } /* while(size > 0) { TFTscreen.line(x, y, (up)?x+size-1:x, (up)?y:y+size-1); ++x, ++y, --size; } */ } int x_center(int w, int length, int size) { return floor((w-length*(size*5)+size*2)/2); } int x_alignment_right(int w, int length, int size) { return ceil(w-length*(size*5)+size*2); } void TFTPrint() { size = 3; // ================================================================================== // Вывод показаний температуры // ================================================================================== if(broadcast.Temperature != Log_Temperature) { TFTscreen.setTextSize(size); // Затираем устаревшие данные String info = String(Log_Temperature); info.concat(" C"); if(Log_Temperature > 0) info = "+"+info; info.toCharArray(Temperature, info.length()+1); TFTscreen.stroke(0, 0, 0); TFTscreen.text(Temperature, x_center(w, info.length()+1, size), 35); // Выводим новые показания info = String(broadcast.Temperature); info.concat(" C"); if(broadcast.Temperature > 0) info = "+"+info; info.toCharArray(Temperature, info.length()+1); // Меняем цвет значения температуры в зависимости от самой температуры int r, g = 0, b; if(broadcast.Temperature > 0) { r = map(broadcast.Temperature, 0, 40, 255, 150); // Красный b = map(broadcast.Temperature, 0, 40, 30, 0); // Изменяем оттенок для более наглядного перехода через ноль } else { r = map(broadcast.Temperature, -40, 0, 0, 30); // Изменяем оттенок для более наглядного перехода через ноль b = map(broadcast.Temperature, -40, 0, 150, 255); // Синий } TFTscreen.stroke(b, g, r); // ВНИМАНИЕ: в библиотеке перепутаны позиции цветов, место RGB используется BGR! TFTscreen.text(Temperature, x_center(w, info.length()+1, size), 35); } size = 1; // ================================================================================== // Вывод показаний давления // ================================================================================== if(broadcast.Pressure != Log_Pressure) { TFTscreen.setTextSize(size); // Затираем устаревшие данные info = String(Log_Pressure); info.toCharArray(Pressure, info.length()); TFTscreen.stroke(0, 0, 0); TFTscreen.text(Pressure, x_alignment_right(w/2-5, info.length(), size), 80); // Выводим новые показания info = String(broadcast.Pressure); info.toCharArray(Pressure, info.length()); TFTscreen.stroke(255, 255, 255); TFTscreen.text(Pressure, x_alignment_right(w/2-5, info.length(), size), 80); changes(10, 106, 85, (broadcast.Pressure > Log_Pressure)?true:false); } else { changes(10, 106, 85, true, true); changes(10, 106, 85, false, true); } // ================================================================================== // Вывод показаний влажности // ================================================================================== if(broadcast.Humidity != Log_Humidity) { TFTscreen.setTextSize(size); // Затираем устаревшие данные info = String(Log_Humidity); info.toCharArray(Humidity, info.length()); TFTscreen.stroke(0, 0, 0); TFTscreen.text(Humidity, x_alignment_right(w/2-5, info.length(), size), 100); // Выводим новые показания info = String(broadcast.Humidity); info.toCharArray(Humidity, info.length()); TFTscreen.stroke(255, 255, 255); TFTscreen.text(Humidity, x_alignment_right(w/2-5, info.length(), size), 100); changes(10, 106, 105, (broadcast.Humidity > Log_Humidity)?true:false); } else { changes(10, 106, 105, true, true); changes(10, 106, 105, false, true); } // ================================================================================== // Вывод показаний точки росы\инея // ================================================================================== if(broadcast.dewPoint != Log_dewPoint) { TFTscreen.setTextSize(size); // Затираем устаревшие данные info = String(Log_dewPoint); info.toCharArray(dewPoint, info.length()); TFTscreen.stroke(0, 0, 0); TFTscreen.text(dewPoint, x_alignment_right(w/2-5, info.length(), size), 120); // Выводим новые показания info = String(broadcast.dewPoint); info.toCharArray(dewPoint, info.length()); TFTscreen.stroke(255, 255, 255); TFTscreen.text(dewPoint, x_alignment_right(w/2-5, info.length(), size), 120); changes(10, 106, 125, (broadcast.dewPoint > Log_dewPoint)?true:false); } else { changes(10, 106, 125, true, true); changes(10, 106, 125, false, true); } // Обновляем значения в логах для последующего сравнения показаний Log_Temperature = broadcast.Temperature; Log_Pressure = broadcast.Pressure; Log_Humidity = broadcast.Humidity; Log_dewPoint = broadcast.dewPoint; }

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

Как мне показалось, дизайн это та часть проекта, которая отнимает большую часть времени!

Скрытый текст

Часть данных сфабрикованы для отображения некоторых элементов дизайна.

Артефакты на дисплее, это пыль и прочая грязь скопившаяся за долго время нахождения дисплея в... где то там, ... ну там, не помню откуда его достал! Отстаньте!

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

  1. x_center
  2. x_alignment_right

Первая производит центровку текста, а вторая выравнивание по правой части указанной зоны. Все вычисления производятся относительно размеров заданного текста, исходя из выражения 1 size = 1PX х 1PX сегмента шрифта.

На дисплее также отображаются элементы соответствующие повышению или понижению той или оной величины показаний. Отображаются они в виде треугольников. Но в коде функции changes есть альтернативное отображение в виде треугольников повернутых на 45 градусов. Если показания повышаются то элемент красный, в противном случае, синий.

Кстати, цвет и оттенок основной температуры изменяется в зависимости от самой температуры. Довольно спорное решение, но на мой взгляд, визуально комфортное. Я некоторое время бился над ней, и понял, что значения в функции stroke , объекта TFT дисплея, указаны в неверном порядке. BGR место RGB . Это ошибка разработчика, ну или я что-то не понимаю.

PS : Все довольно интересно, но на мой взгляд заслуживает дальнейшего развития. Чем и займемся через какое то время.

Когда узнал о народном мониторинге, о возможности быть частью этой системы мониторинга погоды, меня охватил азарт, и была сделана простенькая метеостанция на ардуино нано и ethernet модуле.
Передавала она на сайт температуру, давление и влажность. Работала худо бедно, иногда подвисала, необходимо было перезагружать. Потом сдох датчик влажности, и я занялся поиском альтернативного устройства. Долго поглядывал на esp8266, но знал о ней очень немного. Останавливало то, что код для нее надо было писать в незнакомой мне среде esplorer на незнакомом мне языке. Здесь уже публиковался подобного устройства, устройство работало с условно бесплатной прошивкой от Homes Smart, такое решение меня не устроило. Позднее я узнал, что esp8266 можно вполне успешно подружить с arduinoIDE. Я начал усиленно гуглить, и в результате догуглился до устраивающих меня результатов.
Надеюсь, статья окажется полезной. Думаю, ее можно расценивать как обзор-руководство по сборке.

NodeMcu это своего рода отладочная плата для esp8266 (в моем понимании). С помощью нее удобно делать прототипы устройств на макетных платах. Удобно заливать прошивку из ArduinoIDE, все происходит автоматически. Естественно, необходимо ArduinoIDE к работе с esp8266. Подготовив рабочую среду сразу набросал схему, это было не сложно.
Датчик давления и температуры bmp180 подключен по i2c к SCL(gpio05) и SDA(gpio04).
Датчик влажности и температуры dht22 подключен к gpio02
Дисплей 1602 с припаянным i2c адаптером так же посажен на scl и cda, параллельно с датчиком давления.
Питание датчиков 3.3в, питание дисплея 5в.

Фоторезистор подключен к пину А0, он управляет яркостью дисплея, чтобы в ночи дисплей не светился слишком ярко. Питанием подсветки заведует gpio14, на котором реализован программный ШИМ. После транзисторного каскада питание подсветки подходит непосредственно к пятачку А (анод) на дисплее. он находится рядом со светодиодом. Со spi адаптера дисплея необходимо снять перемычку, которая отвечает за подсветку.

Фото прототипа





Схему и печатку приложу в конце.

Сложнее было с кодом.

//ардуино 181, либы схоронил #include #include #include #include #include LiquidCrystal_I2C lcd(0x27, 16, 2); #include #include #include #include #define debug true // вывод отладочных сообщений #define postingInterval 300000 // интервал между отправками данных в миллисекундах (5 минут) #define DHTPIN 2 // dht на gpio02 // Uncomment the type of sensor in use: //#define DHTTYPE DHT11 // DHT 11 #define DHTTYPE DHT22 // DHT 22 (AM2302) //#define DHTTYPE DHT21 // DHT 21 (AM2301) // Lib instantiate DHT dht(DHTPIN, DHTTYPE); Adafruit_BMP085 bmp; /**/unsigned long lastConnectionTime = 0; // время последней передачи данных /**/String Hostname; //имя железки - выглядит как ESPAABBCCDDEEFF т.е. ESP+mac адрес. float dhttemp; // буферная переменная для хранения температуры от dht22 int dhthum; // буферная переменная для хранения влажности от dht22 int topwm; // хранит значение для шима яркости дисплея void wifimanstart() { // Волшебная процедура начального подключения к Wifi. // Если не знает к чему подцепить - создает точку доступа ESP8266 и настроечную таблицу http://192.168.4.1 // Подробнее: https://github.com/tzapu/WiFiManager WiFiManager wifiManager; wifiManager.setDebugOutput(debug); wifiManager.setMinimumSignalQuality(); if (!wifiManager.autoConnect("ESP8266")) { if (debug) Serial.println("failed to connect and hit timeout"); delay(3000); //reset and try again, or maybe put it to deep sleep ESP.reset(); delay(5000); } if (debug) Serial.println("connected..."); } void setup() { // pinMode(14, OUTPUT); // gpio14 будет шимить подсветку дисплея Hostname = "ESP"+WiFi.macAddress(); Hostname.replace(":",""); Serial.begin(115200); // инициализация экрана lcd.begin(4, 5); // sda=gpio04, scl=gpio05 lcd.backlight(); // инициализация датчика температуры и давления bmp180 dht.begin(); if (!bmp.begin()) // если датчик не обнаружен, сообщаем об этом в компорт и на дисплей { Serial.println("Could not find BMP180 or BMP085 sensor at 0x77"); lcd.clear(); lcd.print("BMP180 FAILED"); while (1) {} } WiFi.hostname(Hostname); wifimanstart(); Serial.println(WiFi.localIP()); Serial.println(WiFi.macAddress()); Serial.print("Narodmon ID: "); Serial.println(Hostname); // выдаем в компорт мак и айпишник железки, так же выводим на дисплей lcd.clear(); lcd.setCursor(0, 0); lcd.print(WiFi.localIP()); lcd.setCursor(0, 1); lcd.print(Hostname); lastConnectionTime = millis() - postingInterval + 15000; //первая передача на народный мониторинг через 15 сек. } void WriteLcdTemp (void){ // заполнение дисплея. происходит каждые 5 минут после получения данных с датчиков lcd.clear(); lcd.setCursor(1, 0); lcd.print("T1 "); lcd.setCursor(4, 0); lcd.print(bmp.readTemperature()); lcd.setCursor(8,0); lcd.print(" P "); lcd.setCursor(11,0); lcd.print(bmp.readPressure()/133.3); lcd.setCursor(1, 1); lcd.print("T2 "); lcd.setCursor(4, 1); lcd.print(dhttemp); lcd.setCursor(8,1); lcd.print(" H "); lcd.setCursor(11,1); lcd.print(dhthum); lcd.setCursor(13,1); lcd.print("%"); } bool SendToNarodmon() { // Собственно формирование пакета и отправка. WiFiClient client; String buf; buf = "#" + Hostname + "#ESP_YOBA" + "\r\n"; // заголовок И ИМЯ, которое будет отображаться в народном мониторинге, чтоб не палить мак адрес dhttemp=dht.readTemperature(); // сохравняем в буферные переменные данные с dht22, чтобы удобно было оперировать dhthum=dht.readHumidity(); buf = buf + "#T1#" + String(bmp.readTemperature()) + "\r\n"; //температура bmp180 buf = buf + "#T2#" + String(dhttemp) + "\r\n"; //температура dht22 buf = buf + "#H1#" + String(dhthum) + "\r\n"; //влажность buf = buf + "#P1#" + String(bmp.readPressure()) + "\r\n"; //давление buf = buf + "##\r\n"; // закрываем пакет if (!client.connect("narodmon.ru", 8283)) { // попытка подключения Serial.println("connection failed"); lcd.clear(); lcd.print("connect failed"); return false; // не удалось; } else { WriteLcdTemp(); client.print(buf); // и отправляем данные if (debug) Serial.print(buf); while (client.available()) { String line = client.readStringUntil("\r"); // если что-то в ответ будет - все в Serial Serial.print(line); } } return true; //ушло } void loop() { //автояркость topwm=map(analogRead(A0), 0, 1023, 10, 950); analogWrite(14, topwm); delay(100);// нужна, беж делея у меня не подключался к вайфаю if (millis() - lastConnectionTime > postingInterval) {// ждем 5 минут и отправляем if (WiFi.status() == WL_CONNECTED) { // ну конечно если подключены if (SendToNarodmon()) { lastConnectionTime = millis(); }else{ lastConnectionTime = millis() - postingInterval + 15000; }//следующая попытка через 15 сек }else{ lastConnectionTime = millis() - postingInterval + 15000; Serial.println("Not connected to WiFi"); lcd.clear(); lcd.print("No WiFi");}//следующая попытка через 15 сек } yield(); // что за команда - фиг знает, но ESP работает с ней стабильно и не глючит. }

Что умеет устройство?
Устройство производит измерение температуры, давления (датчик bmp180) и влажности (датчик dht22), отображает показания на дисплее, и отправляет на сайт народного мониторинга.
При первом после прошивки включении, или при отсутствии знакомых wifi сетей устройство прикидывается точкой доступа открытого типа с именем ESP8266.

В com порт устройство шлет это:

Необходимо подключиться с телефона, ноутбука или планшета к точке с именем ESP8266, и пройти по адресу 192.168.4.1
Откроется такая страничка:


Нажимаем кнопку Configure Wifi, и попадаем на такую страничку


Далее выбираем свою сеть, вводим пароль, жмем Save. Готово, устройство само перезагружается, и начинает работать. Сначала на дисплей и в com порт выводится ip адрес и mac адрес устройства с префиксом ESP, его надо использовать в качестве id датчика при регистрации на сайте народного мониторинга, а через 15 секунд на дисплей, в com порт, и на сайт народного мониторинга выводятся первые показания с датчиков.
T1 - температура с bmp180
T2 - температура с dht22
P - атмосферное давление. На дисплей выводится в мм. рт. ст., на народный мониторинг идет в не помню каких единицах, преобразуется в мм. рт. ст. автоматически.
Н - влажность в процентах.


В строчках Т2 и Н ересь, потому что не подключен датчик dht22

В таком виде конструкция проработала пару недель, пока я потихоньку продумывал готовое устройство.
Готовое устройство решил собирать на модуле (такой же стоит на nodemcu)
Быстренько развел и вытравил плату.




Код менять не пришлось вообще. Номера портов для датчиков те же, необходимо только подключить голую esp8266 по типовой схеме, чтобы она могла работать, и можно было заливать прошивку. 3.3 вольта получил с помощью стабилизатора ams 1117 3.3v.
Питается устройство от телефонной зарядки 5в. 2А. Но и одного ампера, думаю, будет достаточно.


Для прошивки вывел отдельный 3-pin разъем с контактами RX, TX и GND.

Прошивал готовое устройство с помощью адаптера usb - uart. Плюс его в том, что на нем имеется переключатель 5v-3.3v, хотя знающие ребята говорят, что этот переключатель работает только для питания, а уровень rx и tx не меняется. Но у меня все работало без преобразования уровней, наверное потому, что esp8266 толерантна к 5v на rx tx, хоть и работает от 3.3.
Так же на готовой плате был предусмотрен переключатель для ввода в режим прошивки (красный ползунковый, нижний ползунок для ввода в режим прошивки. Верхний ползунок я подключил на gpio12, на всякий случай, возможно для переключения режимов индикации на будущее, а пока он не задействован. Можно не мудрить, и просто поставить перемычку между gpio0 и GND)

Для прошивки нужно подключить usb-uart преобразователь таким образом:
esp rx - uart tx
esp tx - uart rx
esp gnd - uart gnd

Затем подключить gpio0 к земле с помощью нижнего ползунка на переключателе, нажать кнопку «Reset» на плате (находится сверху), в arduinoIDE выбрать нужный com port, скорость загрузки (115200 для большинства плат esp8266), и нажать кнопку «Загрузка».
После окончания загрузки устройство начнет работать, переключатель прошивки нужно возвратить в положение OFF, иначе при следующей перезагрузке или отключении питания устройство опять войдет в режим прошивки.

Вспомним сдохший датчик dht22. Симптомы - постоянно показывает влажность 99.9, в сухую погоду может показывать меньше. Сдох он осенью 2016 года, исправно проработав всю весну и лето. Была неделя постоянных дождей, и мне на электропочту свалилось письмо от народного мониторинга, что, мол, ваш датчик несколько дней подряд показывает одно и то же. Я не стал менять датчик, а просто спрятал его из общего доступа до недавнего момента.
Возможной причиной помирания считаю тесный корпус. В качестве его основы было использовано яйцо от киндерсюрприза. Был разработан новый, более технологичный и просторный корпус из подрозетника и заглушки канализационной трубы. Вот оба корпуса рядом:


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

схема и внешний вид




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

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

В собранном виде

Испытание влажностью пройдено успешно. Датчик жив.

Это был полезный опыт для меня, я наконец то пощупал esp8266, и получил стабильно работающее полезное мне устройство.
Надеюсь кому то пригодится эта статья. Если возникнут трудности или вопросы, пишите в личку, отвечу.

Планирую купить +121 Добавить в избранное Обзор понравился +108 +214