Kvazitec Weather Monitoring — автономная система мониторинга погодных условий, разрабатываемая на основе микроконтроллера Arduino. Система будет собирать данные с датчиков температуры, влажности, атмосферного давления, напряжения и тока, а затем передавать их по радиоканалу на сервер для анализа и прогнозирования погоды, контроля состояния системы.
Проект реализуется на базе микроконтроллера Arduino с использованием следующих компонентов:
#include <SPI.h> // библиотека для работы с шиной SPI
#include <Adafruit_Sensor.h>
#include "nRF24L01.h" // библиотека радиомодуля
#include "RF24.h" // ещё библиотека радиомодуля
#include <Adafruit_BME280.h>
#include <Adafruit_INA219.h>
#include <DHT.h>
#include <DHT_U.h>
#define DHTPIN 2
#define SEALEVELPRESSURE_HPA (1013.25)
DHT dht(DHTPIN, DHT22);
Adafruit_BME280 bme;
Adafruit_INA219 ina219;
RF24 radio(9, 10); // "создать" модуль на пинах 9 и 10 Для Уно
//RF24 radio(9,53); // для Меги
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; //возможные номера труб
float tranzmit[8];
void setup() {
Serial.begin(9600); // открываем порт для связи с ПК
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
digitalWrite(4, 1);
digitalWrite(5, 0);
if (!bme.begin(0x76))
{
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
if (! ina219.begin()) {
Serial.println("Failed to find INA219 chip");
while (1) { delay(10); }
}
dht.begin();
radio.begin(); // активировать модуль
radio.setAutoAck(1); // режим подтверждения приёма, 1 вкл 0 выкл
radio.setRetries(0, 15); // (время между попыткой достучаться, число попыток)
radio.enableAckPayload(); // разрешить отсылку данных в ответ на входящий сигнал
radio.setPayloadSize(32); // размер пакета, в байтах
radio.openWritingPipe(address[0]); // мы - труба 0, открываем канал для передачи данных
radio.setChannel(0x70); // выбираем канал (в котором нет шумов!)
radio.setPALevel (RF24_PA_MAX); // уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
radio.setDataRate (RF24_250KBPS); // скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
//должна быть одинакова на приёмнике и передатчике!
//при самой низкой скорости имеем самую высокую чувствительность и дальность!!
radio.powerUp(); // начать работу
radio.stopListening(); // не слушаем радиоэфир, мы передатчик
}
void loop() {
tranzmit[0] = bme.readTemperature();
tranzmit[1] = bme.readHumidity();
tranzmit[2] = bme.readPressure() / 100.0F;
float alt = bme.readAltitude(SEALEVELPRESSURE_HPA);
tranzmit[3] = dht.readHumidity(); //Измеряем влажность
float tin = dht.readTemperature(); //Измеряем температуру
tranzmit[4] = tin;
float shuntvoltage = ina219.getShuntVoltage_mV(); // Получение напряжение на шунте
float busvoltage = ina219.getBusVoltage_V();
tranzmit[5] = busvoltage; // Получение значение напряжения V
tranzmit[6] = ina219.getCurrent_mA(); // Получение значение тока в мА
//float power_mW = ina219.getPower_mW(); // Получение значение мощности
tranzmit[7] = busvoltage + (shuntvoltage / 1000); // Расчет напряжение на нагрузки
radio.write(&tranzmit, sizeof(tranzmit));
if (tin < 10.00) {
digitalWrite(5, 1);
} else {
digitalWrite(5, 0);
}
}
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
RF24 radio(4, 5); // "создать" модуль на пинах 9 и 10 Для Уно
//RF24 radio(9,53); // для Меги
float received_data[8];
String send;
unsigned long ntime;
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; //возможные номера труб
LiquidCrystal_I2C lcd(0x27,16,2); // Устанавливаем дисплей
void setup() {
Serial.begin(9600); // открываем порт для связи с ПК
radio.begin(); // активировать модуль
radio.setAutoAck(1); // режим подтверждения приёма, 1 вкл 0 выкл
radio.setRetries(0, 15); // (время между попыткой достучаться, число попыток)
radio.enableAckPayload(); // разрешить отсылку данных в ответ на входящий сигнал
radio.setPayloadSize(32); // размер пакета, в байтах
radio.openReadingPipe(1, address[1]); // хотим слушать трубу 0
radio.setChannel(0x70); // выбираем канал (в котором нет шумов!)
radio.setPALevel (RF24_PA_MAX); // уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
radio.setDataRate (RF24_250KBPS); // скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
//должна быть одинакова на приёмнике и передатчике!
//при самой низкой скорости имеем самую высокую чувствительность и дальность!!
radio.powerUp(); // начать работу
radio.startListening(); // начинаем слушать эфир, мы приёмный модуль
lcd.init();
lcd.backlight();// Включаем подсветку дисплея
ntime = millis();
}
void loop() {
byte pipeNo;
while (radio.available(&pipeNo)) { // слушаем эфир со всех труб
radio.read( &received_data, sizeof(received_data) ); // чиатем входящий сигнал
}
float temp = round(received_data[0]*100)/100;
float humb = round(received_data[1]*100)/100;
float press = round(received_data[2]*100)/100;
float hin = round(received_data[3]*100)/100;
float tin = round(received_data[4]*100)/100;
float busvoltage = round(received_data[5]*100)/100;
float current = round(received_data[6]*100)/100;
float loadvoltage = round(received_data[7]*100)/100;
if (millis - ntime > 10000) { // задержка между отправками строки с данными в COM-порт
send = "";
send = send+temp+humb+press+hin+tin+busvoltage+current+loadvoltage;
Serial.println(send);
}
if (analogRead(1) < 341) {
// Устанавливаем курсор на вторую строку и нулевой символ.
lcd.setCursor(0, 0);
// Выводим на экран количество секунд с момента запуска ардуины
lcd.print("T ");
lcd.print(temp);
lcd.setCursor(0, 1);
lcd.print("P ");
lcd.print(press);
lcd.setCursor(10, 0);
lcd.print("H ");
lcd.print(humb);
lcd.setCursor(7, 0);
// Выводим на экран количество секунд с момента запуска ардуины
lcd.print(" ");
}
if ((analogRead(1) < 683) & (analogRead(1) > 341)) {
lcd.setCursor(0, 0);
lcd.print("TiN ");
lcd.print(tin);
lcd.setCursor(0, 1);
lcd.print("HiN ");
lcd.print(hin);
lcd.setCursor(10, 0);
lcd.print(" ");
}
if ((analogRead(1) < 1024) & (analogRead(1) > 683)) {
lcd.setCursor(6, 0);
lcd.print(" ");
lcd.setCursor(8, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("V ");
lcd.print(loadvoltage);
lcd.setCursor(0, 1);
lcd.print("I ");
lcd.print(current);
lcd.setCursor(10, 0);
lcd.print(" ");
}
}
"""Для нормальной работы скрипта требуется наличие в директории данного скрипта следующих файлов:
1. Пустой текстовый файл userids.txt
2. Текстовый файл tokenf.txt, содержащий ТОЛЬКО токен вашего telegram-бота, который вы можете получить, создав бота
с помощью BotFather в Telegram
Также должны быть установлены сторонние библиотеки PyTelegramBotAPI, PySerial"""
import telebot
import serial
import time
from telebot import types
useridsf = open('userids.txt', 'r')
userids = useridsf.readlines()
useridsf.close()
for i in range(1, len(userids)):
userids[i] = int(userids[i])
print(userids)
ntime = time.time()
status = 1
temp = 0
humb = 0
press = 0
hin = 0
tin = 0
debug = #ввести ID чата отладки
busvoltage = 0
current = 0
loadvoltage = 0
try:
port = "COM4" # Replace with the appropriate COM port name
baudrate = 9600
ser = serial.Serial(port, baudrate=baudrate, bytesize=8)
except:
status = 0
def datahandler():
#Здесь данные, полученные из COM-порта должны становится
#нормальными списками из 8 элементов каждый. В списках должны содержаться передаваемые погодные данные
global status
try:
# Read a line of data from the serial port
line_in = ser.readline().decode().strip()
if line_in:
print(line_in)
global temp
global humb
global press
global hin
global tin
global busvoltage
global loadvoltage
global current
zindexs = []
for i1 in range(0, len(line_in)):
if line_in[i1] == '.':
zindexs.append(i1)
print(zindexs)
temp = line_in[0:zindexs[0]+3]
humb = line_in[zindexs[0]+3:zindexs[1]+3]
press = line_in[zindexs[1]+3:zindexs[2]+3]
hin = line_in[zindexs[2]+3:zindexs[3]+3]
tin = line_in[zindexs[3]+3:zindexs[4]+3]
busvoltage = line_in[zindexs[4]+3:zindexs[5]+3]
loadvoltage = line_in[zindexs[5]+3:zindexs[6]+3]
current = line_in[zindexs[6]+3:zindexs[7]+3]
except:
status = 0
def error(mess):
global status
bot.send_message(mess.chat.id, 'На данный момент ни одна из метеостанций Kvazitec, к сожалению, не способна предоставить данные. После получения данных хотя бы с одной из них вам будет отправлено уведомление. Приятного ожидания!')
bot.send_message(mess.chat.id, '⌛')
bot.send_message(debug, 'Error')
status = 1
tokenf = open('tokenf.txt', 'r')
toke = tokenf.readline()
bot = telebot.TeleBot(toke)
@bot.message_handler(commands=['start'])
def starter(mess):
global status
try:
userids.index(mess.chat.id)
except:
useridsf = open('userids.txt', 'a')
useridsf.write('\n'+str(mess.chat.id))
useridsf.close()
userids.append(mess.chat.id)
if status == 0:
error(mess)
elif status == 1:
datahandler()
if status == 1:
markup = types.InlineKeyboardMarkup()
markup.add(types.InlineKeyboardButton('KW V1 54.1', callback_data='v1.54.1'))
bot.send_message(mess.chat.id,'Доброго дня! Вам доступны погодные данные с метеостанций Kvazitec, список которых вы видите ниже. Для получения данных с какой-либо метеостанции нажмите на кнопку с её названием', reply_markup=markup)
elif status == 0:
error(mess)
print(userids)
@bot.callback_query_handler(func=lambda call: True)
def caller(call):
global status
if call.data == 'v1.54.1':
datahandler()
if status == 1:
markup1 = types.InlineKeyboardMarkup()
markup1.add(types.InlineKeyboardButton('Обновить данные', callback_data='v1.54.1'))
bot.send_message(call.message.chat.id,'Данные об окружающем воздухе:' + '\n' + 'Температура: ' + temp + '°C'+'\n' + 'Влажность: ' + humb + '%' + '\n' + 'Давление: ' + press + ' кПа', reply_markup=markup1)
elif status == 0:
error(call.message)
bot.polling(non_stop=True)
Исходный код проекта доступен по адресу: Kvazitec/KvaziWeather