LoRa sx1278 и Raspberry Pi - дальняя P2P радиосвязь
-
Технология LoRa (англ. Long Range - дальний диапазон) набирает популярность в сфере IoT, подключенных автомобилей, M2M телематики и т.д. Благодаря возможности передавать данные на большое расстояние с минимальным энергопотреблением разработчики предпочитают использовать LoRa для приёма/передачи данных от устройств, питаемых от батарей.
В этой статье мы рассмотрим использование LoRa модуля SX1278/SX1276 (дальность передачи данных несколько километров) c Raspberry Pi для общения с другим устройством - Arduino с таким же модулем LoRa - SX1278. На практике это можно использовать следующим образом - Arduino выступает как сервер, собирающий данные от множества датчиков и передающий их на удалённый Raspberry Pi, выступающий в роли клиента, принимающего данные и загружающего их в облако через Интернет-соединение. Итак, поехали!
Подключение LoRa модуля SX1278 к Raspberry Pi
SX1278 16ти контактный модуль, взаимодействует с Raspberry Pi по SPI интерфейсу (логика 3.3V), поэтому подключать его можно напрямую к SPI-пинам GPIO
Raspberry Pi SX1278 3.3V <--> 3.3V Ground <--> Ground GPIO 10 <--> MOSI GPIO 9 <--> MISO GPIO 11 <--> SCK GPIO 8 <--> Nss / Enable GPIO 4 <--> DIO 0 GPIO 17 <--> DIO 1 GPIO 18 <--> DIO 2 GPIO 27 <--> DIO 3 GPIO 22 <--> RST
В этом примере я буду запитывать модуль от Raspberry Pi, тока должно хватить, т.к это энергоэффективный модуль с низким потреблением тока. При желании можно также запитать модуль от внешнего источника
Библиотека PyLora
Существует множество python библиотек для работы с LoRa модулями. Чаще всего Raspberry Pi используется в базовых станций LoRaWan для получения данных от множества LoRa устройств и последующей отправки этих данных на облачный сервер. Мы же пока рассмотрим простой P2P обмен данными при помощи Python пакета PyLora.
Подготовка Raspberry Pi
Как уже было сказано выше, взаимодействие между LoRa модулем SX1298 и Raspberry Pi происходит через SPI интерфейс, поэтому первым делом запустим из консоли sudo raspi-config и в появившемся окне выберем 5 пункт - Interfacing Options, а затем пункт "SPI enable" для включения SPI интерфейса.
Далее установим Python библиотеку для работы с GPIO Raspberry Pi
pip install RPi.GPIO
библиотеку для работы с SPI spidev
pip install spidev
и собственно пакет pyLoRa
pip install pyLoRa
PyLora также поддерживает зашифрованные соединения, но их мы рассмотрим в следующих статьях.Программируем Raspberry Pi
В P2P LoRa соединениях модуль, передающий данные называется сервером, а принимающий - клиентом. Arduino c датчиком будет передавать полезные данные (сервер), а Raspberry Pi (клиент) - принимать.
Сама по себе программа очень простая - мы должны настроить SX1278 для работы на частоте 433Мгц и затем "слушать" эфир для приёма входящих пакетов. Если что-то приходит, выводим значение в терминал.
Подключаем необходимые библиотеки:
from time import sleep from SX127x.LoRa import * from SX127x.board_config import BOARD
Далее создадим класс LoRaRcvCont() с тремя методами.
Так как нам требуется только работа Raspberry Pi в качестве клиента, то в классе определены только методы init, start и rx_done
Метод set_pa_config задаёт режим работы модуля. В нашем случае инициализируем модуль для работы на частоте 433МГц с пропускной способностью 125КГц
from time import sleep from SX127x.LoRa import * from SX127x.board_config import BOARD BOARD.setup() class LoRaRcvCont(LoRa): def __init__(self, verbose=False): super(LoRaRcvCont, self).__init__(verbose) self.set_mode(MODE.SLEEP) self.set_dio_mapping([0] * 6) def start(self): self.reset_ptr_rx() self.set_mode(MODE.RXCONT) while True: sleep(.5) rssi_value = self.get_rssi_value() status = self.get_modem_status() sys.stdout.flush() def on_rx_done(self): print("\nReceived: ") self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) print(bytes(payload).decode("utf-8",'ignore')) self.set_mode(MODE.SLEEP) self.reset_ptr_rx() self.set_mode(MODE.RXCONT) lora = LoRaRcvCont(verbose=False) lora.set_mode(MODE.STDBY) #Medium Range Defaults after init are 434.0MHz, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on 13 dBm lora.set_pa_config(pa_select=1) try: lora.start() except KeyboardInterrupt: sys.stdout.flush() print("") sys.stderr.write("KeyboardInterrupt\n") finally: sys.stdout.flush() print("") lora.set_mode(MODE.SLEEP) BOARD.teardown()
В функции start происходит настройка модуля как постоянного получателя данных (режим RXCONT), а также постоянный мониторинг (каждые полсекунды) уровня мощности принимаемого сигнала RSSI и статуса. RSSI измеряется вdBm и является отрицательной величиной. Минимальное значение -120 dBm.
Функция on_rx_done выполняется после приёма входящего пакета данных. После установки флага RxDone в переменную payload помещается из Rx-буффера полученное значение, затем конвертируем значение этой переменной в utf-8 и выводим в терминал. Возвращаем модуль в спящий режим до приёма следующего значения.
Также в программе реализовано завершение при нажатии на кнопки клавиатуры.
Подключение SX1278 к Arduino
SX1278 Arduino UNO 3.3V <--> 3.3V Gnd <--> Gnd En/Nss <--> D10 G0/DIO0 <--> D2 SCK <--> D13 MISO <--> D12 MOSI <--> D11 RST <--> D9
Программируем Arduino
Первым делом нужно установит в Arduino IDE библиотеку Radiohead от AirSpayce. Скачать её можно отсюда -https://github.com/PaulStoffregen/RadioHead
Программа для Arduino будет отправлять тестовые пакеты с численными значениями от 0 до 9.
Подключаем SPI библиотеку и RH_RF95 для осуществления LoRa связи. Затем прописываем, к каким контактам Arduino подключены линии CS, RST, INT модуля SX1278 и устанавливаем частоту работы модуля (434Мгц)
В функции setup перезагружаем LoRa модуль, устанавливая низкий уровень на контакте сброса (RST) на 10 миллисекунд. Инициализируем SX1278 функцией rf95.init() . Затем устанавливаем частоту и мощность передатчика (чем больше, тем дальше максимальное расстояние передачи, но и выше энергопотребление)
#include <SPI.h> //подключаем библиотеку SPI #include <RH_RF95.h> // подключаем библиотеку RF95 #define RFM95_CS 10 #define RFM95_RST 9 #define RFM95_INT 2 #define RF95_FREQ 434.0 RH_RF95 rf95(RFM95_CS, RFM95_INT); void setup() { Serial.begin(9600); // Перезагрузка LoRa модуля pinMode(RFM95_RST, OUTPUT); digitalWrite(RFM95_RST, LOW); delay(10); digitalWrite(RFM95_RST, HIGH); delay(10); //Инициализация LoRa модуля while (!rf95.init()) { Serial.println("LoRa radio init failed"); while (1); } //Устанавливаем частоту 434.0MHz if (!rf95.setFrequency(RF95_FREQ)) { Serial.println("setFrequency failed"); while (1); } rf95.setTxPower(18); //устанавливаем мощность передатчика } char value = 48; void loop() { Serial.print("Send: "); char radiopacket[1] = {char(value)}; rf95.send((uint8_t *)radiopacket, 1); delay(1000); value++; if (value > '9') value = 48; }
В бесконечном цикле главной функции отсылаем пакеты с данными методом rf95.send() . Данные могут быть любые, например, показания датчиков или пользовательские команды. В нашем примере просто отсылаются символьные значения от 0 до 9 с интервалом в 1 секунду.
Проверка работы
Загружаем программу в Arduino, включаем Raspberry Pi и запускаем на ней Python скрипт.
Если всё сделано верно, то в терминале должны начать выводиться принимаемые значения
В следующей статье рассмотрим построение базовой станции LoRaWan на основе Raspberry Pi и LoRa модуля SX1301/SX1308