В статье «DIY: передаем данные на километры с помощью контроллера Micro::Bit и радиомодуля EBYTE LoRa» (часть 1 и часть 2) мы рассказали, как обеспечить связь на обширных территориях при небольшой излучаемой мощности.
Но что, если нужно передавать данные на расстояния в десятки или даже сотни километров? Например, вдоль таких объектов, как автомобильные дороги, железнодорожные линии или трубопроводы?
Помимо спутников, здесь помогут ретрансляторы, способные принимать данные по радиоканалу и передавать их дальше, до следующего ретранслятора или до конечного узла обмена данными.
Пока, однако, мы не будем решать такие грандиозные задачи, ограничившись увеличением дальности с помощью одного ретранслятора на micro::bit с радиомодулем LoRa EBYTE E32.
Допустим, нам нужно контролировать погоду в парнике из дома, но расстояние между домом и парником такое, что при минимальной мощности радиомодуля 10 мВт надежную связь установить не получается.
Разместим где-нибудь посередине ретранслятор, который будет получать запросы от центрального узла, сделанного на базе Raspberry Pi, и передавать их в парник на узел micro::bit. Данные измерений в парнике будут передаваться обратно на центральный узел опять же через ретранслятор (рис. 1).
Макет системы сбора данных с ретранслятором показана на рис. 2.
Здесь мы использовали те же самые блоки, что и для системы с архитектурой «звезда» из прошлой статьи, изменив только программное обеспечение.
Центральный узел создан на базе Raspberry Pi, а ретранслятор и узел для парника — на базе micro::bit.
Конфигурацию радиомодулей E32 мы оставили прежней. Все радиомодули в наших примерах будут работать на канале 15, а их адреса приведены в табл. 1.
Табл. 1. Адреса радиомодулей
Узел |
Адрес |
Центральный узел |
14 (0x0E) |
Ретранслятор |
13 (0x0D) |
Парник |
12 (0x0C) |
Разумеется, для ретранслятора и парника можно использовать другой номер канала. Более того, центральный и периферийный узел могут передавать данные на одном канале, а ретранслятор — на другом. При выборе номеров каналов следует учитывать, какие частоты разрешены к использованию в вашей стране без лицензии, либо оформить соответствующие документы.
Узел ретранслятора
Программу micro::bit для ретранслятора, как и все программы из этой статьи, можно загрузить с сайта GitHub по адресу https://github.com/AlexandreFrolov/loranet.
Файл с программой для ретранслятора называется microbit-pxt-lora-repeater.hex, а файл программы для парника — microbit-lora-net-host2r.hex.
Программа ретранслятора очень проста. На этапе инициализации она задает параметры подключения и работы радиомодуля E32, а также устанавливает размер буферов передачи данных для UART.
После инициализации на светодиодной матрице micro::bit зажигается буква «R», идентифицирующая узел ретранслятора (рис. 3).
Когда центральный узел отправляет в ретранслятор команду «getRData», блок ретранслятора передает по радиоканалу команду «getData» на узел парника с адресом 12 и рисует на мониторе micro::bit стрелку, направленную на сервер. После этого на монитор выводится буква «R» (рис. 4).
В ответ на команду «getData», отправленную на узел парника, ретранслятор получает от этого узла данные измерений. Они не содержат строку «getRData» и отправляются ретранслятором в неизменном виде на центральный узел с адресом 14.
Как только данные будут отправлены, на мониторе ретранслятора на короткое время появится стрелка, направленная на юг, а затем ее сменит буква «R».
Таким образом, наш ретранслятор передает в одну сторону (в парник) команду «getRData», а затем в другую строну (на центральный узел) данные измерений в парнике.
Ретранслятор ничего не знает о структуре и размере передаваемых данных, за это отвечает центральный узел и узел парника.
Узел парника
Узел парника практически полностью аналогичен периферийным узлам из упомянутой выше статьи. Изменения касаются только ПО для micro::bit.
На этапе инициализации выполняются действия, необходимые для работы с радиомодулем и последовательным портом, после чего на монитор выводится буква «B» (рис. 5).
Когда от ретранслятора в узел парника поступает команда «getData», соответствующий блок вызывает функцию getWeatherData, возвращающую результаты измерений погоды. Далее полученные от этой функции данные отправляются в узел ретранслятора на 15 канале по адресу 13 (рис. 6).
Функция getWeatherData получает данные от погодной станции BME-280, преобразует их в текстовые строки и соединяет через символ точки с запятой (рис. 7).
Центральный узел
В предыдущей статье в центральном узле работала программа, отправляющая в цикле команду «getData» на все периферийные узлы, затем она записывала полученные от них данные измерений в JSON-файл.
Теперь центральный узел обращается к периферийному узлу через ретранслятор. Программа e32-loranet-repeater.py отправляет в узел ретранслятора команду «getRData», а полученные от ретранслятора данные измерений записывает в JSON-файл (листинг 1).
Листинг 1. Файл https://github.com/AlexandreFrolov/loranet/blob/main/py/e32-loranet-repeater.py
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import RPi.GPIO as GPIO
import serial
import time
import sys
from time import sleep
import json
NODE_ADDR_CHAN = [b'\x00\x0B\x0F',
b'\x00\x0C\x0F',
b'\x00\x0D\x0F']
def gpio_init ():
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
M0 = 22
M1 = 27
GPIO.setup(M0,GPIO.OUT)
GPIO.setup(M1,GPIO.OUT)
GPIO.output(M0,GPIO.LOW)
GPIO.output(M1,GPIO.LOW)
time.sleep(1)
ser = serial.Serial("/dev/serial0", 9600, timeout=1)
ser.flushInput()
return ser
def send_cmd(node):
try :
if ser.isOpen() :
ser.write(NODE_ADDR_CHAN[node])
ser.write('getRData \n'.encode())
except :
if ser.isOpen() :
ser.close()
GPIO.cleanup()
while ser.inWaiting() == 0:
sleep(0.03)
data_left = ser.inWaiting()
received_data = ser.readline()
sleep(0.03)
received_data += ser.read(data_left)
rec = received_data.decode("utf-8").strip()
node_data = rec.split(';')
return node_data
def format_node_data(node, node_data):
NODE_1_2_ITEMS = ['Температура',
'Давление',
'Влажность',
'Точка росы']
NODE_3_ITEMS = ['Температура CPU',
'Интенсивность освещения']
node_dict={}
i=0
for val in node_data:
val = str(val)
if(node == 0 or node == 1 or node == 2):
node_dict[NODE_1_2_ITEMS[i]]= val
else:
node_dict[NODE_3_ITEMS[i]]= val
i = i+1
return node_dict
def get_nodes_data():
nodes_dict={}
node = 2
node_data = send_cmd(node)
nodes_dict[node] = format_node_data(node, node_data)
return nodes_dict
def save_nodes_data_to_file(nodes_dict):
jsonString = json.dumps(nodes_dict, indent=2, ensure_ascii=False)
print(jsonString)
with open('hosts_data.json', 'w') as f:
json.dump(nodes_dict, f, indent=2, ensure_ascii=False)
ser = gpio_init()
nodes_dict = get_nodes_data()
save_nodes_data_to_file(nodes_dict)
По сравнению с ПО центрального узла из предыдущей статьи, основные изменения коснулись функции send_cmd.
Время ожидания ответа от периферийного узла, передаваемого через ретранслятор, может быть относительно большим. Программа дожидается ответа в бесконечном цикле:
while ser.inWaiting() == 0:
sleep(0.03)
Когда в устройстве serial появляются данные, они считываются и декодируются, после чего возвращаются в виде строки со значениями, разделенными символом «точка с запятой»:
data_left = ser.inWaiting()
received_data = ser.readline()
sleep(0.03)
received_data += ser.read(data_left)
rec = received_data.decode("utf-8").strip()
node_data = rec.split(';')
return node_data
Как и в программе из предыдущей статьи, функция save_nodes_data_to_file записывает данные в файл hosts_data.json, а также выводит на консоль:
$ python e32-loranet-repeater.py
{
"2": {
"Давление": "993",
"Точка росы": "4",
"Влажность": "24",
"Температура": "24"
}
}
Идеи для развития проекта
В каком направлении вы можете развивать свой учебный проект с ретранслятором?
Добавьте больше ретрансляторов
Прежде всего, можно добавить еще ретрансляторов, увеличив таким образом общее расстояние, на котором будет возможно получать данные измерений. На рис. 8 показана схема с использованием двух ретрансляторов.
Можно сделать так, чтобы первый ретранслятор передавал команду «getRData» на второй узел ретранслятора, установленный в гараже с адресом 12. Второй ретранслятор, в свою очередь, будет передавать эту команду дальше, узлу сбора данных в парнике с адресом 11 (табл. 2).
Табл. 2. Адреса радиомодулей
Узел |
Адрес |
Центральный узел |
14 (0x0E) |
Ретранслятор в летнем домике |
13 (0x0D) |
Ретранслятор в гараже |
12 (0x0C) |
Парник |
11 (0x0B) |
При передаче данных в обратную сторону узел из парника должен передавать данные на ретранслятор в гараже по адресу 12.
Передавайте данные измерений с ретрансляторов
Еще одна идея, которую вы можете реализовать, заключается в том, чтобы ретрансляторы не просто передавали данные в направлении центрального узла, а добавляли к ним результаты собственных измерений.
Например, узлы ретранслятора могут добавлять в данные температуру процессора в микрокомпьютере или данные погодной станции, установленной в ретрансляторе. Разумеется, нужно правильно отделить эти данные в общем потоке, а в программе, работающей на центральном узле, правильно их обработать.
Используйте антенны с большим усилением или направленные антенны
Существенно увеличить дальность при той же мощности можно с помощью антенн, обладающих большим усилением или направленных антенн.
Однако в том, что касается направленных антенн, не все так просто. Было бы идеально на узле ретранслятора подключить две такие антенны, направленные в разные стороны, каждая на свой ретранслятор или узел.
Но подключение двух радиомодулей с интерфейсом UART к одному micro::bit проблематично. Такую задачу можно решить с использованием радиомодулей LoRa с интерфейсами SPI или I2C.
Второй вариант — использовать в узле ретранслятора два микрокомпьютера micro::bit, к каждому из которых подключен радиомодуль LoRa. При этом данные между микрокомпьютерами можно передавать с помощью встроенного в micro::bit модуля Bluetooth.
Если у вас появятся еще какие-нибудь идеи по использованию ретрансляторов, расскажите о них в комментариях к этой статье!
Автор: Александр Фролов.
НЛО прилетело и оставило здесь промокод для читателей нашего блога:— 15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.