プライベート LoRa 通信でデータを送受信。

2024年10月26日

【 当サイトには広告リンクが含まれています。 】

プライベート LoRa 通信は、通信距離が従来の通信方式と比較して長い、LPWA(Low Power Wide Area「低消費電力広域通信」)規格の一つです。

実習では、ラズパイPicoWに接続したLoRa通信モジュール(E220-900T22S(JP))を親機と子機として2セット用意し、テキストデータを親子機器間で送受信しながら、現在時刻と電波強度(RSSI)を子機のOLEDディスプレイに表示します。

送受信の確認方法について

親機と子機の送信手順を次のように行います。

  1. 子機から親機に64バイトのテキストデータ(0123456789abcd・・・)を送信します。

  2. 親機は受信したデータが正しいかどうかを判定し、正しい場合はLEDを点灯させます。その後、内部で動作している時計の情報(現在時刻)と、電波強度(RSSI)を子機の送信します。

  3. 子機は受信した経過時間と電波強度(RSSI)の内容に応じて、LEDを点灯させます。受信したデータはOLED(有機ELディスプレイ)に表示した後、親機に先ほどそうした64バイトのテキストデータと異なったデータ(abcd・・・0123456789)を送信します。

  4. 親機は受信したデータが正しいかどうかを判定し、正しい場合はLEDを消灯させます。その後、内部で動作している時計の情報(現在時刻)と、電波強度(RSSI)を子機の送信します。

  5. 子機は受信した経過時間と電波強度(RSSI)の内容に応じて、LEDを消灯させます。受信したデータはOLED(有機ELディスプレイ)に表示した後、親機に最初に送信した64バイトのテキストデータと異なったデータ(0123456789abcd・・・)を送信します。

  6. 1~5を繰返します。



実験準備

実験に必要な環境や部品を準備します。

機器

「ラズパイPicoWを始めよう。」記事で書きました、MicroPythonファームウェアをインストールしたラズパイPicoWと、統合開発環境ThonnyをインストールしたRaspi4Bを準備します。

親機、子機の2セットが必要です。


使う部品

LoRaモジュールなど実験に使う部品を準備します。

部 品 名規 格数 量取扱い店(参考)
LoRa通信モジュール評価ボードE220-900T22S(JP)-EV12秋月電子通商
LoRa用アンテナTX915-JKS-202秋月電子通商
有機ELディスプレイ(OLED) 白色
(子機のみ使用)
SSD13061秋月電子通商
ブレッドボードBB-1022秋月電子通商
ジャンパーワイヤ14種類×10本1秋月電子通商


配線

準備した機器と部品を、配線リストと配線図を参考にして接続します。

配線リスト

次の配線を行います。

▶️親機の配線

FromTo
ラズパイPicoW(GND)LoRa通信モジュール(GND)
ラズパイPicoW(3V3)LoRa通信モジュール(VCC)
ラズパイPicoW(GP27)LoRa通信モジュール(M1)
ラズパイPicoW(GP26)LoRa通信モジュール(M0)
ラズパイPicoW(GP18)LoRa通信モジュール(AUX)
ラズパイPicoW(GP17)LoRa通信モジュール(TXD)
ラズパイPicoW(GP16)LoRa通信モジュール(RXD)


▶️子機の配線

親機の配線に、新たに有機ELディスプレイ(OLED) を追加して配線をします。

FromTo
ラズパイPicoW(GND)有機ELディスプレイ(GND)
ラズパイPicoW(3V3)有機ELディスプレイ(VCC)
ラズパイPicoW(GP21)有機ELディスプレイ(SCL)
ラズパイPicoW(GP20)有機ELディスプレイ(SDA)
ラズパイPicoW(GP28)ラズパイPicoW(GND)


配線図



データ送受信プログラムの実行

テキストデータを親子機器間で送受信しながら、現在時刻と電波強度(RSSI)が、継続的に子機のOLEDディスプレイに表示されることを確認します。

Raspi4BのThonnyを起動し、次のコードを「エディタ」に入力するか、リストをコピーしてペーストします。

▶️親機のコード


#LoRaモジュール 親機 (Raspberry Pi Pico W)

##################################################
#
#      モジュールの読み込み
#
##################################################

from machine import Pin
from machine import UART
import utime
import struct


##################################################
#
#      グローバル変数
#
##################################################

#RSSIバイト (1:有効、0:無効)
GLBL_RSSI_BYTE = 1

##################################################
#
#      モジュール自アドレス選択(下位アドレス)
#
##################################################

#1:0x00,0x00  0:0x00.0x01
LOW_ADRS_SEL = Pin(28, Pin.IN, Pin.PULL_UP)


##################################################
#
#      Pico W上のLED
#
##################################################

led = Pin("LED", Pin.OUT)


##################################################
#
#      モジュールのピン
#
##################################################

AUX = 18
M0 = 26
M1 = 27

TXD = 17 #(UART0 RX)
RXD = 16 #(UART0 TX)

#AUXピン
LR_AUX = Pin(AUX,Pin.IN)
#M0ピン
LR_M0 = Pin(M0,Pin.OUT)
#M1ピン
LR_M1 = Pin(M1,Pin.OUT)


##################################################
#
#      モジュールの初期設定
#
##################################################

def lora_initst():
    
    ######設定レジスタパラメータを設定######
          
    #Config/DeepSleepモード(mode 3)に設定
        
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)        
        
    LR_M0.value(1)
    LR_M1.value(1)
        
    #UART設定
    urt = UART(0, 9600, tx=Pin(RXD), rx=Pin(TXD))
    urt.init(9600, bits=8, parity=None, stop=1)
     
    #設定レジスタにパラメータを設定
    
    #書込コマンド(0xC0)、スタートアドレス(0x00)、書込数(0x08)
    CMD = [0xC0, 0x00, 0x08]
    
    #レジスタ-00(ADR_H):自デバイスの上位アドレス(0x00)
    ADR_H = 0x00
    CMD.append(ADR_H)
    
    
    #自アドレス選択(下位アドレス)
    if LOW_ADRS_SEL.value() == 1:  
        #レジスタ-01(ADR_L):デバイスの下位アドレス(0x00)    
        ADR_L = 0x00
        CMD.append(ADR_L)
    else:
        #レジスタ-01(ADR_L):デバイスの下位アドレス(0x01)  送信先アドレス  
        ADR_L = 0x01
        CMD.append(ADR_L)    
    
    
    #レジスタ-02(REG0):ボーレート(9600)、帯域幅設定(BW:125)、拡散率設定(SF:9)
    REG0 = 0x70
    CMD.append(REG0)    
    
    #レジスタ-03(REG1):ペイロード長(64byte)、RSSI環境ノイズ(無効)、未使用、送信出力(13dBm)
    REG1 = 0x81
    CMD.append(REG1)
    
    #レジスタ-04(REG2):自周波数チャンネル(0)
    REG2 = 0x00
    CMD.append(REG2)
    
    #レジスタ-05(REG3):RSSIバイト(有効)、 送信方法(通常 Fixed-block)、未使用、
    #低電圧動作(無効)、WORサイクル(3000ms)
    REG3 = 0xC5
    CMD.append(REG3)
    
    #レジスタ-06:暗号化キー上位バイト(0)
    ENCRYPT_H = 0x00
    CMD.append(ENCRYPT_H)    
    
    #レジスタ-07:暗号化キー下位バイト(0)
    ENCRYPT_L = 0x00
    CMD.append(ENCRYPT_L)
    
    #パラメータ設定値確認
    #print("パラメータの設定値")
    
    #設定値表示
    #disp = ""
    #for prm in CMD:
        #disp = disp + str(hex(prm)) + "/"
        #print(hex(prm))    
    #print(disp)
    
    #受信バッファクリア
    utime.sleep_ms(200)
    while urt.any() != 0 :
        urt.read()
          
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)
        
    #書込
    for val in CMD:    
        dat = struct.pack("B", val)
        urt.write(bytes(dat))
        #utime.sleep(0.002)

    utime.sleep_ms(1000)    
        
    
    ######設定レジスタパラメータを読出######

    
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)
        
    #Config/DeepSleepモード(mode 3)に設定
    LR_M0.value(1)
    LR_M1.value(1)
    
    utime.sleep_ms(200)
    
    #読出コマンド(0xC1)、スタートアドレス(0x00)、読出数(0x08)
    CMD = [0xC1, 0x00, 0x08]
    rspns = bytes()
    

    #モジュールにコマンドを書込

    #受信バッファクリア
    utime.sleep_ms(200)
    while urt.any() != 0 :
        urt.read()
          
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)

    #書込
    for val in CMD:   
        dat = struct.pack("B", val)
        urt.write(bytes(dat))
        #utime.sleep(0.002)

    utime.sleep_ms(1000)
    
        
    #パタメータを読込   
    while urt.any() != 0 :
        rspns = urt.read(urt.any())
     
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)
        
    LR_M0.value(0)
    LR_M1.value(0)
    
    return urt

##################################################
#
#      送信
#
##################################################

def lora_transmission(urt,txdt):
    
    #送信先上位アドレス(0x00)
    TX_ADR_H = 0x00

    #送信先アドレス選択(下位アドレス)
    if LOW_ADRS_SEL.value() == 1:  
        #送信先下位アドレス(0x01)    
        TX_ADR_L = 0x01
    else:
        #送信先下位アドレス(0x00)    
        TX_ADR_L = 0x00        
    
    #送信先チャンネル(0x01)    
    CHNL= 0x01

    #送信データにアドレスとチャンネルを設定 
    payload = bytes([TX_ADR_H, TX_ADR_L, CHNL])
    
    #テストデータを設定
    payload = payload + txdt.encode("utf-8")
      
    
    #受信バッファクリア
    utime.sleep_ms(200)
    while urt.any() != 0 :
        urt.read()
          
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)  
    
    #送信
    for dat in payload:
        bdat = struct.pack("B", dat)
        urt.write(bytes(bdat))
        
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)
         
    return
    
    
##################################################
#
#      受信
#
##################################################

def lora_receive(urt):
    #print("受信中...")
    payload = bytes()
           
    #データ受信待ち
    while LR_AUX.value() != 0:
        utime.sleep_ms(1)
        
    #受信開始待ち時間
    utime.sleep_ms(3)
    
    #RSSI初期化
    rssi = 0

    #受信開始待ち
    while True:                
        if urt.any() != 0:
            #受信データ読込
            payload = payload + urt.read()            
        elif urt.any() == 0 and len(payload) != 0:
            if GLBL_RSSI_BYTE ==1:
                #受信データ(RSSIバイト削除)
                rcv_dara = payload[:-1]
                
                #RSSIバイト有効
                rssi = int(payload[-1]) - 256
                #print("RSSI: {0} dBm".format(rssi))
                break
            else:
                #受信データ
                rcv_dara = payload
                
                
                #RSSIバイト無効
                #print("受信完了(RSSIバイト無効)")
                #print(payload) 
                break
    
    
    rcv_dara = rcv_dara.decode("utf-8")
    
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)
          
   
    return rcv_dara, rssi
    
    
##################################################
#
#      メイン
#
##################################################


#LED消灯
led.value(0)
    
#モジュールの初期設定
urt = lora_initst()

utime.sleep_ms(2000)


while True:
    #ローカル時刻設定
    lcl_tm= utime.localtime()      
    tm = ("%2d:%02d:%02d" % (lcl_tm[3:6]))
        
    #時刻表示
    #print("受信  "+ tm)
 
    #受信
    rcv_data, rssi = lora_receive(urt)
    #print(rcv_data)
    
    #送信データ
    txdt = tm + str(rssi)
      
        
    if rcv_data == "012345678abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ":
        #LED消灯
        led.value(1)
        lora_transmission(urt,txdt + "0")    
        
    if rcv_data == "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678":
        #LED点灯
        led.value(0)
        lora_transmission(urt,txdt + "1")


▶️子機のコード


事前に有機ELディスプレイ SSD1306(OLED)用のモジュール「ssd1306」をこちらからダウンロードして、ラズパイPicoWの「libフォルダ」に保存してください。



#LoRaモジュール 子機 (Raspberry Pi Pico W)

##################################################
#
#      モジュールの読み込み
#
##################################################

from machine import Pin
import utime

#LoRaモジュール通信用
from machine import UART
import struct

#有機ELディスプレイ SSD1306(OLED)用
from machine import I2C
from ssd1306 import SSD1306_I2C


##################################################
#
#      グローバル変数
#
##################################################

#RSSIバイト (1:有効、0:無効)
GLBL_RSSI_BYTE = 0

##################################################
#
#      モジュール自アドレス選択(下位アドレス)
#
##################################################

#1:0x00,0x00  0:0x00.0x01
LOW_ADRS_SEL = Pin(28, Pin.IN, Pin.PULL_UP)

##################################################
#
#      Pico W上のLED
#
##################################################

led = Pin('LED', Pin.OUT)


##################################################
#
#      有機ELディスプレイ SSD1306(OLED)設定
#
##################################################
   
#I2Cを利用するため、オブジェクト(i2c)を作成
i2c = I2C(0, scl=Pin(21), sda=Pin(20), freq=400000)
    
#OLEDを利用するため、オブジェクト(oled)を作成
oled = SSD1306_I2C(128, 64, i2c)


##################################################
#
#      モジュールのピン
#
##################################################

AUX = 18
M0 = 26
M1 = 27

TXD = 17 #(UART0 RX)
RXD = 16 #(UART0 TX)

#AUXピン
LR_AUX = Pin(AUX,Pin.IN)
#M0ピン
LR_M0 = Pin(M0,Pin.OUT)
#M1ピン
LR_M1 = Pin(M1,Pin.OUT)


##################################################
#
#      モジュールの初期設定
#
##################################################

def lora_initst():
    
    ######設定レジスタパラメータを設定######
          
    #Config/DeepSleepモード(mode 3)に設定
        
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)        
        
    LR_M0.value(1)
    LR_M1.value(1)
        
    #UART設定
    urt = UART(0, 9600, tx=Pin(RXD), rx=Pin(TXD))
    urt.init(9600, bits=8, parity=None, stop=1)
     
    #設定レジスタにパラメータを設定
    
    #書込コマンド(0xC0)、スタートアドレス(0x00)、書込数(0x08)
    CMD = [0xC0, 0x00, 0x08]
    
    #レジスタ-00(ADR_H):自デバイスの上位アドレス(0x00)
    ADR_H = 0x00
    CMD.append(ADR_H)
    
    
    #自アドレス選択(下位アドレス)
    if LOW_ADRS_SEL.value() == 1:  
        #レジスタ-01(ADR_L):デバイスの下位アドレス(0x00)    
        ADR_L = 0x00
        CMD.append(ADR_L)
    else:
        #レジスタ-01(ADR_L):デバイスの下位アドレス(0x01)  送信先アドレス  
        ADR_L = 0x01
        CMD.append(ADR_L)    
    
    
    #レジスタ-02(REG0):ボーレート(9600)、帯域幅設定(BW:125)、拡散率設定(SF:9)
    REG0 = 0x70
    CMD.append(REG0)    
    
    #レジスタ-03(REG1):ペイロード長(64byte)、RSSI環境ノイズ(無効)、未使用、送信出力(13dBm)
    REG1 = 0x81
    CMD.append(REG1)
    
    #レジスタ-04(REG2):自周波数チャンネル(1)
    REG2 = 0x01
    CMD.append(REG2)
    
    #レジスタ-05(REG3):RSSIバイト(有効)、 送信方法(通常 Fixed-block)、未使用、
    #低電圧動作(無効)、WORサイクル(3000ms)
    REG3 = 0x45
    CMD.append(REG3)
    
    #レジスタ-06:暗号化キー上位バイト(0)
    ENCRYPT_H = 0x00
    CMD.append(ENCRYPT_H)    
    
    #レジスタ-07:暗号化キー下位バイト(0)
    ENCRYPT_L = 0x00
    CMD.append(ENCRYPT_L)
    
    #パラメータ設定値確認
    #print("パラメータの設定値")
    
    #設定値表示
    #disp = ""
    #for prm in CMD:
        #disp = disp + str(hex(prm)) + "/"
        #print(hex(prm))    
    #print(disp)
    
    #受信バッファクリア
    utime.sleep_ms(200)
    while urt.any() != 0 :
        urt.read()
          
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)  

    #書込
    for val in CMD:    
        dat = struct.pack("B", val)
        urt.write(bytes(dat))
        #utime.sleep(0.002)

    utime.sleep_ms(1000)    
        
    
    ######設定レジスタパラメータを読出######

    
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)
        
    #Config/DeepSleepモード(mode 3)に設定
    LR_M0.value(1)
    LR_M1.value(1)
    
    utime.sleep_ms(200)
    
    #読出コマンド(0xC1)、スタートアドレス(0x00)、読出数(0x08)
    CMD = [0xC1, 0x00, 0x08]
    rspns = bytes()
    

    #モジュールにコマンドを書込

    #受信バッファクリア
    utime.sleep_ms(200)
    while urt.any() != 0 :
        urt.read()
          
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)

    #書込
    for val in CMD:          
        dat = struct.pack("B", val)
        urt.write(bytes(dat))

    utime.sleep_ms(1000)
    
        
    #パタメータを読込   
    while urt.any() != 0 :
        rspns = urt.read(urt.any())      
   
    #読込値表示
    #disp = ""
    #for prm in rspns:
        #disp = disp + str(hex(prm)) + "/"
        #print(hex(prm))    
    #print(disp)
        
    
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)
        
    #通常送受信モード(mode 0)に設定               
    LR_M0.value(0)
    LR_M1.value(0)
    
    return urt

##################################################
#
#      送信
#     (Pico W UART0 TX → 子機LoRa → 親機LoRa)
#
##################################################

def lora_transmission(urt,txdt):
    
    #送信先上位アドレス(0x00)
    TX_ADR_H = 0x00

    #送信先アドレス選択(下位アドレス)
    if LOW_ADRS_SEL.value() == 1:  
        #送信先下位アドレス(0x01)    
        TX_ADR_L = 0x01
    else:
        #送信先下位アドレス(0x00)    
        TX_ADR_L = 0x00        
    
    #送信先チャンネル(0x00)    
    CHNL= 0x00

    #送信データにアドレスとチャンネルを設定 
    payload = bytes([TX_ADR_H, TX_ADR_L, CHNL])
    
    #テストデータを設定
    payload = payload + txdt.encode("utf-8")
    
    #print("payload: {0}".format(payload))
    
    
    #受信バッファクリア
    utime.sleep_ms(200)
    while urt.any() != 0 :
        urt.read()
          
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)  
    
    #送信
    for dat in payload:
        bdat = struct.pack("B", dat)
        urt.write(bytes(bdat))
        #print(bdat)
        
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)     
    
    return
    
    
##################################################
#
#      受信
#     (親機LoRa → 子機LoRa → Pico W UART0 TX)
#
##################################################

def lora_receive(urt):
    #print("受信中...")
    payload = bytes()
        
    #データ受信待ち
    while LR_AUX.value() != 0:
        utime.sleep_ms(1)
        
    #受信開始待ち時間
    utime.sleep_ms(3)
    
    #RSSI初期化
    rssi = 0
      
    
    #受信開始待ち
    while True:                
        if urt.any() != 0:
            
            #受信データ読込
            payload = payload + urt.read()
            #print("MSG" + str(payload))
        elif urt.any() == 0 and len(payload) != 0:
            if GLBL_RSSI_BYTE ==1:
                #受信データ(RSSIバイト削除)
                rcv_data = payload[:-1]               
                
                #RSSIバイト有効
                rssi = int(payload[-1]) - 256
                print("RSSI: {0} dBm".format(rssi))
                break
            else:
                #受信データ
                rcv_data = payload               
                
                #RSSIバイト無効
                #print("受信完了(RSSIバイト無効)")
                #print(payload) 
                break
    
    #print(rcv_data)
    rcv_data = rcv_data.decode("utf-8") 
    
    #モジュールのアイドル状態確認
    while LR_AUX.value() == 0:
        utime.sleep_ms(1)
        
               
    return rcv_data, rssi

    
##################################################
#
#      メイン
#
##################################################

#LED消灯
led.value(0)

#SSD1306(OLED)消去
oled.fill(0)
oled.show()


#モジュールの初期設定
urt = lora_initst()


#送信
lora_transmission(urt,"012345678abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
    

while True:
    
    #受信
    rcv_data, rssi = lora_receive(urt)
    #print(rcv_data)
    
    #時刻
    tm = rcv_data[:8]
    #RSSI
    rssi = rcv_data[8:-1]
    #応答フラグ
    resflg =rcv_data[-1]
    
    #SSD1306(OLED)表示
    oled.fill(0)   
    oled.write_text(tm, x=0, y=10, size=2)
    oled.write_text(rssi + "dBm", x=0, y=40, size=2)
    oled.show()    
    
    utime.sleep_ms(2000)
    
    #応答フラグ判定
    if resflg == "1":
        #LED点灯
        led.value(1)
        lora_transmission(urt,"012345678abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
        
    if  resflg == "0":
        #LED消灯
        led.value(0)
        lora_transmission(urt,"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678")              
    
    #utime.sleep_ms(2000)
   


親機のThonnyの「F5」キーを押して、データ送受信プログラムを実行し、数秒後、子機のThonnyの「F5」キーを押して、データ送受信プログラムを実行します。

親機、子機のLEDが数秒間隔で点滅し、子機のOLEDディスプレイに時刻と電波強度(RSSI)が継続的に表示されます。



確認後、Thonnyの「Ctrl + c」キーを押すと、処理が中断します。

Raspi4Bを接続せずに電池等で起動する場合を考え、親子機ともファイル名「main.py」で保存しました。

親機にRaspi4Bを接続せずに、電池等で起動させた場合は、現在時刻ではなく、「0:00:00」から始まる時刻を表示します。


LoRa通信モジュールの使い方

親子機、子機の2セットのLoRa通信モジュール(E220-900T22S(JP))を使って、テキストデータを送受信しながら、現在時刻と電波強度(RSSI)が、継続的に子機のOLEDディスプレイに表示されることを確認しました。

LoRa通信モジュール(以下 モジュール)を使ってプライベート LoRa 通信を行うための基本的な 使い方を簡単に見ていきます。

モジュールのデータシート、MicroPython用にライブラリについては、株式会社クレアリンクテクノロジー(DRAGON TORCH)のダウンロード・サポートよりダウンロードしてください。


モジュールの初期設定

モジュールの動作は、9バイトで構成される設定レジスタ(レジスタアドレス 0x00~0x08)を操作することで制御されます。

モジュールとラズパイPicoWはUART通信によりデータの送受信が行われ、設定レジスタへの書込み、読出しは、次のコマンドにより行われます。

  • レジスタ書込みコマンド:0xC1、レジスタ開始アドレス、書込み数

  • レジスタ読出しコマンド:0xC0、レジスタ開始アドレス、読出し数


設定レジスタにはモジュールのデバイスアドレス、データの伝送速度(ボーレート)、データの長さ(ペイロード長)、送信出力、周波数チャンネル、電波強度 (RSSI)通知の有無等を設定します。


▶️設定レジスタへの書込みコマンド

コマンド開始アドレス書込み数備 考
0xC00x000x08


▶️設定レジスタへの書込み内容

レジスタ
アドレス
項 目設 定 値
親 機子 機
0x00アドレスの上位バイト0x000x00
0x01アドレスの下位バイト0x000x01
0x02・ボーレート:9600bps
・帯域幅設定(BW):125
・拡散率設定(SF):9
0x700x70
0x03・ペイロード長:64byte
・RSSI環境ノイズ:無功
・送信出力:13dBm
0x810x81
0x04自身の周波数チャンネル0x000x01
0x05・RSSIバイト:親機=有効、子機=無効
・送信方法:通常(Fixed-block)
・低電圧動作:無功
・WORサイクル:3000ms
0xC50x45
0x06暗号化キー上位バイト0x000x00
0x07暗号化キー下位バイト0x000x00


▶️設定レジスタからの読出しコマンド

コマンド開始アドレス書込み数備 考
0xC10x000x08


設定レジスタへの書込み、設定レジスタからの読出しは、Config/DeepSleepモード(モジュールのM0、M1ピンをHigh)に設定し、UART通信で行います。

モジュールが何らか処理を行っている場合は、書込み、読出しはできませんので、モジュールのAUXピンをモニターし処理を行っていないことや、受信用バッファのデータ有無を確認する必要があります。

書込み、読出し後は、通常の送受信モードにするため、M0、M1ピンをLowに設定します。


送信

送信は送信先のアドレス(2バイト)、周波数チャンネル(1バイト)を実際のデータに付加して行いますので、実際のデータは設定したペイロード長(64バイト)から3バイト引いた61バイトになります。

▶️親機から子機への送信

子機の上位アドレス子機の下位アドレス子機の周波数チャンネル
0x000x010x01


▶️子機から親機への送信

親機の上位アドレス親機の下位アドレス親機の周波数チャンネル
0x000x000x00


送信は、通常の送受信モード(モジュールのM0、M1ピンをLow)に設定し、UART通信で行います。

モジュールが何らか処理を行っている場合は、送信はできませんので、モジュールのAUXピンをモニターし処理を行っていないことや、受信用バッファのデータ有無を確認する必要があります。


受信

受信は受信したアドレス(2バイト)、周波数チャンネル(1バイト)が、自身のアドレス、周波数チャンネルと一致した場合に処理されます。

親機はRSSIバイトが有効になっていますので、モジュールは受信データの最後にRSSIバイトを付与して、ラズパイPicoWにデータを送ります。

ラズパイPicoWは最後のバイトを抽出して、電波強度(RSSI)を計算します。

子機はRSSIバイトが無効になっていますので、電波強度(RSSI)の計算は必要ありません。

受信は、通常の送受信モード(モジュールのM0、M1ピンをLow)に設定し、UART通信で行います。

モジュールが何らか処理を行っていいる場合は、受信はできませんので、モジュールのAUXピンをモニターし処理を行っていないことを確認する必要があります。


まとめ

親機、子機の2セットのLoRa通信モジュール(E220-900T22S(JP))を使って、テキストデータを送受信しながら、現在時刻と電波強度(RSSI)が、継続的に子機のOLEDディスプレイに表示されることを確認しました。

LoRa通信モジュール(E220-900T22S(JP))で通信を行うための基礎的な設定と送信、受信の方法を学びました。

住宅地や農地で利用した場合の、通信距離や通信精度を確認することが今後の課題です。