Метеостанция на NodeMcu. Народный мониторинг. Домашняя метеостанция на Arduino и отправка данных на "Народный мониторинг" Формат передачи данных

Метеостанция на NodeMcu. Народный мониторинг. Домашняя метеостанция на Arduino и отправка данных на "Народный мониторинг" Формат передачи данных

25.10.2020

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

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

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

Сторожевой таймер стоит на случай ч.п. Как показывает практика, 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 : Все довольно интересно, но на мой взгляд заслуживает дальнейшего развития. Чем и займемся через какое то время.

Это совместный проект. Ссылки на каналы, сайт и архив авторов будут в конце описания. Создаётся блочная система управления ВетроСолнечной электростанции. Имеем два дачных участка с альтернативным энергообеспечением. На одном участке есть внешнее электричество, на втором полное отсутствие такового. Участки находятся в разных регионах России. На первом участке установлен самодельный ветрогенератор мощностью 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 в регулярно обновляемом

Введение

Приветствую всех, сегодня хочу рассказать вам о небольшой подпрограмме или утилите, кому как удобней, под названием «Монитор порта». Если вы уже знакомы с Arduino IDE то вы не раз с ней сталкивались и догадались о чем пойдет речь. Но не торопитесь уходить, вам точно будет что прочесть, так как мы пройдемся от основ до полного разбора ее работы.

И так, «Монитор порта» это небольшая подпрограмма Arduino IDE, предназначенная для приёма-передачи данных из-в Arduino. Ввиду того, что Arduino IDE не имеет никаких средств отладки скетчей, это единственное средство проверить все ли работает верно, и так как надо.

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

Саму форму «Монитора порта» можно разбить на три части: верхняя , центральная и нижняя .

  1. В верхней части расположено поле ввода, в которое пользователь может вписать те данные, которые он хочет отправить в Arduino. Это может быть как текст, так и цифры (подробнее о формате передачи я расскажу чуть ниже). По кнопке «Отправить» как вы уже догадались, подпрограмма отправляет введённые данные в COM-порт и далее в Arduino.
  2. В центральной же части расположено текстовое поле, в которое выводиться вся информация, полученная из COM-порта, т.е. то, что было отправлено из Arduino.
  3. В нижней части формы, расположены дополнительные настройки, а именно:
  • «Автопрокрутка» - Удобна в том случае, когда вы хотите видеть всегда свежую информацию, полученную из Arduino. Центральная часть автоматически пролистывается в самый низ поля.
  • «Постфикс» - Выпадающий список, в котором можно выбрать один из вариантов постфикса, т.е. когда вы нажимаете кнопку «Отправить» в верхней части формы, к данным которые вы ввели в поле, будут добавлены еще несколько байт, какие читайте ниже.
  • «Скорость» - Выпадающий список, в котором необходимо выбрать скорость передачи данных в бодах.

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

Передача данных из Arduino в «Монитор порта»

Начнем мы с Arduino.

Для того чтобы передать данные из Arduino в «Монитор порта» необходимо в функции setup() проинициализировать класс Serial вызвав его метод begin попутно передав скорость и настройки COM-порта.

Синтаксис.

Serial.begin(скорость, настройки);

  • Где скорость - это скорость передачи данных бод в секунду.
  • В настройках (не обязательный параметр) же указывается, сколько информационных бит в байте, а также количество стоповых бит и добавлять ли бит четности. По умолчанию если не передать настройки (а они нам не нужны в 99.9% случаев), класс Serial возьмёт стандартные настройки, а именно:
  1. Количество информационных бит в байте - 8.
  2. Количество стоповых бит - 1.
  3. Бит четности - Без бита четности.

Что такое стартовый бит, информационный бит, бит четности, почему скорость измеряется в бодах, я расскажу вам в другой статье, иначе переварить такой большой объём информации, а статья получиться не маленькая, будет не просто. Сейчас же мы будем пользоваться стандартными настройками, где скорость равна 9600 бод в секунду, а настройки Arduino будет выбирать автоматически.

Итого у нас получилось следующее:

Void setup() { // Инициализируем (запускаем) класс Serial вызывая его метод begin указывая скорость 9600 бод в секунду. Serial.begin(9600); }

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

Void loop() { // Отправляем «Hellow World!». Serial.print("Hellow World!"); // Отправляем «Hellow World!» включая спецсимволы, означающие переход на новую строку. Serial.println("Hellow World!"); // Спим одну секунду. delay(1000); }

Таким образом, в мониторе порта мы будем видеть строку, состоящую из двух «Hellow World!» каждую секунду (см. фото выше ).

Класс Serial содержит и другие методы для работы с монитором порта, но, как правило, методов print и println достаточно в большинстве случаев.

Получение данных отправленных из «Монитора порта» в Arduino

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

Поможет нам с этим все тот же класс Serial и его метод readString .

И так по команде «HIGH » мы будем включать светодиод, а по команде «LOW » будем выключать.

Для того чтобы отправить команду, необходимо в поле расположенном в верхней части формы набрать текст, и нажать кнопку «Отправить». Получать команды мы будем при помощи упомянутого метода readString.

Итого у Вас должно получиться следующее.

Void setup() { Serial.begin(9600); pinMode(13, OUTPUT); } void loop() { // Получаем команды на включение-выключение светодиода на 13 порту. String str = Serial.readString(); // Если команда «HIGH» то включаем светодиод. if (str == "HIGH") digitalWrite(13, HIGH); // Если команда «LOW» то выключаем светодиод. if (str == "LOW") digitalWrite(13, LOW); // Спим 1 секунду. delay(1000); }

Вот так, без особых мучений можно создать N-е количество команд и обрабатывать их в Arduino.

Формат передачи данных

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

К примеру, отправив один байт равный 128, на самом деле монитор порта получит три байта.

  • Байт 49 - Символ единицы в кодировке ASCII.
  • Байт 50 - Символ двойки.
  • Байт 56 - Символ восьмерки.

При выполнении метода println мы получим и вовсе 5 байт. Где первые три будут описанные выше, а два дополнительных это байт CR (13) и LF(10), означающие перевод на новую строку.

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

И вот теперь прочтя все, что я тут написал, наконец, можно рассказать что такое «Постфикс», выпадающий список в нижней части монитора порта.

Постфикс это байт или байты, в зависимости от того какой пункт вы выбрали, которые будут добавлены к данным которые вы ввели в поле для отправки.

Например, написав в поле для отправки число 128 и нажав на кнопку «Отправить» мы получим следующее:

  • В постфиксе выбрано «Нет конца строки» - Монитор порта отправит только то что было введено в поле для отправки, не добавляя ничего.
  • В постфиксе выбрано «NL (Новая строка)» - Монитор порта отправит то, что было введено в поле для отправки, и добавит байт LF (10).
  • В постфиксе выбрано «CR (Возврат каретки)» - Монитор порта отправит то, что было введено в поле для отправки, и добавит байт CR (10).
  • В постфиксе выбрано «NL & CR» - Монитор порта отправит то, что было введено в поле для отправки, и добавит два байт CR (13) и LF (10).

На этом все. Пишите в комментариях, что вам не понятно, и в новых статьях мы попробуем расписать это более подробно.

Ну а следующая статья будет о том, как написать свой монитор порта на Delphi.

Успехов вам и удачи.

Пожалуйста, включите javascript для работы комментариев.

В которой описывалось создание устройства для мониторинга параметров ПК. Сразу захотелось что-то подобное. Но так как опыта программирования 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) . После соединения на дисплее должна быть похожая картина.



© 2024 beasthackerz.ru - Браузеры. Аудио. Жесткий диск. Программы. Локальная сеть. Windows