В прошлой статье  «Метеостанция на основе ардуино» рассматривалась метеостанция, которая передавала данные на удалённый монитор с использованием блоков 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Д печати корпусов.

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

Доработка метеостанции, web сервер.