LoRa通信モジュール
2026.05.27
今回は知人から資材提供を受けたLoRa通信モジュールを使ってみました。

LoRaモジュールは扱いが難しそうと思っている方にも簡単に遊ぶことができるように
クレアリンクテクノロジーさんから提供されているライブラリの機能を絞り込んでシンプルなライブラリに書き換えました。
ちなみにこのモジュールでは送受信を同時に行うことはできないので、テストには2台必要です。
●E220-900T22S(JP)-EV2(株式会社クレアリンクテクノロジー)

①E220-900T22S(JP)-R2 LoRaモジュール ②IPX u.FL端子 ③SMA端子
ボード自体は小さく、アンテナ端子を除けばブレッドボードに収まります。
●仕様
| 型名 |
E220-900T22S(JP)-EV2 |
| RFモジュール |
LoRa通信モジュール E220-900T22S(JP)-R2
|
| インターフェース |
UART
制御I/O(信号レベルは3.3 V TTL)、状態出力
|
| 動作電圧(上限は定格) |
3.1 ~ 5.5 V(Vcc給電時)
2.9 ~ 3.6 V(Vdd給電時)※
[低電圧モード使用時]
2.2 ~ 5.5 V(Vcc給電時)
2.1 ~ 3.6 V(Vdd給電時)※
|
| 動作温度範囲 |
-45~85℃ |
| 接続端子 |
ピンヘッダ
SMA端子 |
| 外形寸法 |
36 x 21 mm
※ SMA端子を含む場合:46 x 21 mm |
●LoRa用アンテナ

全長47㎜のLoRa用アンテナにSMA L型コネクタを取り付けています。卓上でテストする際に邪魔にならない長さです。
クレアリンクテクノロジーさんが提供しているLoRa用アンテナは全長195mmもあるので本番仕様といったところでしょう。
TX915-JKS-20
・種別:LoRa用アンテナ
・端子形状:SMA-P
・利得:3dB
・定在波比(SWR・VSWR):1.5
・設置方法:コネクターマウント
・サイズ:φ20mm × 195mm
データシートやオリジナルのライブラリは下記のリンクから取得できます
E220-900T22S(JP)データシート
Technical Datasheet
ESP32・Arduinoライブラリ&利用ガイド ver.2.0
ここでは、上記ライブラリをカスタマイズして使いましたが、元のソースの面影はほとんどありません。
固定長パケットによる通常送信にのみ機能を絞り込んでいます。
外部設定ファイルも必要ありません。
●カスタマイズ・ライブラリ(Sara Tsukiyono ver.)
E220_900T22S.zip
E220_900T22S.zip
┣ E220_900T22S.h
┣ E220_900T22S.cpp
┗ E220_900T22S.ino (テスト用コード)
●LoRaモジュールとマイコンとの配線
ESP32 と Raspberry Pi Pico との間で通信を行います。

左がESP32(Sparkfun ESP32 Thing Plus)、右がRaspberry Pi Pico(Groundstudio Marble Pico)です。
配線に合わせて、E220_900T22S.ino の最初の部分を編集します
#if defined(ARDUINO_ARCH_ESP32)
#define M0_PIN 32 // to LoRa Module M0
#define M1_PIN 33 // to LoRa Module M1
#define AUX_PIN 23 // to LoRa module AUX (not used)
#define RXD_PIN 16 // to LoRa module TX
#define TXD_PIN 17 // to LoRa module RX
#define MASTER_ADDRESS 64762 // address; 0 - 65535
#define SLAVE_ADDRESS 19042 // address; 0 - 65535
#elif defined (ARDUINO_ARCH_RP2040)
#define M0_PIN 10
#define M1_PIN 11
#define AUX_PIN 12
#define RXD_PIN 9
#define TXD_PIN 8
#define MASTER_ADDRESS 19042
#define SLAVE_ADDRESS 64762
#endif
#define BIND_CHANNEL 25 // channel: 0 - 30
#include "E220_900T22S.h"
E220_900T22S e220(M0_PIN,M1_PIN,AUX_PIN);
2台ともESP32を使用する場合には、2台目は、MASTERとSLAVEのアドレスを逆転させてビルドします
void setup() {
Serial.begin(115200);
// payload size 1X:197 2X:200
e220.setFirmwareVer(E220_FIRMWAREVER_2X);
e220.debug(&Serial);
#if defined(ARDUINO_ARCH_ESP32)
Serial2.begin(9600, SERIAL_8N1, RXD_PIN, TXD_PIN);
#elif defined (ARDUINO_ARCH_RP2040)
Serial2.setTX(TXD_PIN);
Serial2.setRX(RXD_PIN);
Serial2.begin(9600, SERIAL_8N1);
#endif
delay(800); // wait 800m sec
if (!e220.setConfig(&Serial2,SLAVE_ADDRESS,
MASTER_ADDRESS,BIND_CHANNEL)) while(1);
}
ペイロード(送信するデータの内容)サイズはファームウェアのバージョンによって異なります。
1X系は197バイト、2X系は200バイトです。
送受信パケットの内容をコンソールに表示したい場合は
e220.debug(&Serial);
を用います
ループ内に記述している送信処理の一例です
void send() {
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/ for example... /_/
//_/ send data entered from the console. /_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
if (Serial.available()) {
memset(&post,0x0,e220.packet_size);
// read from the console. termination CR+LF or LF
int len = 0;
while (len < e220.packet_size) {
if (Serial.available()) {
post.data[len] = Serial.read();
if (post.data[len] == 0x0a) {
post.data[len] = 0x0;
if ((len>0)&&(post.data[len-1]==0x0d)) post.data[len-1] = 0x0;
break;
}
len++;
}
delay(1);
}
e220.sendPacket(&post);
delay(1);
}
}
この例ではシリアル接続しているコンソールから文字入力して送信しています
E220_PACKET post, recv;
送受信用のパケットはE220_900T22S.hで定義しています
typedef struct {
uint16_t address;
uint8_t channel;
uint8_t data[200]; // actually 197 bytes
} E220_PACKET;
次に受信部分です
void receive() {
if(e220.receivePacket(&recv)) {
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/ custemized code here! /_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/
}
}
受信したデータは&recvに格納されているので、内容を取り出して処理するコードを記述します

ソースコードのビルドには、PlatformIOを使用しています。
Arduino開発環境構築 PlatformIO
ESP32、Picoの各々に接続しているRaspberry Piのデバイスモニタを起動します

(ESP32側デバイスモニタ表示)
setup()で e220.debug(&Serial)を記述した場合は、マイコン起動時にレジスタへの設定情報が表示されます。
ここで12345と入力して[ENTER]します。

宛先アドレスとチャンネル、パケット送信サイズに続いて、ペイロードの内容を表示してます。
送信側モジュールでは送信元アドレスを送信しないので、プログラム側でペイロード内に送信元アドレスを含めています。

(Pico側デバイスモニタ表示)
受信側Picoのコンソールです。
送信元アドレス、チャンネル、受信パケットサイズに続いてペイロードの内容が表示されます。
ペイロード内の最初の3バイトは送信元アドレスとチャンネルです。
今度は逆にPico側でabcdeと入力します

(Pico側デバイスモニタ表示)

(ESP32側デバイスモニタ表示)

パケット受信側でこのようなメッセージが表示されることがあります。
void receive() {
if(e220.receivePacket(&recv)) {
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/ custemized code here! /_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/
}
}
e220.receivePacket(&recv)は、falseを返し、
e220.err_no にエラーコード(E220_ERR_PACKET_IRREGULAR)がセットされます。
(E220_900T22S.cpp)
if (len < packet_size) {
err_no = E220_ERR_PACKET_IRREGULAR;
if (serialMon) serialMon->printf("PACKET IRREGULAR : %d bytes\n", len);
return false;
}
この際には受信側から送信側へパケット再送要求の制御を追加するか
(E220_900T22S.h)
#define E220_RECV_TIMEOUT (500) // timeout interval 500ms
のタイムアウト時間を長く設定してみてください。
同様の方法で、ファームウェアのバージョンがわからないときは、送信側を
(E220_900T22S.ino)
e220.setFirmwareVer(E220_FIRMWAREVER_2X);
受信側は
e220.setFirmwareVer(E220_FIRMWAREVER_1X);
に変更してビルド、実行してみてください。

受信側で上記の表示されれば、ファームウェアのバージョンは2Xです。
PACKET_IRREGULARなどが表示されればおそらく1X系です。
今回編集したライブラリではバージョン2X系のファームウェアに1X系を指定しても、パケットサイズは197バイトになりますが、
正常に動作するように配慮しています。
●ブロードキャスト送信
通常送信でもブロードキャスト風通信は可能です。
宛先の複数LoRaモジュールに同一アドレスを設定します。
ただし、これはマスター側からスレーブ側へ一方的にパケットを送信する場合です。
スレーブ側からのデータ収集を目的とした場合、一斉に返信が行われるので、返信データの取りこぼしが発生します。
スレーブに指示を与える場合は各スレーブモジュールに別々に送信しましょう。

LoRaモジュールのアドレスは(0~65535)、チャンネルは最低でも(0~30を指定できるので、
トランスペアレントモードにして送信先アドレスを無視して、複数モジュールの特定チャンネル宛に送信するよりも、
送信先モジュールに同一のアドレスを設定して、チャンネルを用途によって割り振り、アドレス指定で送信したほうが、
近隣で同一のモジュールを使用されている方から傍受される可能性が極端に低下すると思います。
●暗号化
このモジュールは暗号機能も実装していますが、独自にペイロード内を暗号化することをお勧めします。
●モジュールの最適化
モジュールをチューニングしたい方は下記の部分を編集してください
(E220_900T22S.cpp)
config.own_address = master; // 1 own_address 0 (<= 65535)
config.baud_rate = E220_BAUDRATE_9600; // 2 baud_rate 9600 bps
config.air_data_rate = E220_SF_VAL_9; // 3 air_data_rate (case SF:9 BW:125)
config.subpacket_size = E220_SUBPACKET_SIZE_200; // 4 subpacket_size 200
config.rssi_ambient_noise_flag = 0x01; // 5 rssi_ambient_noise_flag 0:invalid 1:valid
config.transmitting_power = E220_TRANSMITTING_POWER_13; // 6 transmitting_power 13 dBm
config.own_channel = channel; // 7 own_channel 0
config.rssi_byte_flag = 0x0; // 8 rssi_byte_flag 0:invalid 1:valid
config.transmission_method_type = E220_TRANSMISSION_METHOD_TYPE_1; // 9 transmission_method_type (Destination specification mode)
config.wor_cycle = E220_WOR_CYCLE_500; //10 wor_cycle 2000 ms
config.encryption_key = 0x0000; //11 encryption_key 0 (<= 65535)
config.target_address = slave; //12 target_address 0 (<= 65535)
config.target_channel = channel; //13 target_channel 0
config.strict_mode = 0b1; // strict_mode
config.Lowvoltage_operation = 0b0; // Lowvoltage_operation enable = 0
config.recv_target_address = 0b0; // recv_target_address disable
config.send_data_checksum = 0b0; // send_data_checksum disable
config.recv_data_checksum = 0b0; // recv_data_checksum disable
config.recv_data_packetsize = 0b0; // recv_data_packetsize disable
config.aux_low_holdtime = 0b10; // aux_low_holdtime 00 default:2-3msec
config.carriresense_timeout = 0x00; // carriresense_timeout 00 (default)
●カスタマイズ・ライブラリに関して
ライブラリは判読性を高めているので、不具合が発生した場合は適当に書き換えてください。
こちらで気付いた時には随時アップデートしておきます。
●補足
Arduino系への対応も試みたのですが、HardwareSerialで接続可能なLeonardo系(Serial1)で、デバッグ機能を削除して辛うじて動く感じなのでコードは掲載しません。
|