LoRa P2P 通信モードは、複数の LoRa デバイスを直接通信させることができます。このモードでは LoRa 変調技術をベースにデータパケットを送信し、フレーム内容を完全にカスタマイズして独自のプライベートネットワークを構築できます。リアルタイム性が求められ、通信範囲が比較的狭く、複雑なネットワーク管理が不要なシーンに適しています。
デバイスの実際の使用に合わせて通信パラメータを設定してください。設定が一致するデバイス同士でなければ通信できません。異なる Atom プロセッサを使用する場合は、以下のマクロを参照して適切な TX/RX ピンを指定してください。
#include <M5Unified.h>#include "rak3172_p2p.hpp" #define LORA_CONFIG_PRLEN 8#define LORA_CONFIG_PWR 22#define LORA_FREQ 868E6 // 868E6 equals to 868*10^6, which is the frequency 868M(Hz). It can be modified to 915 or 470 accordingly. #define LORA_CR 0 // (4/5=0, 4/6=1, 4/7=2, 4/8=3)#define LORA_SF 7 // (6, 7, 8, 9, 10, 11, 12)#define LORA_BW 500 // (125, 250, 500) #define ATOM_LORA_RX 19#define ATOM_LORA_TX 22 #define ATOMS3_LORA_RX 6#define ATOMS3_LORA_TX 5 RAK3172P2P lora; void LoRaLoopTask(void* arg) { while (1) { lora.update(); vTaskDelay(5); }} void setup() { M5.begin(); Serial.begin(115200); Serial.println("LoRa Init..."); // The second and third parameters in the next line should start with `ATOM` or `ATOMS3` according to the device actually used. while (!lora.init(&Serial2, ATOMS3_LORA_RX, ATOMS3_LORA_TX, RAK3172_BPS_115200)) { delay(1000); } lora.setMode(P2P_RX_MODE, 0); if (lora.config(LORA_FREQ, LORA_SF, LORA_BW, LORA_CR, LORA_CONFIG_PRLEN, LORA_CONFIG_PWR)) { Serial.println("LoRa config success"); } else { Serial.println("LoRa config failed"); } lora.setMode(P2P_TX_RX_MODE); xTaskCreate(LoRaLoopTask, "LoRaLoopTask", 1024 * 10, NULL, 2, NULL);} void loop() { M5.update(); if (M5.BtnA.wasPressed()) { if (lora.print("Hello!")) { Serial.println("Send success"); } } if (lora.available()) { std::vector<p2p_frame_t> frames = lora.read(); for (int i = 0; i < frames.size(); i++) { Serial.print("RSSI: "); Serial.print(frames[i].rssi); Serial.print(" SNR: "); Serial.print(frames[i].snr); Serial.print(" LEN: "); Serial.print(frames[i].len); Serial.print(" Payload: "); for (uint8_t j = 0; j < frames[i].len; j++) { Serial.printf("%02X", frames[i].payload[j]); } Serial.println(); } lora.flush(); }}
このサンプルをデバイスへ書き込んだ後、シリアルモニタでログを確認します。AtomS3R の中央ボタンを押すとデータが送信されます。
シリアルモニターで表示された "48656C6C6F21" は、"Hello!" のASCIIコードです。
LoRaWAN 通信モードでは、デバイスは LoRaWAN ゲートウェイを介してデータを送受信します。周波数ホッピング技術により、多数のデバイスノードを同時に管理でき、データのセキュリティも確保されます。使用前に、公共の LoRaWAN ゲートウェイが利用可能であることを確認してください。公共ゲートウェイがない場合は、自身でゲートウェイを構築することも可能です。
OTAA 入網では DevEUI、AppEUI、AppKey パラメータを使用します。
#include <M5Unified.h>#include "rak3172_lorawan.hpp" #define DEVEUI "****************"#define APPEUI "****************"#define APPKEY "********************************" // get or set the channel mask to close or open the channel (only for US915, AU915, CN470)#define CHANNEL_MASK "0000" #define ATOM_LORA_RX 19#define ATOM_LORA_TX 22 #define ATOMS3_LORA_RX 6#define ATOMS3_LORA_TX 5 RAK3172LoRaWAN lorawan;bool isJoin = false; void joinCallback(bool status){ isJoin = status; if (status) { Serial.println("[LoRaWAN] Join network successful!"); Serial.println("Device EUI: " + String(DEVEUI)); } else { Serial.println("[LoRaWAN] Join network failed!"); }} void sendCallback(){ Serial.println("[LoRaWAN] Uplink confirmed by server");} void errorCallback(char* error){ Serial.print("[LoRaWAN] Error: "); Serial.println(error);} void LoRaWANLoopTask(void* arg){ while (1) { lorawan.update(); vTaskDelay(5); }} void setup(){ M5.begin(); Serial.begin(115200); Serial.println("[Init] Initializing LoRaWAN module..."); while (!lorawan.init(&Serial2, ATOMS3_LORA_RX, ATOMS3_LORA_TX, RAK3172_BPS_115200)) { Serial.println("[Init] Failed to initialize module, retrying..."); delay(1000); } Serial.println("Device Init OK"); Serial.println("[Config] Setting band to EU868..."); while (!lorawan.setBAND(EU868, CHANNEL_MASK)) { Serial.println(" failed, retrying..."); delay(1000); } Serial.println("[Config] Setting OTAA parameters..."); while (!lorawan.setOTAA(DEVEUI, APPEUI, APPKEY)) { Serial.println(" failed, retrying..."); delay(1000); } Serial.println("[Config] Setting device mode to CLASS_C..."); while (!lorawan.setMode(CLASS_C)) { Serial.println(" failed, retrying..."); delay(1000); } Serial.println("[Config] Setting data rate to DR4..."); while (!lorawan.setDR(4)) { Serial.println(" failed, retrying..."); delay(1000); } Serial.println("[Config] Setting Link check..."); while (!lorawan.setLinkCheck(ALLWAYS_LINKCHECK)) { delay(1000); } lorawan.onSend(sendCallback); lorawan.onJoin(joinCallback); lorawan.onError(errorCallback); xTaskCreate(LoRaWANLoopTask, "LoRaWANLoopTask", 1024 * 10, NULL, 5, NULL); Serial.println("[Info] Attempting to join the network..."); if (lorawan.join(true, false, 10, 10)) { Serial.println("Start Join..."); } else { Serial.println("Join Fail"); }} void loop(){ M5.update(); if (M5.BtnA.wasReleased()) { if (isJoin) { String data = "UPlink LoRaWAN Frame: " + String(millis()); if (lorawan.send(data)) { Serial.println("Send Successful"); } else { Serial.println("Send fail"); } } else { Serial.println("LoRaWAN not joined"); } } if (lorawan.available()) { std::vector<lorawan_frame_t> frames = lorawan.read(); for (int i = 0; i < frames.size(); i++) { Serial.print("RSSI: "); Serial.println(frames[i].rssi); Serial.print("SNR: "); Serial.println(frames[i].snr); Serial.print("LEN: "); Serial.println(frames[i].len); Serial.print("PORT: "); Serial.println(frames[i].port); Serial.print("UNITCAST: "); Serial.println(frames[i].unicast); Serial.print("Payload: "); for (uint8_t j = 0; j < frames[i].len; j++) { Serial.printf("%02X", frames[i].payload[j]); } Serial.println(); } lorawan.flush(); } if (Serial.available()) { String ch = Serial.readString(); lorawan.sendCommand(ch); }}
このサンプルを書き込んだ後、シリアルモニタでログを確認します。Join 成功後、AtomS3R の中央ボタンを押してデータを送信します。
TTN の該当デバイスページで現在のアップリンク/ダウンリンクデータログを確認できます。
Messaging ページに切り替えると、ダウンリンクデータの送信が可能です。
ABP 入網では DevAddr、AppSkey、NwkSkey パラメータを使用します。Join プロセスは不要で、キー情報を初期化すればすぐにデータ送信を開始できます。
#include <M5Unified.h>#include "rak3172_lorawan.hpp" #define DEVADDR "***********" // Device Address#define APPSKEY "**********************" // Application Session Key#define NWKSKEY "**********************" // Network Session Key // get or set the channel mask to close or open the channel (only for US915, AU915, CN470)#define CHANNEL_MASK "0000" #define ATOM_LORA_RX 19#define ATOM_LORA_TX 22 #define ATOMS3_LORA_RX 6#define ATOMS3_LORA_TX 5 RAK3172LoRaWAN lorawan; void errorCallback(char* error){ Serial.print("[LoRaWAN] Error: "); Serial.println(error);} void LoRaWANLoopTask(void* arg){ while (1) { lorawan.update(); vTaskDelay(5); }} void setup(){ M5.begin(); Serial.begin(115200); Serial.println("[Init] Initializing LoRaWAN module..."); while (!lorawan.init(&Serial2, ATOMS3_LORA_RX, ATOMS3_LORA_TX, RAK3172_BPS_115200)) { Serial.println("[Init] Failed to initialize module, retrying..."); delay(1000); } Serial.println("Device Init OK"); Serial.println("[Config] Setting band to EU868..."); while (!lorawan.setBAND(EU868, CHANNEL_MASK)) { Serial.println(" failed, retrying..."); delay(1000); } Serial.println("[Config] Setting ABP parameters..."); while (!lorawan.setABP(DEVADDR, NWKSKEY, APPSKEY)) { Serial.println(" failed, retrying..."); delay(1000); } Serial.println("[Config] Setting device mode to CLASS_C..."); while (!lorawan.setMode(CLASS_C)) { Serial.println(" failed, retrying..."); delay(1000); } Serial.println("[Config] Setting data rate to DR4..."); while (!lorawan.setDR(4)) { Serial.println(" failed, retrying..."); delay(1000); } Serial.println("[Config] Setting Link check..."); while (!lorawan.setLinkCheck(ALLWAYS_LINKCHECK)) { delay(1000); } lorawan.onError(errorCallback); xTaskCreate(LoRaWANLoopTask, "LoRaWANLoopTask", 1024 * 10, NULL, 5, NULL);} void loop(){ M5.update(); if (M5.BtnA.wasReleased()) { String data = "UPlink LoRaWAN Frame: " + String(millis()); if (lorawan.send(data)) { Serial.println("Send Successful"); } else { Serial.println("Send fail"); } } if (lorawan.available()) { std::vector<lorawan_frame_t> frames = lorawan.read(); for (int i = 0; i < frames.size(); i++) { Serial.print("RSSI: "); Serial.println(frames[i].rssi); Serial.print("SNR: "); Serial.println(frames[i].snr); Serial.print("LEN: "); Serial.println(frames[i].len); Serial.print("PORT: "); Serial.println(frames[i].port); Serial.print("UNITCAST: "); Serial.println(frames[i].unicast); Serial.print("Payload: "); for (uint8_t j = 0; j < frames[i].len; j++) { Serial.printf("%02X", frames[i].payload[j]); } Serial.println(); } lorawan.flush(); } if (Serial.available()) { String ch = Serial.readString(); lorawan.sendCommand(ch); }}
CayenneLPP は最適化されたセンサーデータフォーマットです。TTN や Chirpstack にデータをアップロードする際、コンソールや API で取得できるデフォルトのデータは通常 Base64 でエンコードされており、可読性に欠けます。CayenneLPP はさまざまな基本センサータイプをサポートし、LoRaWAN ネットワークを利用した環境データ収集時に解析しやすいフォーマットを提供します。そのため、関連データの処理には CayenneLPP の使用を推奨します。コンソールのノード設定ページで CayenneLPP デコーダを選択するだけで、センサーデータを直感的に確認できます。詳細やサンプルについては以下をご参照ください。