В прошлой статье «Метеостанция на основе ардуино» рассматривалась метеостанция, которая передавала данные на удалённый монитор с использованием блоков LoRa. Пришло время немного модернизировать метеостанцию. Технически процедура заключается в добавлении Ethernet Shield W5100 в приёмную часть (монитор) и изготовлении нового корпуса монитора.
// Приемник. //Arduino Uno, датчик температуры терморезистор TTC 103 (аналог), //ЖК дисплей ST7920 , блок LoRa XL1278-SMT. #include <SPI.h> //Библиотека для подключение внешних устройств #include <RH_RF95.h> // Библиотека для работы с блоком LoRa. #include <Ethernet.h> #include <math.h> //Библиотека для простых мат вычислений #include <U8glib.h> // Подключаем библиотеку U8glib byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ipAddress(192, 168, 1, 177); // Инициализируйте библиотеку сервера Ethernet с IP-адресом и портом, // который вы хотите использовать (порт 80 по умолчанию для HTTP) EthernetServer server(80); // Подпрограмма для вычисления температуры аналогового датчика. double Tehrmister(int RawADC){ double Temp; Temp=log(((10240000/RawADC)-10000)); Temp=1/(0.001129148+(0.000234125*Temp)+(0.0000000876741*Temp*Temp*Temp)); Temp=Temp-273.15; //Кельвин в Цельсий return Temp; } U8GLIB_ST7920_128X64_1X u8g(5); //(13, 11, 5, U8G_PIN_NONE); // настройка пинов u8g( SCK,MOSI,CS[, RST ]) RH_RF95 rf95(7, 2); // Подключаем блк LoRa 7 - выбор чипа NSS (пин на ардуино) // 2 - прерывание (пин на ардуино) // Создаём массив данных для приема через LoRa struct RECEIVE_DATA{ int Temperature; double Pozicion; int Skorost; // int Skorost_max; boolean Perimetr; int Vlazhnost; int Press; int Alt; }; RECEIVE_DATA mydata; // Переменные String Azm = ("С"); // Отоброжаемое состояние направления ветра - Азимут int TemperDom; // Отоброжение температуры в доме String Alarm; // Отоброжаемое состояние периметра охраны int switchPin = 3; // пин Вкл. охраны периметра String Alarm_sw; // Отоброжаемое сосояние включения сигнализации int piezoPin = 8; //Пищалка boolean a1 = 0; // состояние кнопки включения пищалки //uint32_t myTimer1; // int Sk = 0; // int sk1 = 0; // int sk2 = 1; int Skorost_sr; void setup() { pinMode(switchPin, INPUT); pinMode(10, OUTPUT); Serial.begin(9600); //Открывает последовательный порт, на скорости 9600 бит/с while (!Serial); if (!rf95.init()) { //В случае не выполнения условия написать LoRa failed! // u8g.firstPage(); // Всё что выводится на дисплей указывается в цикле: // u8g.firstPage(); do{ ... команды ... }while(u8g.nextPage()); // do{ // u8g.setFont(u8g_font_7x13); // Выбираем шрифт u8g_font_6x10 // u8g.setColorIndex(1); // Выбираем цвет белый // u8g.setPrintPos( 24, 35);u8g.print("LoRa failed!"); // Выводим текст "LoRa failed!" // в позиции 24х35 // }while(u8g.nextPage()); // delay(15000); } rf95.setTxPower(1); rf95.setFrequency(433.00); rf95.setModemConfig(RH_RF95::Bw125Cr48Sf4096 ); //Подключились к Ethernet Ethernet.begin(mac, ipAddress); // Запустили сервер server.begin(); // Serial.print("server is at "); // Serial.println(Ethernet.localIP()); } void loop() { TemperDom = double(Tehrmister(analogRead(0))); if (rf95.available()) { uint8_t len = sizeof(mydata); if (rf95.recv((uint8_t*)&mydata, &len)) if (0 <= mydata.Pozicion && 11.25 > mydata.Pozicion) Azm = ("C"); if (11.25 <= mydata.Pozicion && 33.75 > mydata.Pozicion) Azm = ("CCB"); if (33.75 <= mydata.Pozicion && 56.25 > mydata.Pozicion) Azm = ("CB"); if (56.25 <= mydata.Pozicion && 78.75 > mydata.Pozicion) Azm = ("BCB"); if (78.75 <= mydata.Pozicion && 101.25 > mydata.Pozicion) Azm = ("B"); if (101.25 <= mydata.Pozicion && 123.75 > mydata.Pozicion) Azm = ("ВЮВ"); // ВЮВ if (123.75 <= mydata.Pozicion && 146.25 > mydata.Pozicion) Azm = ("ЮВ"); // ЮВ if (146.25 <= mydata.Pozicion && 168.75 > mydata.Pozicion) Azm = ("ЮЮB"); // ЮЮВ if (168.75 <= mydata.Pozicion && 191.25 > mydata.Pozicion) Azm = ("Ю"); // Ю if (191.25 <= mydata.Pozicion && 213.75 > mydata.Pozicion) Azm = ("ЮЮЗ"); // ЮЮЗ if (213.75 <= mydata.Pozicion && 236.25 > mydata.Pozicion) Azm = ("ЮЗ"); // ЮЗ if (236.25 <= mydata.Pozicion && 258.75 > mydata.Pozicion) Azm = ("ЗЮЗ"); // ЗЮЗ if (258.75 <= mydata.Pozicion && 281.25 > mydata.Pozicion) Azm = ("З"); // З if (281.25 <= mydata.Pozicion && 303.75 > mydata.Pozicion) Azm = ("ЗСЗ"); // 3C3 if (303.75 <= mydata.Pozicion && 326.25 > mydata.Pozicion) Azm = ("СЗ"); // СЗ if (326.25 <= mydata.Pozicion && 348.75 > mydata.Pozicion) Azm = ("ССЗ"); //CC3 if (348.75 <= mydata.Pozicion && 360.00 > mydata.Pozicion) Azm = ("C"); // Вычисляем среднюю скорость ветра за 1 мин // if (millis() - myTimer1 >= 60000) { // ищем разницу (1 мин.) // myTimer1 = millis(); // сброс таймера // Skorost_sr = sk1/sk2; // sk1 = 0; // sk2 = 1; // } else { // Sk = (mydata.Skorost); // sk1 = sk1 + Sk; // sk2 = sk2 + 1; // } Skorost_sr = (mydata.Skorost); if (!mydata.Perimetr==0) Alarm = ("Авария"); else Alarm = ("Норма"); if(analogRead(switchPin) < 512){ // Кнопка нажата Alarm_sw = ("ВКЛ");a1 = 1;} else {Alarm_sw = ("ВЫКЛ");a1 = 0;} if(a1==1 && mydata.Perimetr==1) // Если нажата кнопка // и периметр Авария то { // Пищалка tone (piezoPin,1000,600); delay(600); tone (piezoPin,800,600); delay(4000); } // Выводим данные на экран. u8g.firstPage(); // Всё что выводится на дисплей указывается в цикле: // u8g.firstPage(); do{ ... команды ... }while(u8g.nextPage()); do{ u8g.setFont(rus6x12); // Выбираем шрифт u8g.setColorIndex(1); // Выбираем белый цвет // Отображение температуры u8g.drawStr( 0, 9,"Температура ул.= "); u8g.setPrintPos(98, 9); u8g.print(mydata.Temperature); // Вывод значения температуры на улице u8g.drawPixel(116,1); u8g.drawPixel(117,1); u8g.drawPixel(118,1); u8g.drawPixel(116,2); u8g.drawPixel(118,2); u8g.drawPixel(116,3); u8g.drawPixel(117,3); u8g.drawPixel(118,3); u8g.drawStr( 120, 9,"С"); // Отображение влажности воздуха u8g.drawStr( 0, 20,"Влажность = "); u8g.setPrintPos(72, 20); u8g.print(mydata.Vlazhnost); // Вывод значения влажности на улице u8g.drawStr( 90, 20,"%"); // Отображение направления ветра - Азимута u8g.drawStr( 0, 31,"Аз.= "); u8g.setPrintPos(30, 31); u8g.print(Azm); // Отображение скорости ветра u8g.drawStr( 54, 31,"Ск.в.="); u8g.setPrintPos(96, 31); u8g.print(Skorost_sr); // Вывод значения скорости ветра u8g.drawStr( 110, 31,"м/с"); // Отображение давления u8g.drawStr( 0, 42,"Давлен. ="); u8g.setPrintPos(58, 42); u8g.print(mydata.Press); // Вывод значения давления на улице u8g.drawStr( 80, 42,"мм.рт.ст"); // Отображение температуры в доме u8g.drawStr( 0, 53,"Температура дом ="); u8g.setPrintPos(105, 53); u8g.print(TemperDom); // Вывод значения температуры в доме u8g.drawPixel(118,44); u8g.drawPixel(119,44); u8g.drawPixel(120,44); u8g.drawPixel(118,45); u8g.drawPixel(120,45); u8g.drawPixel(118,46); u8g.drawPixel(119,46); u8g.drawPixel(120,46); u8g.drawStr( 122, 53,"С"); // Отоброжение состояния периметра u8g.drawStr( 0, 63,"Перим.="); u8g.setPrintPos(48, 63); u8g.print(Alarm); u8g.setPrintPos(100, 63); u8g.print(Alarm_sw); }while(u8g.nextPage()); // Проверяем, есть ли запросы EthernetClient client = server.available(); if (client) { // Запросы есть boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { // char c = client.read(); // Serial.write(c); // Меняем кодировку на странице браузера. <html> начало документа client.println("<!DOCTYPE html> <html lang='ru'> <meta charset='UTF-8'> <body>"); // client.println("<title>Данные с датчиков метеостанции</title>"); // Надпись в заголовке страницы client.println("<h2> Показания метеостанции:</h2>"); // client.println("<br />"); // переход на следующую строку client.print ("<p>- Температура на улице = "); client.print (mydata.Temperature); client.println (" C;</p>"); client.print ("<p>- Влажность воздуха = "); client.print (mydata.Vlazhnost); client.println (" %;</p>"); client.print ("<p>- Атмосферное давление = "); client.print (mydata.Press); client.println (" мм.рт.ст;</p>"); client.print ("<p>- Направление ветра "); client.println (Azm); client.println(";</p>"); client.print ("<p>- Скорость ветра = "); client.print (Skorost_sr); client.println (" м/с. </p>"); client.println("</body> </html>"); // Конец документа // Запрос // Даем немного времени на получение данных клиентом delay(5); // Закрываем коннект client.stop(); } } } } }
Адрес сервера метеостанции 192.168.1.177 , однако можно поменять на другой в строке - IPAddress ipAddress(192, 168, 1, 177); данного кода. STL файл для печати и скетч можно скачать с яндекса.
Напишите отзыв.
Шильд устанавливается на блок Arduino UNO, подключения внешних устройств остаются прежними, только подключаются не к ардуино, а к таким же портам на шильде. В общем схема особо не меняется и можно использовать схему из предыдущей статьи.
Программный код тоже претерпел изменения. В следствии малого размера памяти контроллера пришлось урезать часть функционала. Ниже представлен измененный код с учётом использования шильда. На основе шильда решено было создать серверную часть. Сервер отлично работает в локальной сети и зайти на него ложно с помощью любого браузера. Однако для подключения из внешней сети (интернет) в роутере нужно сделать проброс порта (в данной статье этот процесс не рассматривается :-)).
Передающая часть описана в предыдущей части, там же можно скачать архив со скетчем и STL файлами для 3Д печати корпусов.
Ниже представлен код для ардуино.