alexandre_frolov
alexandre_frolov
9348 просмотров2 комментариев

Дальняя радиосвязь с LoRa на одноплатных микрокомпьютерах Repka Pi

Содержание


Если вы занимаетесь сбором данных на обширной территории, да еще не охваченной интернетом, возникает задача передачи данных на расстояния, исчисляемые километрами без использования WiFi и сети Ethernet.

В решении этой задачи вам помогут радиомодули, передающие данные с использованием технологии связи на большие расстояния (Long Range, LoRa). Эта технология запатентована компанией Semtech и реализована в микросхемах приемо-передатчиков (трансиверов), таких как SX1268, SX1276, SX1278.

В зависимости от выходной мощности передатчика, типа антенны, рабочей частоты, наличия прямой видимости или препятствий для прохождения радиоволн в виде домов, леса, помех со стороны других источников радиоизлучения и других факторов дальность может составлять от сотен метров до десятков километров.

К сожалению, скорость передачи данных LoRa невелика, порядка 2400-19200 бит/c.  Однако этого достаточно, например, для систем телеметрии и удаленного контроля, систем умного дома или других подобных систем.

Изучите законодательство #

В законодательстве есть ограничения по используемым частотам, уровням мощности и времени передачи. Найдите перечень и условия использования безлицензионных диапазонов частот (Industrial, Scientific, Medical, ISM) для использования протокола LoRa в вашей стране.

В России правила использования радиочастотного спектра устанавливаются Государственной комиссией по радиочастотам (ГКРЧ). Подробнее об использовании безлицензионных частот можно почитать здесь.

На момент написания этой статьи в России к безлицензионным диапазонам частот отнесены 433 МГц, 868 МГц, 2400 МГц и 5725 МГц.

Для создания сетей интернета вещей в России используют диапазон частот от 864 МГц до 869 МГц с мощностью до 25 мВт. При этом выделяются поддиапазоны от 864,0 МГц до 865,0 МГц и 868,7 МГц до 869,2 МГц. В первом из этих поддиапазонов действуют дополнительные ограничения: период активной работы может составлять не более 0,1%, и не разрешается работать вблизи аэропортов. У второго поддиапазона таких ограничений нет.

Законодательство постоянно изменяется, поэтому его необходимо отслеживать.

Особенности протокола LoRa #

Метод модуляции LoRa использует технику расширения спектра (spread spectrum modulation) и вариацию линейной частотной модуляции (chirp spread spectrum, CSS). При этом данные кодируются широкополосными импульсами с частотой, изменяющейся на некотором временном интервале. Также применяется прямая коррекция ошибок (forward error correction, FEC).

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

Радиомодули LoRa компании EBYTE #

В этой статье мы будем подключать к Repka Pi и Raspberry Pi модули LoRa производства компании EBYTE с интерфейсом UART.  Описание модулей можно найти здесь. Кроме того, один из периферийных узлов будет сделан на базе микрокомпьютера Micro:bit.

Модули LoRa и антенны к ним можно купить на Алиэкспресс. В табл. 1 перечислены некоторые модули производства EBYTE с интерфейсом UART, рассчитанные на разные частотные диапазоны и мощность.

Табл. 1. Модули EBYTE с технологией LoRa

Мощность модулей может регулироваться в пределах, указанных в табл. 1. Выбирая частотный диапазон и мощность, сверяйтесь с законодательством в области распределения частот для LoRa вашей страны. Есть также способы увеличения дальности без увеличения мощности передатчика. Это  использование антенн с большим усилением, направленных антенн и ретрансляторов.

Заметим, что компания EBYTE выпускает модули LoRa с термокомпенсированным кварцем (TCXO), что улучшает качество связи в уличных условиях.

Перечисленные в табл. 1 модули производства EBYTE очень легко установить на макетную плату, но есть SMD-модули.

На модуле EBYTE имеется семь контактов: M0, M1, RXD, TXD, AUX, VCC и GND, а также разъем антенны (рис. 1).

Рис 1. Модуль LoRa E32 433T30D

Контакт GND нужно объединить с землей микрокомпьютера Repka Pi.

На контакт VCC следует подать питающее напряжение. Согласно документации, напряжение питания должно лежать в диапазоне от 3,3 В до 5,2 В. Если максимальная мощность не нужна,  используйте источник питания 3,3 В.

Контакты RXD и TXD предназначены, соответственно, для приема и передачи данных с помощью протокола UART. Их нужно подключить к соответствующим контактам GPIO Repka Pi.

Аналогично, к GPIO подключаются контакты M0, M1 и AUX.

Первые два из них задают режим работы радиомодуля, например, режим установки параметров (конфигурирования), режим обычной работы, режим сохранения мощности и, наконец, режим автоматического перехода из режима сохранения мощности в активный режим при получении данных по радиоканалу.

Для изменения параметров модуля на выводы M0 и M1 нужно подавать напряжение 3,3 В, что соответствует логической единице. В режиме передачи данных на эти выводы нужно подать нулевое напряжение.

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

Выберите правильную антенну #

Включение радиомодуля на передачу без антенны может привести к его выходу из строя. Используйте антенны правильного типа, специально предназначенные для работы с вашими модулями и на нужной вам частоте.

Для подбора антенны найдите нужный модуль по названию на этом сайте , а затем щелкните кнопку Manual. Изучите в документации раздел Antenna recommendation.

Выбирая антенну, учитывайте ее тип, размеры, рабочую частоту, а также такой параметр, как усиление Gain, измеряемое в децибелах. Чем выше усиление антенны выше, тем будет дальше устойчивая связь при одинаковой выходной мощности передатчика.

Также важен тип интерфейса антенны. Чтобы вы смогли подключить антенну непосредственно к модулям, перечисленным в табл. 1, у нее должен быть интерфейс SMA-J.

В табл. 2 для примера мы привели список совместимых типов антенн для разных модулей EBYTE.

Табл. 2. Антенны для радиомодулей EBYTE с технологией LoRa

Антенну следует располагать вдали от стен и металлических поверхностей. Чем больше высота ее установки, тем больше дальность радиосвязи при прочих равных условиях. Лучше всего подключать антенну непосредственно к антенному разъему радиомодуля, так как промежуточный соединительный кабель ослабит радиосигнал. Это отрицательно скажется на дальности связи.

Конфигурирование модулей EBYTE LoRa #

Прежде чем использовать модули EBYTE, их нужно правильно сконфигурировать. В частности,  следует установить режим передачи данных (прозрачный или фиксированный), частоту (номер канала) и выходную мощность передатчика, а также другие параметры.

В репозитории вы найдете программы get-e32-config.py и set-e32-config.py. Первая из этих программ выводит на консоль байты текущей конфигурации радиомодуля, а вторая позволяет изменить конфигурацию.

Работа программы get-e32-config.py основана на отправке модулю E32 через UART команды чтения конфигурации в виде трех байт 0xC1. В ответ программа получает от радиомодуля шесть байт ответа, и после раскодирования выводит конфигурацию на консоль:

# python3 get-e32-config.py
Работает на платформе: Repka-Pi

Конфигурация модуля E32:                        0xc0000d1a0fc7
Сохраняем параметры при выключении питания:     0xc0
Нужен подтягивающий резистор для UART:          1
Таймаут в режиме сохранения энергии:            0
Адрес:                  0x000d
Режим UART:             0x0
Скорость UART:          0x3
Скорость радиоканала:   0x2
Номер радиоканала:      0x1a
Режим Fixed:            1
Включен режим FEC:      1
Выходная мощность:      3

Аналогично при запуске на Raspberry Pi:

# python3 get-e32-config.py
Работает на платформе: Raspberry Pi

Конфигурация модуля E32:                        0xc0000b1a0fc7
Сохраняем параметры при выключении питания:     0xc0
Нужен подтягивающий резистор для UART:          1
Таймаут в режиме сохранения энергии:            0
Адрес:                  0x000b
Режим UART:             0x0
Скорость UART:          0x3
Скорость радиоканала:   0x2
Номер радиоканала:      0x1a
Режим Fixed:            1
Включен режим FEC:      1
Выходная мощность:      3

Далее мы расскажем об этих программах подробнее, а сейчас расскажем о том, как закодированы байты конфигурации.

Байты конфигурации модуля EBYTE E32 #

Описание байтов конфигурации радиомодуля EBYTE E32 приведено в табл. 3.

Табл. 3. Кодирование байтов конфигурации E32

Сохранение конфигурации при выключении питания модуля #

Первый байт с номером 0 полученной конфигурации может содержать значения 0xC0 и 0xC2. В первом случае конфигурация модуля сохраняется при выключении его питания, а во втором — нет.

Адрес радиомодуля #

Каждому модулю можно назначить свой адрес в диапазоне от 0 до 65535. По умолчанию установлен адрес, равный 0. Адрес 65535 используется для широковещательной рассылки данных по всем адресам, а также в так называемом режиме мониторинга адресов.

Можно отправлять данные только модулям, сконфигурированным на определенный адрес, или всем модулям сразу независимо от их адреса (при отправке на широковещательный адрес 65535).

Номер канала передачи данных #

Параметр номера канала передачи данных задает частоту, на которой радиомодуль будет вести передачу. Частота вычисляется по формуле, которая зависит от типа модуля (табл. 4).

Табл. 4. Вычисление рабочей частоты по номеру канала

С помощью конфигурирования номеров каналов установите рабочую частоту модуля, разрешенную для использования протокола LoRa в вашей стране. Например, для модулей E32-868T20D и E32-868T30D можно установить частоту 869 МГц, если задать номер канала, равный 7 (862+7=869).

Режимы работы модуля #

Пятый байт конфигурации позволяет задавать дополнительные параметры конфигурации.

С помощью бита 7 этого байта можно установить несколько режимов работы модуля:

  • прозрачная передача (transparent transmission);
  • фиксированная передача (fixed transmission);
  • фиксированная широковещательная трансляция (fixed transmission broadcast);
  • режим мониторинга фиксированной передачи (fixed transmission monitoring)

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

На рис. 2 изображены четыре модуля с нулевым адресом. При этом модули A, B и C сконфигурированы для использования канала с номером 15, а модуль D — канала с номером 5.

Рис. 2. Режим прозрачной передачи

В режиме прозрачной передачи модули A, B и С могут взаимодействовать между собой, но модуль D, работающий на другом канале, будет недоступен.

Режим фиксированной передачи интереснее в плане адресации модулей. В этом режиме передающий модуль может без изменения своей конфигурации передавать данные принимающему модулю с любым адресом и на любом канале (рис. 3).

Рис. 3. Режим фиксированной передачи

Как видно из рис. 3, модуль A получает вместе с данными адрес назначения (равный 2) и номер канала (равный 4), на котором нужно вести передачу. Только модуль B сможет принять эти данные, так как именно он имеет адрес, равный 2, и работает на канале с номером 4.

Модули C и D не примут данные. У первого из них адрес задан как 3, а второй работает не на четвертом, а на пятом канале.

В режиме фиксированной широковещательной трансляции данные будут приняты всеми модулями, работающими на заданном канале, независимо от их адреса. Для этого при отправке данных нужно указать специальный адрес 65535, а также номер канала, на котором будет происходить передача (рис. 4).

Рис. 4. Режим широковещательной передачи данных

Здесь передача идет на четвертом канале, поэтому данные будут приняты модулями B и С. Модуль D не примет данные — он сконфигурирован для работы на пятом канале.

Еще один режим, в который можно перевести модуль, называется мониторингом фиксированной передачи. В этом режиме можно настроить модуль так, чтобы он принимал все пакеты, отправленные другими модулями, на заданном канале. Для этого нужно задать для принимающего модуля адрес 65535 и канал, на котором должен выполняться контроль.

Формат данных UART #

Байт с номером 3 (табл. 3) задает формат данных для UART, а также скорость передачи данных по радиоканалу.

Биты 7 и 6 этого байта определяют режим работы порта UART:

  • 00 — 8N1 (используется по умолчанию);
  • 01 — 8O1;
  • 10 — 8E1;
  • 11 — 8N1 (то же самое, что и 00)

Режим 8N1 означает, что пакет данных содержит 8 бит, нет служебного бита проверки четности, используется один стоп-бит в конце пакета.

Режим 8O1 аналогичен предыдущему, но используется контроль по нечетности. В режиме 8E1 то же самое, но применяется контроль по четности.

Скорость передачи данных UART #

Биты 5, 4 и 3 третьего байта конфигурации задают скорость передачи данных в bps:

  • 000 — 1200;
  • 001 — 2400;
  • 010 — 4800;
  • 011 — 9600 (по умолчанию);
  • 100 — 19200;
  • 101 — 38400;
  • 110 — 57600;
  • 111 — 115200

Скорость передачи данных по радиоканалу #

Биты 2, 1 и 0 байта конфигурации с номером 3 задают скорость передачи данных по радиоканалу:

  • 000 — 300;
  • 001 — 1200;
  • 010 — 2400 (по умолчанию);
  • 011 — 4800;
  • 100 — 9600;
  • 101 — 19200;
  • 110 — 19200;
  • 111 — 19200

Протокол LoRa не позволяет передавать данные с большой скоростью, поэтому нет особого смысла устанавливать высокую скорость для протокола UART. Что касается скорости передачи данных по радиоканалу, то, чем она ниже, тем больше дальность устойчивой радиосвязи. С учетом этих обстоятельств вы можете оставить параметры скорости передачи данных UART и через радиоканал (эфир) установленными по умолчанию.

Выходная мощность и другие параметры #

Байт конфигурации номером 5 (то есть последний, шестой байт по счету) сдержит значения множества различных параметров.

Очень важно правильно установить биты 1 и 0 этого байта конфигурации, так как они определяют выходную мощность передатчика радиомодуля.

Для модулей E32-915T30D, E32-868T30D или E32-433T30D мощность задается так:

  • 00 — 30 dBm или 1 Вт (установлена по умолчанию)
  • 01 — 27 dBm или 501 мВт
  • 10 — 24 dBm или 251 мВт
  • 11 — 21 dBm или 126 мВт

Если у вас модули E32-915T20D, E32-868T20D или E32-433T20D, то мощность будет ниже:

  • 00 — 20 dBm или 100 мВт (установлена по умолчанию)
  • 01 — 17 dBm или 50 мВт
  • 10 — 14 dBm или 25 мВт
  • 11 — 10 dBm или 10 мВт

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

Стенд с EBYTE E32 LoRa и Repka Pi #

Для конфигурирования модулей E32 и их совместного использования с микрокомпьютером Repka Pi соберем стенд, показанный на рис. 5.

Рис. 5. Подключение модуля LoRa E32 к микрокомпьютеру Repka Pi

На рис. 6 показана схема подключения контактов радиомодуля E32 к порту GPIO микрокомпьютера Repka Pi. Для Raspberry Pi нужно точно такое же подключение.

Рис. 6. Подключение контактов E32 к порту GPIO Repka Pi

Обратите внимание, что питание на модуль E32 подается отдельно, что особенно важно при высоком уровне мощности передатчика. В макете мы использовали понижающий стабилизатор напряжения на базе AMS1117, но подойдет любой аналогичный.

Выводы M0 и M1 модуля E32 подключены к контактам 13 (PA9) и 15 (PA10) платы Repka PI, соответственно. Напомним, что эти выводы задают режимы работы модуля.

Линии приема данных модуля RXD и передачи данных TXD нужно подключить к контактам 8 и 10 платы Repka PI, соответственно. Контакт 8 соответствует UART0-TX, а контакт 10 — UART0-RX микрокомпьютера. То есть RXD модуля подключается к UART0-TX микрокомпьютера, а TXD модуля — к UART0-RX микрокомпьютера.

И, наконец, контакт AUX модуля E32 нужно подключить к контакту 12 (PA6) микрокомпьютера Repka Pi. Напомним, что когда модуль E32 занят выполнением какой-либо операции, на нем устанавливается нулевое значение напряжения, а когда свободен — напряжение 3,3 В.

Программа чтения конфигурации радиомодулей #

Рассмотрим упомянутую выше программу чтения текущей конфигурации радиомодуля get-e32-config.py. Эта программа отправляет через UART модулю E32 команды чтения конфигурации в виде трех байт 0xC1. В ответ она получает шесть байт ответа, и после раскодирования выводит данные конфигурации на консоль.

Перед запуском программы необходимо установить библиотеку RepkaPi.GPIO, доступную на GitFlic, а также другие программы и библиотеки.

Установка библиотеки RepkaPi.GPIO выполняется следующим образом:

# apt-get update
# apt-get install python3-dev git
# git clone https://github.com/DikShv/RepkaPi3.GPIO.git
# cd RepkaPi3.GPIO
# apt-get install python3-setuptools
# python3 setup.py install

Далее клонируйте репозиторий repka-pi-lora:

# git clone https://github.com/AlexandreFrolov/repka-pi-lora.git

Установите python3-pip, pyserial и программу lm-sensors:

# apt install python3-pip
# pip3 install pyserial
# apt install lm-sensors

Если вы все сделали правильно, то при запуске в консоли программа get-e32-config.py выведет расшифрованные байты конфигурации:

# python3 get-e32-config.py
Работает на платформе: Repka-Pi

Конфигурация модуля E32:                        0xc0000d1a0fc7
Сохраняем параметры при выключении питания:     0xc0
Нужен подтягивающий резистор для UART:          1
Таймаут в режиме сохранения энергии:            0
Адрес:                  0x000d
Режим UART:             0x0
Скорость UART:          0x3
Скорость радиоканала:   0x2
Номер радиоканала:      0x1a
Режим Fixed:            1
Включен режим FEC:      1
Выходная мощность:      3

Исходный код программы чтения конфигурации можно загрузить из Github (листинг 1).

Листинг 1. https://raw.githubusercontent.com/AlexandreFrolov/repka-pi-lora/main/get-e32-config.py

В начале своей работы с помощью функции get_board_type программа определяет, на какой платформе ее запустили (Repka Pi или Raspberry Pi).

В зависимости от типа платформы для работы с GPIO подключаются библиотеки RepkaPi.GPIO или RPi.GPIO:

if board_type 'Repka-Pi':
    import RepkaPi.GPIO as GPIO
    GPIO.setboard(GPIO.REPKAPI3)
elif board_type 'Raspberry Pi':
    import RPi.GPIO as GPIO
print('Работает на платформе: ' + board_type + "\n")

Далее импортируются другие необходимые библиотеки и вызываются следующие функции:

ser = gpio_init()
received_data = e32_get_config()
print_e32_config(received_data)
gpio_cleanup()

Функция gpio_init инициализирует нужные нам линии GPIO. После этого функция e32_get_config читает текущую конфигурацию модуля E32, а затем выводит конфигурацию в расшифрованном виде при помощи функции print_e32_config.

Перед завершением работы вызывается функция gpio_cleanup для сброса порта GPIO.

В зависимости от платформы для работы с UART указывается устройство /dev/ttyS0 (Repka PI) или /dev/serial0 (Raspberry Pi):

if board_type == 'Repka-Pi':
    ser = serial.Serial("/dev/ttyS0", 9600, timeout=1)
elif board_type == 'Raspberry Pi':
    ser = serial.Serial("/dev/serial0", 9600, timeout=1)

Исходный код функции e32_get_config приведен ниже:

def e32_get_config():
    try :
     if ser.isOpen() :
      wait_for_aux_pin()
      ser.write(b'\xC1\xC1\xC1')
      sleep(1)
    except :
     if ser.isOpen() :
      ser.close()
      GPIO.cleanup()

    wait_for_aux_pin()
    if ser.inWaiting() > 0:
        wait_for_serial_data(ser)
        received_data = ser.read(6)
        sleep(1)
    return received_data

Функция вначале открывает устройство UART, создавая объект ser класса Serial. Далее функция проверяет, что модуль E32 готов принимать данные, вызывая для этого функцию wait_for_aux_pin.

Если модуль E32 не занят выполнением какой-либо операции, программа отправляет в него три байта команды чтения конфигурации b'\xC1\xC1\xC1'.

Далее функция e32_get_config снова ожидает готовность E32, дожидается, когда в буфере UART появятся данные, и затем читает шесть байт конфигурации.

Байты конфигурации передаются функции print_e32_config, которая извлекает отдельный поля с помощью операций сдвига и логического И.

Программа конфигурирования радиомодулей #

Программа конфигурирования радиомодулей E32 set-e32-config.py позволяет настроить конфигурацию, выбрав ее из заранее сформированного массива (листинг 2).

Листинг 2. https://raw.githubusercontent.com/AlexandreFrolov/repka-pi-lora/main/set-e32-config.py

Это удобно, если нужно подготовить несколько узлов, работающих в одном канале, но имеющих разные адреса.

Массив конфигураций указан следующим образом:

NODE_CFG = [b'\xC0\x00\x0B\x1A\x0F\xC7', # 1: Node 1, Address 0x0B
            b'\xC0\x00\x0C\x1A\x0F\xC7', # 2: Node 2, Address 0x0C
            b'\xC0\x00\x0D\x1A\x0F\xC7', # 3: Node 3, Address 0x0D
            b'\xC0\x00\x0E\x1A\x0F\xC7'] # 4: Node 4, Address 0x0E

При запуске нужно передать программе set-e32-config.py номер узла от 1 до 4. После запуска программа выведет на консоль байты новой конфигурации и запросит разрешение на внесение изменений:

# python3 set-e32-config.py 2
Node 2 set new config:
c0000c1a0fc7
Enter 'yes' to confirm: yes
Node 2 new config:
c0000c1a0fc7

Чтобы проверить, изменилась ли конфигурация, используйте описанную ранее программу get-e32-config.py.

Новая конфигурация устанавливается функцией set_config. Для записи в порт UART, подключенный к радиомодулю, выдается команда b'\xC1\xC1\xC1'.

Система сбора данных #

Теперь у нас есть все, чтобы создать систему сбора данных с обширных территорий. Мы соберем ее макет с применением радиомодулей E32, подключенных к микрокомпьютерам Repka Pi, Raspberry Pi и Micro:bit (рис. 7).

Рис. 7. Система сбора данных на базе Repka Pi

Система содержит четыре микрокомпьютера:

  • главный узел, Repka Pi, адрес E;
  • периферийный узел 1, Raspberry Pi, адрес B;
  • периферийный узел 2, Micro:bit, адрес С;
  • периферийный узел 3, RepkaPi, адрес D

Главный узел отправляет поочередно запросы на периферийные узлы и получает в ответ от этих узлов данные телеметрии. В макете, показанном на рис. 7, узел 1 возвращает температуру CPU микрокомпьютера, узел 2 — температуру окружающей среды, давление, влажность и точку росы, а узел 3 — температуру CPU и GPU на плате микрокомпьютера.

На главном узле запускается программа send-request-e32.py, отправляющая запрос. Адреса отправки запросов и ответы выводятся на консоль, а также записываются в файл hosts_data.json:

# python3 send-request-e32.py
Repka-Pi

Sended to :b'\x00\x0b\x0f'
Received: 46;0

Sended to :b'\x00\x0c\x0f'
Received: 27;983;0;7

Sended to :b'\x00\r\x0f'
Received: 39;42

{
  "0": {
    "Температура CPU": "46",
    "Температура GPU": "0"
  },
  "1": {
    "Температура": "27",
    "Давление": "983",
    "Влажность": "0",
    "Точка росы": "7"
  },
  "2": {
    "Температура CPU": "39",
    "Температура GPU": "42"
  }
}

Вы можете запускать эту программу периодически с помощью crontab, например, раз в 15 минут или с другим актуальным для вас интервалом времени.

Программа send-request-e32.py #

Исходный код программы send-request-e32.py, отправляющей запросы на периферийные узлы для получения телеметрии, приведен в листинге 3.

Листинг 3. https://raw.githubusercontent.com/AlexandreFrolov/repka-pi-lora/main/send-request-e32.py

После инициализации GPIO программа вызывает функцию get_nodes_data, которая получает данные телеметрии от периферийных узлов и сохраняет их в JSON-файле при помощи функции save_nodes_data_to_file:

ser = gpio_init()
nodes_dict = get_nodes_data(ser)
save_nodes_data_to_file(nodes_dict)

Функция get_nodes_data отправляет по очереди на все периферийные узлы команду получения телеметрии, вызывая send_cmd. Данные телеметрии форматируются для последующего преобразования в JSON при помощи функции format_node_data:

def get_nodes_data(ser):
    nodes_dict={}
    node_data0 = send_cmd(ser, b'\x00\x0B\x0F')
    node_data1 = send_cmd(ser, b'\x00\x0C\x0F')
    node_data2 = send_cmd(ser, b'\x00\x0D\x0F')

    nodes_dict[0] = format_node_data(0, node_data0)
    nodes_dict[1] = format_node_data(1, node_data1)
    nodes_dict[2] = format_node_data(2, node_data2)
    return nodes_dict

И, наконец, функция save_nodes_data_to_file преобразует данные в формат JSON, выводит их на консоль и записывает в файл:

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)

Функция send_cmd отправляет в радиомодуль сначала адрес периферийного модуля, а затем строку 'getData \n':

def send_cmd(ser, address):
    try :
        if ser.isOpen() :
            wait_for_aux_pin()
            ser.write(address)
            wait_for_aux_pin()
            ser.write('getData \n'.encode())
    except :
        if ser.isOpen() :
            ser.close()
            GPIO.cleanup()
    print('Sended to :' + str(address))
  
    wait_for_aux_pin()
    received_data = ser.readline()
    sleep(0.05)
    wait_for_aux_pin()
    data_left = ser.inWaiting()
    received_data += ser.read(data_left)
    rec = received_data.decode("utf-8").strip()
    print('Received: ' + received_data.decode('utf-8') + "\n")
    node_data = rec.split(';')
    return node_data

Данные от периферийных узлов приходят в виде строки значений, разделенных точкой с запятой. Эти данные декодируются и разделяются при помощи функции split, а затем сохраняются в файле при помощи функции save_nodes_data_to_file.

Функция format_node_data позволяет задать различный набор названий параметров для каждого узла.

Программа get-request-e32.py #

На периферийных узлах с микрокомпьютерами Repka Pi и Raspberry Pi запускается программа get-request-e32.py (листинг 4).

Листинг 4. https://raw.githubusercontent.com/AlexandreFrolov/repka-pi-lora/main/get-request-e32.py

Эта программа ожидает в цикле прихода от центрального узла нашей системы сбора данных команды в виде строки 'getData \n'. В ответ на эту команду программа получает данные телеметрии, а затем отправляет их на центральный узел по радиоканалу.

Цикл ожидания запускается после инициализации GPIO функцией wait_for_cmd:

ser = gpio_init()
wait_for_cmd(ser, b'\x00\x0E\x0F')

В качестве второго параметра этой функции передается адрес центрального узла, по которому нужно отправить ответ.

Цикл выглядит следующим образом:

while True:
    received_data = ser.readline()
    sleep(0.03)
    data_left = ser.inWaiting()
    received_data += ser.read(data_left)
    rec = received_data.decode("utf-8").strip()
    if received_data:
        print(rec)
    else:
        print('.', end='', flush=True)
       
   if 'getData' in rec:
       temperature_data = get_sensor_temperatures()
       print(temperature_data.encode())
       s_data = temperature_data.encode()
       if ser.isOpen() :
           wait_for_aux_pin()
           ser.write(address)
           wait_for_aux_pin()
           ser.write(s_data)
           print(s_data)

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

Если в декодированных данных содержится строка 'getData', программа получает температуру CPU и GPU (GPU только для Repka Pi) функцией get_sensor_temperatures. Далее программа выводит через UART в радиомодуль вначале адрес центрального узла, а затем закодированные данные.

Температура измеряется при помощи утилиты sensors, которую вы установили на периферийные узлы.

Программа для Micro:bit #

Один из периферийных узлов создан с использованием микрокомпьютера Micro:bit. Код программы для узла 1 приведет в листинге 5.

Листинг 5. https://raw.githubusercontent.com/AlexandreFrolov/repka-pi-lora/main/microbit-lora-net-host1.hex

Вы можете загрузить этот код в редактор Microsoft MakeCode, а потом записать на диск микрокомпьютера Micro:bit, подключенного через USB.

На рис. 8 показана первая часть программы microbit-lora-net-host1.hex.

Рис. 8. Программа microbit-lora-net-host1.hex (часть 1)

На этапе инициализации блок при начале  выводит на дисплей строку E32 Loranet Host 1, а затем инициализирует модуль E32, порт UART и погодную станцию BMP280. На светодиодную панель микрокомпьютера выводится цифра 1.

Блок on e32radio received получает управление при поступлении команды от центрального узла. Если эта команда содержит строку ‘getData’, блок E32 Send string отправляет по указанному адресу на центральный узел данные от погодной станции. Эти данные возвращает функция getWeatherData (рис. 9).

Рис. 9. Программа microbit-lora-net-host1.hex (часть 2)

Подробнее о работе с E32 с помощью Micro:bit вы можете прочитать в статьях:

Итоги #

Из нашей статьи вы узнали о том, как с помощью радиомодулей EBYTE E32 LoRa и микрокомпьютеров можно создать систему сбора данных на обширной территории, измеряемой километрами. Даже если там нет доступа к сети интернет.

Вы научились конфигурировать радиомодули и использовать их в фиксированном режиме, когда можно передавать данные на узлы по их адресам.

Важно, что система может быть построена с использованием разных микрокомпьютеров. Это может быть российский микрокомпьютер Repka Pi 3, а также микрокомпьютеры Raspberry Pi 3 и Micro:bit. Микрокомпьютеры других типов, в которых имеется порт UART и GPIO, также поддаются интеграции с EBYTE E32 LoRa.

Подключая к периферийным микрокомпьютерам через порты GPIO различные сенсоры и исполнительные устройства, можно собирать довольно сложные системы. А Repka Pi позволит вам создавать их на отечественных микрокомпьютерах.


Комментарии (2)

Для участия в обсуждении Вы должны быть авторизованным пользователем
Kogotok
Kogotok  

Спасибо, наглядно и понятно.
А были практические замеры по дистанции в городах, например в жилых районах при расположении на уровне 1 этажа, сколько такая конструкция по километражу пробивает застройку и сколько если поднять скажем на среднюю высоту, метров 30-40 (9-10 этажи)?

ntv  

Интересует ток потребления (мА) у LoRa в разных режимах - передачи, приёма, сна... пониженного потребления. Интересует эксплуатация с автономным (портативным) питанием на пром.площадках ~100х100 метров с передачей 2-4 информационных байт с частотой 1 раз в сек. Есть ли механизмы перевода LoRa в сон и выхода из сна (по прерыванию или иначе)? Требуется ли повторная конфигурация (инициализация) по сбросу питания? Скорость (время) выхода в режим передачи после подачи питания? Есть ли вариант работы без запросов, когда несколько беспроводных датчиков (10-50 шт с разными адресами) 1 раз в сек отправляют данные одному приёмнику? Гарантирована ли доставка приёмнику? Готов провести эксперименты (и поделиться результатами) с разумными токами потребления с портативным питанием; или внимательно получить совет использовать иные приёмо-передатчики. Привет и спасибо АнРя.

Темы

Навигация

ВойтиРегистрация