Вот так это всё выглядит в собранном виде. 

Передающая часть

Приёмная часть (монитор)

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

Кнопка с фиксацией на приёмной части предназначена для включения и отключения сигнала тревоги в случае нарушения периметра.

Схема передатчика и приёмника метеостанции.

В схеме приёмника не отображено подключение блока LoRa. Блок LoRa подключается также, как и в передающей части. Пьезоэлемент пищалки лучше сделать активным с добавлением транзистора (схем пьезопищалок в интернете полно).

 Стабилизатор на 3.3 В в схеме передатчика необязателен, можно подключиться к питанию 3.3 В на плате Arduino UNO. Кнопка подсветки подключена вместо джампера подсветки на плате LCD 1602A.

Колодка подключения датчиков предназначена для более удобного подключения датчиков. Колодку можно разместить на удалении от основного блока вблизи датчиков, а основной передающий блок метеостанции подключить к колодке витой парой.

Имя  
Эл. почта  
Сообщение  
  

Скетч передатчика метеостанции

// Передатчик.
//Arduino Uno, датчик температуры и влажности DHT-22 (DHT-11),
// индикатор двухстрочный 1602А, блок LoRa XL1278-SMT.
// Для анимометра используется оптический прерыватель KY-010.
// Для позиционера использкутся угловой датчик WDD35D4-5K.
// Датчик давления BMP280.

#include <Adafruit_Sensor.h>

#include <Adafruit_BMP280.h> //Библиотека для барометра

#include <SPI.h> //Библиотека для подключение внешних устройств

#include <RH_RF95.h> // Библиотека для работы с блоком LoRa.

#include <math.h> //Библиотека для простых мат вычислений

#include <Wire.h> // Библиотека для работы с протоколом I2C

// создаем объект-экран, передаём используемый адрес и разрешение экрана:
#include <LiquidCrystal_PCF8574.h> // библиотека лдя обмена с экраном по I2C

//LiquidCrystal_PCF8574 lcd(0x27); // Указываем I2C адрес (наиболее распространенное
// значение), а также параметры экрана в случае LCD 1602
// - 2 строки по 16 символов в каждой

LiquidCrystal_PCF8574 lcd(0x27);// адрес экрана 0x27


// подключаем библиотеку DHT
#include "DHT.h"       //Скетч по умолчанию рассчитан на датчик DH22, 

#define DHTPIN 6       // поэтому вам нужно сначала закомментировать 
#define DHTTYPE DHT22  // строчку #define DHTTYPE DHT22 
// #define DHTTYPE DHT11  // Для датчика DHT11 - #define DHTTYPE DHT11.

DHT dht(DHTPIN, DHTTYPE); // Инициализация датчика DHT.



RH_RF95 rf95(7, 2);// Подключаем блк LoRa 7 - выбор чипа NSS (пин на ардуино)
// 2 - прерывание (пин на ардуино)

int analogInput = 1; // Аналоговый вход позиционера.
int vout = 0; // Значение с входа с позиционера.
int switchPin = 5; // Защитный контур.
int pin_anem = 4; // Назначаем пин подключения анимометра
byte v;
int v1;
//int lastButton = HIGH;  // состояние Анемометра без срабатывания
//int currentButton;      // состояние Анемометра без срабатывания

float ob_per_sec = 0; // Частота оборотов
float ob_per_sec1 = 0;
int speed_wind = 0; // Значение после пересчета частоты обор. в скорость ветра м/с

int otobr = 0;
int otobr_max = 0;
int z = 0; // Переменная счетчика общего сброса

Adafruit_BMP280 bmp280; // I2C
//Adafruit_BMP280 bme(BMP_CS); // hardware SPI
//Adafruit_BMP280 bme(BMP_CS, BMP_MOSI, BMP_MISO,  BMP_SCK);


void setup() {

  pinMode(switchPin, INPUT); // Назначаем пин периметра на вход.

  pinMode(pin_anem, INPUT); // Назначаем пин анемометра на вход.

  lcd.begin(16, 2);// у нас экран 16 столбцов на 2 строки
  lcd.setBacklight(255); //установить яркость подсветки на максимум


  Serial.begin(9600); //Открывает последовательный порт, на скорости 9600 бит/с

  if (!bmp280.begin(BMP280_ADDRESS - 1)) {
    lcd.println(F("No BMP280 sensor"));
    delay(10000);
    lcd.clear(); //Очистка памяти диспея
  }


  dht.begin();

  while (!Serial);
  if (!rf95.init()) {
    lcd.println("LoRa failed!");      //В случае не выполнения условия появится
    //Serial.println("LoRa failed!");   //написать LoRa failed!
  } else lcd.println(" LoRa ");
  rf95.setTxPower(3);                // Устанавливаем выходную мощность.
  rf95.setFrequency(433.00);         // Устанавливаем частоту.
  rf95.setModemConfig(RH_RF95::Bw125Cr48Sf4096 );
}


// Создаём массив данных для передачи через LoRa
struct SEND_DATA {
  int Temperature;
  double Pozicion;
  int Skorost;
  // int Skorost_max;
  boolean Perimetr;
  int Vlazhnost;
  int Press;
  int Alt;
};
SEND_DATA mydata;
String Azm = ("N");

void(* resetFunc) (void) = 0; // объявляем функцию reset

void loop() {


  // Скорость ветра

  unsigned long Ltime1 = pulseInLong(pin_anem, LOW); // Отрицательный полупериод в мкС
  unsigned long Htime1 = pulseInLong(pin_anem, HIGH); // Положительный полупериод в мкС
 // unsigned long Ltime2 = pulseInLong(pin_anem, LOW,100000); // Отрицательный полупериод в мкС
//  unsigned long Htime2 = pulseInLong(pin_anem, HIGH,300000); // Положительный полупериод в мкС
//  unsigned long Ltime3 = pulseInLong(pin_anem, LOW,100000); // Отрицательный полупериод в мкС
//  unsigned long Htime3 = pulseInLong(pin_anem, HIGH,300000); // Положительный полупериод в мкС
//  unsigned long Ltime4 = pulseInLong(pin_anem, LOW,100000); // Отрицательный полупериод в мкС
//  unsigned long Htime4 = pulseInLong(pin_anem, HIGH,300000); // Положительный полупериод в мкС
  
//  Serial.print(" Ltime1 = ");
//  Serial.print(Ltime1);
//  Serial.print(" Htime1 = ");
//  Serial.print(Htime1);

  // Полный оборот в мкС
  unsigned long Time = Ltime1 + Htime1; // + Ltime2 + Htime2 + Ltime3 + Htime3 + Ltime4 + Htime4;

//  Serial.print(" Time = ");
//  Serial.print(Time);
  if (Ltime1 == 0 || Htime1 == 0){ob_per_sec = 0;}else{ 
  ob_per_sec =  250000 /(float) Time;}      // Часторта оборотов в сек.

  // ob_per_sec1 = 0;  // Сбрасываем кол-во оборотов в 0 по истечении 1 сек.

  if (ob_per_sec == 0) {speed_wind = 0;}
  if (ob_per_sec > 0.0 && ob_per_sec <= 1.0)   {speed_wind = 1;}
  if (ob_per_sec > 1.0 && ob_per_sec <= 1.5)   {speed_wind = 2;}
  if (ob_per_sec > 1.5 && ob_per_sec <= 2.0)   {speed_wind = 3;}
  if (ob_per_sec > 2.0 && ob_per_sec <= 2.5)   {speed_wind = 4;}
  if (ob_per_sec > 2.5 && ob_per_sec <= 3.0)   {speed_wind = 5;}
  if (ob_per_sec > 3.0 && ob_per_sec <= 3.5)   {speed_wind = 6;}
  if (ob_per_sec > 3.5 && ob_per_sec <= 4.0)   {speed_wind = 7;}
  if (ob_per_sec > 4.0 && ob_per_sec <= 4.5)   {speed_wind = 8;}
  if (ob_per_sec > 4.5 && ob_per_sec <= 5.0)   {speed_wind = 9;}
  if (ob_per_sec > 5.0 && ob_per_sec <= 5.5)  {speed_wind = 10;}
  if (ob_per_sec > 5.5 && ob_per_sec <= 6.0) {speed_wind = 11;}
  if (ob_per_sec > 6.0 && ob_per_sec <= 6.5) {speed_wind = 12;}
  if (ob_per_sec > 6.5 && ob_per_sec <= 7.0) {speed_wind = 13;}
  if (ob_per_sec > 7.0 && ob_per_sec <= 7.5) {speed_wind = 14;}
  if (ob_per_sec > 7.5 && ob_per_sec <= 8.0) {speed_wind = 15;}
  if (ob_per_sec > 8.0 && ob_per_sec <= 8.5) {speed_wind = 16;}
  if (ob_per_sec > 8.5 && ob_per_sec<= 9.0) {speed_wind = 17;}
  if (ob_per_sec > 9.0 && ob_per_sec <= 9.5) {speed_wind = 18;}
  if (ob_per_sec > 9.5 && ob_per_sec <= 10.0) {speed_wind = 19;}
  if (ob_per_sec > 10.0 && ob_per_sec <= 10.5) {speed_wind = 20;}
  if (ob_per_sec > 10.5 && ob_per_sec <= 11.0) {speed_wind = 21;}
  if (ob_per_sec > 11.0 && ob_per_sec <= 11.5) {speed_wind = 22;}
  if (ob_per_sec > 11.5 && ob_per_sec <= 12.0) {speed_wind = 23;}
  if (ob_per_sec > 12.0 && ob_per_sec <= 12.5) {speed_wind = 24;}
  if (ob_per_sec > 12.5 && ob_per_sec <= 13.0) {speed_wind = 25;}
  if (ob_per_sec > 13.0 && ob_per_sec <= 13.5) {speed_wind = 26;}
  if (ob_per_sec > 13.5 && ob_per_sec <= 14.0) {speed_wind = 27;}
  if (ob_per_sec > 14.0 && ob_per_sec <= 14.5) {speed_wind = 28;}
  if (ob_per_sec > 14.5 && ob_per_sec <= 15.0) {speed_wind = 29;}
  if (ob_per_sec > 15.0) {speed_wind = 30;}

  // if (speed_wind > speed_wind_max) {speed_wind_max = speed_wind;} // Проверяем и
  // переписываем, если действующее значение больше чем предыдущее значение.

  mydata.Skorost = speed_wind;
  //mydata.Skorost_max = speed_wind_max;


  // Температура, влажность и давление.

  int T = bmp280.readTemperature();

//  Serial.print(F("Температура = "));
//  Serial.print(T);
//  Serial.println(" *С");

  int P = (bmp280.readPressure()) * 0.00750062;

  mydata.Press = P;

//  Serial.print(F("Атм.Давление = "));
//  Serial.print (P);
//  Serial.println(" мм.рт.ст.");  // mmHg

  int A = bmp280.readAltitude(1013.25);// это должно быть адаптировано к вашему местному прогнозу

  mydata.Alt = A;
  Serial.print(F("Высота над уровнем моря = "));
  Serial.print(A);
  Serial.println(" м");



  float h = dht.readHumidity();        // Чтение данных о влажности и запись в h.
  float t = dht.readTemperature();     // Чтение температуры в град. цельсия  и запись в t.
  if (isnan(h) || isnan(t)) {  // Проверка. Если не удается считать показания,
    // выводится «Ошибка считывания», и программа
    // Serial.println("Failed to read from DHT sensor!"); //завершает работу (чтобы повторить попытку).
    lcd.println("Failed to read from DHT sensor!");
  }

  mydata.Temperature = t;
  mydata.Vlazhnost = h;

  if (digitalRead(switchPin) == HIGH) mydata.Perimetr = HIGH;
  else mydata.Perimetr = LOW;
  //Serial.print(" Perimetr = ");
  //Serial.println(mydata.Perimetr);


  // Позиционер

  vout = analogRead(analogInput); // чтение значения позиционера.
  mydata.Pozicion = vout * 5.0 / 1024.0 * 72; // Вычесление знач. позиции Аз

  if (0 <= mydata.Pozicion && 11.25 > mydata.Pozicion)
    Azm = ("N");
  if (11.25 <= mydata.Pozicion && 33.75 > mydata.Pozicion)
    Azm = ("NNE");
  if (33.75 <= mydata.Pozicion && 56.25 > mydata.Pozicion)
    Azm = ("NE");
  if (56.25 <= mydata.Pozicion && 78.75 > mydata.Pozicion)
    Azm = ("ENE");
  if (78.75 <= mydata.Pozicion && 101.25 > mydata.Pozicion)
    Azm = ("E");
  if (101.25 <= mydata.Pozicion && 123.75 > mydata.Pozicion)
    Azm = ("ESE");
  if (123.75 <= mydata.Pozicion && 146.25 > mydata.Pozicion)
    Azm = ("SE");
  if (146.25 <= mydata.Pozicion && 168.75 > mydata.Pozicion)
    Azm = ("SSE");
  if (168.75 <= mydata.Pozicion && 191.25 > mydata.Pozicion)
    Azm = ("S");
  if (191.25 <= mydata.Pozicion && 213.75 > mydata.Pozicion)
    Azm = ("SSW");
  if (213.75 <= mydata.Pozicion && 236.25 > mydata.Pozicion)
    Azm = ("SW");
  if (236.25 <= mydata.Pozicion && 258.75 > mydata.Pozicion)
    Azm = ("WSW");
  if (258.75 <= mydata.Pozicion && 281.25 > mydata.Pozicion)
    Azm = ("W");
  if (281.25 <= mydata.Pozicion && 303.75 > mydata.Pozicion)
    Azm = ("WNW");
  if (303.75 <= mydata.Pozicion && 326.25 > mydata.Pozicion)
    Azm = ("NW");
  if (326.25 <= mydata.Pozicion && 348.75 > mydata.Pozicion)
    Azm = ("NNW");
  if (348.75 <= mydata.Pozicion && 360.00 > mydata.Pozicion)
    Azm = ("N");



  // Вывод данных.

  // Serial.print("Temp = "); // Печать заголовка
  // Serial.print(mydata.Temperature); // Выводим показания датчика в порт
  // Serial.print("  ");

  // Serial.print("Влажн = "); // Печать заголовка
  // Serial.print(mydata.Vlazhnost); // Выводим показания датчика в порт
  // Serial.print(" % ");

  lcd.clear(); //Очистка памяти диспея
  lcd.setCursor(0, 0); //Установка курсора в начало 1 строки
  lcd.print("Tmp= "); // Печать заголовка
  lcd.print(mydata.Temperature); // Выводим показания датчика
  lcd.print(" C");

  lcd.setCursor(10, 0); //Установка курсора в начало 1 строки
  lcd.print("P= "); // Печать заголовка
  lcd.print(mydata.Press); // Выводим показания датчика



  // Serial.print("Poz = "); // Печать заголовка
  // Serial.print(mydata.Pozicion); // Выводим показания датчика в порт
  // Serial.print("  ");

  lcd.setCursor(0, 1); //Установка курсора в начало 2 строки
  lcd.print("Az = "); // Печать заголовка
  lcd.print(Azm); // Выводим показания датчика


  // Serial.print("U пин = "); // Печать заголовка
  // Serial.print(currentButton); // Выводим показания датчика в порт
  // Serial.print(" ");

  // Serial.print("U пин1 = "); // Печать заголовка
  // Serial.print(ob_per_sec); // Выводим показания датчика в порт
  // Serial.print(" ");

  // Serial.print("U = "); // Печать заголовка
  // Serial.print(mydata.Skorost); // Выводим показания датчика в порт
  // Serial.print(" m/s ");

  lcd.setCursor(8, 1); //Установка курсора в 10 позицию 2 строки
  lcd.print(" U= "); // Печать заголовка
  lcd.print(mydata.Skorost); // Выводим показания датчика

  // Serial.print (" Umax = ");
  // Serial.println (speed_wind_max);

  rf95.send((uint8_t*)&mydata, sizeof(mydata));
  rf95.waitPacketSent();

  if (z >= 7200) {
    resetFunc(); //вызываем reset каждые 12 часов
  }
  z = z + 1;
  delay(600); // Время индикации
  
}
// Приемник.
//Arduino Uno, датчик температуры терморезистор TTC 103 (аналог), 
//ЖК дисплей ST7920 , блок LoRa XL1278-SMT.

#include <SPI.h> //Библиотека для подключение внешних устройств
#include <RH_RF95.h> // Библиотека для работы с блоком LoRa.
#include <math.h> //Библиотека для простых мат вычислений

// Подпрограмма для вычисления температуры аналогового датчика.
  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;
  }

#include <U8glib.h>      // Подключаем библиотеку дисплея U8glib 

 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; // Задаём название массива mydata

// Переменные
String Azm = ("С");  // Отоброжаемое состояние направления ветра - Азимут
int TemperDom;       // Отоброжение температуры в доме
String Alarm;        // Отоброжаемое состояние периметра охраны
float switchPin = 3; // пин Вкл. охраны периметра
String Alarm_sw;     // Отоброжаемое сосояние включения сигнализации

// Переменные для хранения состояния кнопки
int lastButton = 0;
int currentButton = 0;

// функция для подавления дребезга
 int debounse(int last) {
 int current = analogRead(switchPin);
 if(last != current) {
 delay(5);
 current = analogRead(switchPin);
 }
 return current;
 }

 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 выводится написать 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);         
       }else {         // Если блок LoRa работает нормально то выводится надпись LoRa.
    u8g.firstPage();  // Всё что выводится на дисплей указывается в цикле: 
                      // u8g.firstPage(); do{ ... команды ... }while(u8g.nextPage());
    do{                                    
         u8g.setFont(u8g_font_7x13);                 // Выбираем шрифт u8g_font_6x10
         u8g.setColorIndex(1);                       // Выбираем цвет белый
         u8g.setPrintPos( 50, 35); u8g.print("LoRa"); // Выводим текст "LoRa" 
                                                       // в позиции  24х35
     
     }while(u8g.nextPage()); }
   
   rf95.setTxPower(1);  // Задаём уровень вых. мощности блока LoRa
   rf95.setFrequency(433.00);  // Задаём частоту работы блока LoRa
   rf95.setModemConfig(RH_RF95::Bw125Cr48Sf4096 );
       }

void loop() {

 currentButton = debounse(lastButton);
 if(lastButton <= 512 && currentButton >= 512) 
 lastButton = currentButton;

  TemperDom = double(Tehrmister(analogRead(0))); // Заносим в переменнйю значение 
                                                 // температуры в доме   
 if (rf95.available())        // Если с блока LoRa пишёл пакет, то
  {
    uint8_t len = sizeof(mydata);           // Выводим данные из пакета в массив  
    if (rf95.recv((uint8_t*)&mydata, &len)) // данных mydata  

    // Заносим в переменную Azm значение направления ветра
        
    if (0 <= mydata.Pozicion && 11.25 > mydata.Pozicion)  // Если показания от 0 до 11.25 градусов, 
          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 
      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());  
  } 
}

Скетч приёмника метеостанции.

 

STL файлы для печати и инструкцию можно скачать с яндекса, там же имеются скетчи и схема.

Напишите отзыв.

Метеостанция на основе Ардуино

 

    Данный проект разрабатывался с целью изучения способов подключения датчиков и блоков к Ардуино.

Было использовано много способов и в итоге пришёл к данному варианту. В дальнейшем планируется расширение проекта подключение интернет модуля.

Итак, построение метеостанции своими руками.

Проект состоит из двух частей – приёмной и передающей.

Предающая часть состоит из:

  • Блока Arduino UNO;
  • Бока LoRa XL1278-SMT;
  • Индикатора двухстрочного 1602А;
  • Датчика температуры и влажности DHT–22  (возможна установка DHT-11);
  • Датчика давления ВМР280;

   

   Для анемометра используется оптический прерыватель KY-010;

Для азимутального позиционера используется угловой датчик WDD35D4-5K.

Также необходимо предустановить библиотеки:

  • Adafruit_Sensor.h;
  • Adafruit_BMP280.h;
  • SPI.h;
  • RH_RF95.h;
  • math.h;
  • Wire.h.

   Приёмная часть состоит из:

  • Блока Arduino UNO;
  • Бока LoRa XL1278-SMT;
  • ЖК дисплей ST 7920;
  • Датчик температуры терморезистор ТТС 103.

 

  Также необходимо предустановить библиотеку U8glib.h.

Метеостанция измеряет и передает на приёмный блок следующие параметры:

  • Температура на улице;
  • Влажность  на улице;
  • Направление ветра (азимут);
  • Скорость ветра в м/с;
  • Атмосферное давление в мм.рт.ст;
  • Состояние охранного периметра (геркон на двери помещения или дверцы ящика где расположена метеостанция);
  • Также приёмная часть (монитор) измеряет и выводит на дисплей температуру в доме.

  Теперь пару строк о датчиках.

Корпуса датчиков анемометра и позиционера (флюгера), и остальные корпуса распечатаны на 3Д принтере.

 

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

Метеобудка изображена на рисунке без задней стенки, чтобы было видно её устройство.

      В ходе эксплуатации метеостанции (во влажном климате) столкнулся с одной проблемой - это коррозия платы датчиков, находящихся на улице, особенно страдал датчик измеряющий температуру и влажность. Решил данную проблему нанесением лака КО-921 на поверхность платы, отмечаю именно платы, внутрь датчика заливать лак крайне нежелательно.