Private LoRa通信を利用したIoTシステムを実装する〜エッジデバイス編〜
はじめに
前回までの記事で,Private LoRa通信モジュールを使ってセンサデータをゲートウェイに収集することができました.ただ,この状態だとセンサデータの終着点がゲートウェイのままになり,データを集めてもそのデータを保存しておくことや,利用してサービスを開発することはまだできていませんでした.
そこで,今回はせっかく集めたデータをしっかりデータベースに格納するところまでを実装していきます.ここまでできたら,Private LoRa通信を利用したスター型のセンサネットワークは構築できたと言っても良いと思います.
IoTシステムを実装手順
本記事をご覧いただいている皆さんのゴールは「Private LoRa通信を利用してセンサネットワークを構築し,IoTシステムを実装すること」です.
本記事のセンサデバイスには,前回と同様のSHT15搭載 温湿度センサモジュールを使用します.ホストマイコンに関しては今までの記事ではESP-WROOM-32を使用してきましたが,今回はAdafruit Metro M4を使ってみましょう.(もちろん今まで通りESP-WROOM-32を使用した場合でもセンサネットワークの構築はできると思います)
さて,本記事は以下の手順でセンサネットワークを構築していきます.ここで,データサーバの処理は2パターン用意して記事にする予定です.
-
【共通部分】
- 温湿度センサとAdafruit Metro M4とES920LR2でエッジデバイスを作成する
- エッジデバイスからPrivate LoRa通信ゲートウェイにデータを集約する
-
【パターン1】Apache + MySQLでセンサデータをデータベースに格納するPrivate LoRa通信ゲートウェイのEthernet通信設定を行うデータサーバがPrivate LoRa通信ゲートウェイから受け取ったデータをデータベースに格納する
-
【パターン2】Django + MySQLでセンサデータをデータベースに格納し,Webアプリケーション上に表示する
- Private LoRa通信ゲートウェイのEthernet通信設定を行う
- Django REST frameworkでセンサデータをPOSTできるようにする
- DjangoのWebアプリケーション上でセンサデータをプロットする
本記事では,上記の手順の【共通部分】について説明します.
エッジデバイスを作成する
さて,センサネットワークの構築の第一歩としてエッジデバイスを作成します.
今回,実装するエッジデバイスは温度,湿度をセンサから取得することができて,そのデータをPrivate LoRa通信モジュールを利用してゲートウェイに送信できるようなデバイスである想定です.
そこで,センサモジュールとしてSHT15搭載 温湿度センサモジュール,ホストマイコンとしてAdafruit Metro M4,通信モジュールとしてES920LR2を搭載したエッジデバイスを実装します.
0.用意したもの
ハードウェア
今回,実装のために以下のものを用意しました.
部品名 | 今回の記事での役割 |
---|---|
SHT15搭載 温湿度センサモジュール | センサデバイス |
Adafruit Metro M4 | ホストマイコン |
ES920LR2 | Private LoRa通信モジュール |
ユニバーサル基板 | 半田付けをすることで簡単な基板を実装できます |
ジャンプワイヤー | 回路を組むときに使います |
ブレッドボード | 回路を組むときに使います |
ソフトウェア
Adafruit Metro M4への書き込みはArduinoIDEを使用します.インストールが未完了の方はインストールをしておいてくださいね.
※今回の記事では「ArduinoIDE ver1.8.10」を使用しました
1.回路を組む
今回の記事ではAdafruit Metro M4をホストマイコンにしているので,SHT15搭載 温湿度センサモジュールとAdafruit Metro M4の通信,ES920LR2とAdafruit Metro M4の通信がそれぞれできるように回路を作ります.
ピンアサイン
本記事では,以下のピン同士を接続して回路を作成しました.
このときES920LR2のRESETBピンはプルアップが必要なので注意してください.
Adafruit Metro M4 ピン | SHT15搭載 温湿度センサモジュール ピン | ES920LR ピン |
---|---|---|
GND | GND | GND×2 |
3V3 | VCC | VCCRF, VCC |
10 | DATA | - |
11 | SCK | - |
A3 | - | UART_TX |
A1 | - | UART_RX |
8 | - | RESETB |
2.ファームウェアを書き込む
ボードマネージャーを追加する
Adafruit Metro M4の書き込みが初めてという方もいらっしゃると思います.そういう方はまず,Adafruit Metro M4に書き込みを行うためのボードマネージャーが必要になりますので,以下の手順で追加をお願いします.
Windowsをお使いの方の場合
- Arduino IDEを起動して,ウィンドウ左上の「ファイル」-「環境設定」をクリックします.
- 「追加のボードマネージャのURL」の隣のアイコンをクリックします.
- 以下のURLを「追加のボードマネージャのURL」の空欄に入力して,「OK」をクリックします.(このとき,すでに他のアドレスが入力されている場合,「;」でURLを区切って入力してください.)
https:/arduino-board-index/package_adafruit_index.json
- 「OK」をクリックします.
- 「ツール」-「ボード:」-「ボードマネージャ」をクリックします.
- 「検索をフィルタ…」に「adafruit samd」と入力すると,「Adafruit SAMD Boards by Adafruit」が表示されるので,「インストール」をクリックします.(ここで筆者の開発環境でのバージョンは1.5.14でした)
- インストールが行われるので,完了するまでしばらく待ちます.
- インストールが完了したら,「閉じる」をクリックして終了です.
Macをお使いの方の場合
- Arduino IDEを起動して,画面左上の「Arduino」-「Prefernces...」をクリックします.
- 「追加のボードマネージャのURL」の隣のアイコンをクリックします.
- 以下のURLを「追加のボードマネージャのURL」の空欄に入力して,「OK」をクリックします.(このとき,すでに他のアドレスが入力されている場合,「;」でURLを区切って入力してください.)
https:/arduino-board-index/package_adafruit_index.json
- 「OK」をクリックします.
- 「ツール」-「ボード:」-「ボードマネージャ」をクリックします.
- 「検索をフィルタ…」に「adafruit samd」と入力すると,「Adafruit SAMD Boards by Adafruit」が表示されるので,「インストール」をクリックします.(ここで筆者の開発環境でのバージョンは1.5.14でした)
- インストールが行われるので,完了するまでしばらく待ちます.
- インストールが完了したら,「閉じる」をクリックして終了です.
SHT1x-ESPライブラリを追加する
次に,SHT15搭載 温湿度センサモジュールの制御をするライブラリを追加します.
最後にESPと書いてあるので,ESP専用のライブラリなのかな?と思っていたのですが,Adafruit Metro M4でも同じライブラリが使えたので,これを利用します.(ライブラリを検索したときの文章をよく見ると「update to work with ESP32」って書いてあるので,Metroはもともといけたんですかね?)
Arduino IDEの「ツール」-「ライブラリの管理..」から「sht15」と検索し,以下のライブラリをインストールします.(ここで筆者の開発環境でのバージョンは1.0.2でした)
ファームウェアの書き込み
次はファームウェアの書き込みを行います.以下の手順を参考にAdafruit Metro M4へ書き込みを行ってください.
- Adafruit Metro M4とコンピュータを接続します.
- ArduinoIDEを開いて「ツール」-「ボード」から「Adafruit Metro M4」を選択します.
- 「ツール」-「シリアルポート」からAdafruit Metro M4が該当するポートを選択します.
- 「ファイル」-「新規ファイル」を選択して新しいファームウェアを作成します.
- 以下のソースコードをArduinoIDEのスケッチにコピペします.
ソースコード
//ライブラリ//////////
#include <Arduino.h>
#include "wiring_private.h"
#include <SHT1x-ESP.h> // SHT1x-ESPライブラリ(本記事ではver 1.0.2)
// SHT15搭載 温湿度センサモジュールとの通信定義 //////////
#define SHT15_DATA 10 // SHT15搭載 温湿度センサモジュールのDATAに接続します
#define SHT15_SCK 11 // SHT15搭載 温湿度センサモジュールのSCKに接続します
SHT1x sht15(SHT15_DATA, SHT15_SCK, SHT1x::Voltage::DC_3_3v); // SHT15搭載 温湿度センサモジュールとの通信を定義する
// ES920LR2との通信定義 //////////
static const int LoRaBPS = 115200; // ES920LR2とAdafruit Metro M4のUART通信の通信速度
#define LoRa_UART_TXD A3 // ES920LR2の8ピン(TX)に接続します
#define LoRa_UART_RXD A1 // ES920LR2の9ピン(RX)に接続します
#define LoRa_Rst 8 // ES920LR2の24ピン(RESETB)に接続します
Uart LoRa_ss (&sercom0, LoRa_UART_TXD, LoRa_UART_RXD, SERCOM_RX_PAD_1, UART_TX_PAD_0); // SERCOM機能でUART通信を定義する
// データ構造定義 //////////
struct TempHmdSensorData { // 温湿度センサデータ構造体
int temp; // 温度データ
int hmd; // 湿度データ
};
// その他の定義 //////////
#define DEBUG // デバッグモード
#define SETTING // Private LoRa通信設定更新モード
#define INTERVAL 10000 // 送信間隔(10秒)
#ifdef DEBUG
static const short int serialBPS = 115200; // シリアルモニタの通信速度
#endif
void setup() {
#ifdef DEBUG
delay(5000);
Serial.begin(serialBPS); // シリアルセットアップ(デバッグモードがONの場合)
Serial.println("Start!");
#endif
LoRa_begin(LoRaBPS); // ES920LR2起動&セットアップ
}
void loop() {
TempHmdSensorData data; // 温湿度センサデータの箱を用意
data.temp = int(sht15.readTemperatureC() * 100); // 小数点第二位までを誤差なく送信するために100をかける
data.hmd = int(sht15.readHumidity() * 100); // 小数点第二位までを誤差なく送信するために100をかける
char send_buff[25] = {'\0'}; // 送信用の文字列を定義する
sprintf(send_buff, "temp=%05d&hmd=%05d\r\n", data.temp, data.hmd); // 送信用文字列にセンサ値を代入する
LoRa_write(send_buff); // ES920LR2でES920GWX2へ送信する
delay(INTERVAL); // 送信間隔
}
// LoRaモジュールの起動とセットアップを行う関数
void LoRa_begin(int bps) {
#ifdef DEBUG
Serial.println("Begin to connect with LoRa Module...");
#endif
LoRa_ss.begin(bps); // UART通信開始
pinPeripheral(LoRa_UART_TXD, PIO_SERCOM_ALT);
pinPeripheral(LoRa_UART_RXD, PIO_SERCOM_ALT);
// Private LoRa通信モジュールをリセットするピンを定義
pinMode(LoRa_Rst, OUTPUT);
digitalWrite(LoRa_Rst, HIGH);
#ifdef SETTING
LoRa_setting(); // ES920LR2の通信設定変更を行う(Private LoRa通信設定更新モードがONの場合)
#endif
}
// LoRaモジュールの通信設定を変更する関数
void LoRa_setting() {
#ifdef DEBUG
Serial.println("Begin to setup LoRa Module...");
#endif
module_reset(LoRa_Rst); // ES920LR2を再起動
delay(1000);
LoRa_write(" \r\n");
LoRa_write("config\r\n");
delay(100);
LoRa_write("processor\r\n"); // ES920LR2のプロセッサーモードを選択します
delay(1000);
LoRa_write("load\r\n"); // ES920LR2の設定を全て初期設定に戻す
delay(100);
LoRa_write("protocol 2\r\n"); // 通信プロトコルを中継対応Private LoRaに設定
delay(100);
LoRa_write("node 1\r\n"); // デバイスを子機に設定
delay(100);
LoRa_write("bw 4\r\n"); // 帯域幅を125kHzに設定
delay(100);
LoRa_write("sf 7\r\n"); // 拡散率を7に設定
delay(100);
LoRa_write("channel 1\r\n"); // 無線チャンネル番号を1に設定
delay(100);
LoRa_write("panid ABCD\r\n"); // PANネットワークアドレスをABCDに設定
delay(100);
LoRa_write("ownid 1000\r\n"); // 自ノードのネットワークアドレスを1000に設定
delay(100);
LoRa_write("dstid 0000\r\n"); // 送信先ノードのネットワークアドレスを0000に設定
delay(100);
LoRa_write("hopcount 1\r\n"); // 中継数を1に設定
delay(100);
LoRa_write("endid 0000\r\n"); // 最終ノードネットワークアドレスを0000に設定
delay(100);
LoRa_write("aeskey 0123456789ABCDEF0123456789ABCDEF\r\n"); // 最終ノードネットワークアドレスを0000に設定
delay(100);
LoRa_write("save\r\n"); // 設定した内容を内蔵FlashROMに保存
delay(10000);
module_reset(LoRa_Rst); // ES920LR2を再起動
delay(1000);
LoRa_write("processor\r\n"); // ES920LR2のプロセッサーモードを選択します
delay(1000);
LoRa_write("start\r\n"); // ES920LR2をオペレーションモードに移行
delay(1000);
}
// Private LoRa通信モジュールからのメッセージを受信する関数
void LoRa_read() {
if (LoRa_ss.available())Serial.print("from LoRa >>");
while (LoRa_ss.available()) {
char c = LoRa_ss.read();
if (c < 0x80)Serial.write(c);
delay(1);
}
}
// Private LoRa通信モジュールへメッセージを送信する関数
void LoRa_write(char msg[]) {
LoRa_ss.write(msg);
#ifdef DEBUG
Serial.print("to LoRa >>");
Serial.print(msg);
#endif
delay(500);
LoRa_read();
}
// ピン番号を入力してモジュールをハードウェアリセットする関数
void module_reset(int Pin) {
digitalWrite(Pin, LOW);
delay(100);
digitalWrite(Pin, HIGH);
delay(1000);
}
// SERCOMのハンドラ
Stream *SERIALOUT = &LoRa_ss;
void SERCOM0_0_Handler()
{
LoRa_ss.IrqHandler();
}
void SERCOM0_1_Handler()
{
LoRa_ss.IrqHandler();
}
void SERCOM0_2_Handler()
{
LoRa_ss.IrqHandler();
}
void SERCOM0_3_Handler()
{
LoRa_ss.IrqHandler();
}
※このソースコードは以下を参考にしています.
- 書き込みボタンをクリックして書き込みを行います.
- 「ボードへの書き込みが完了しました.」と表示されたら,完了です.
3.動作確認と解説
上記の書き込み手順で書き込みを行うと,以下のような出力がされると思います.Private LoRa通信のレスポンスが「NG」と出ていますが,今は発信したデータを受信してくれるデバイスを用意してないので,現状は問題ありません.
Private LoRa通信設定についての解説
今回,Private LoRa通信設定を以下のように変更しました.
設定項目 | コマンド | 設定内容 |
---|---|---|
通信プロトコル設定 | protocol | 2 |
ノード種別設定 | node | 2 |
帯域幅 | bw | 125kHz |
拡散率 | sf | 7 |
無線チャンネル番号 | channel | 1 |
PANネットワークアドレス | panid | ABCD |
自ノードネットワークアドレス | ownid | 1000 |
送信先ノードネットワークアドレス | dstid | 0000 |
中継数設定 | hopcount | 1 |
最終ノードネットワークアドレス | endid | 0000 |
AES128 暗号化キー | aeskey | 0123456789ABCDEF0123456789ABCDEF |
これらのコマンドの中で,「protocol」,「node」,「hopcount」,「endid」,「aeskey」は初登場だと思いますのでそれぞれ説明を行います.
protocolコマンドはES920LR2で利用する通信プロトコルを選択するコマンドです.ES920LR2コマンド仕様ソフトウェア説明書にもあるように,このコマンドにより,ES920LR2では3つの通信プロトコルから切り替えが可能となっています.そして,今回はプライベートLoRa(中継対応)の通信プロトコルを選択しました.この通信プロトコルを選択した理由は,本記事で利用するPrivate LoRa通信ゲートウェイのES920GWX2がこの中継ありの通信プロトコルに対応している場合が多いためです.
nodeコマンドは対象のPrivate LoRa通信モジュールを搭載したデバイスがどのような役割で使用されるかを設定するコマンドです.今回の場合,ES920LR2を搭載しているデバイスはエッジデバイスとして利用されることを想定していますので,2.EndDeviceを選択しています.
hopcountとendidはどちらもプライベートLoRa(中継対応)の通信プロトコル専用のコマンドです.hopcountはPrivate LoRa通信の中継数,endidはPrivate LoRa通信ゲートウェイのEthernet通信設定を行う最終ネットワークアドレスを指します.それぞれを設定する際の考え方は以下の画像のようになっています.(これについてはまた機会があれば詳しく記事を書きます)
最後に,aeskeyはPrivate LoRa通信を暗号化するコマンドです.発信側と受信側で共通の鍵を持っていれば,Private LoRa通信をより安全に利用できるようになるので,積極的に使うべきコマンドであると思います.今回の暗号化キーは16進数を順番に並べただけの雑なものに設定をしましたが,みなさんが実際にIoTシステムを構築される際にはランダムな32桁の16進数で入力するようにしてください.
ファームウェアについての解説
今回のファームウェアでは,「デバッグモード」と「Private LoRa通信設定更新モード」というものを用意しました.これらは必須の機能ではないですが,実装するといいこともあります.
これらの機能を実装するメリットは,エッジデバイス運用時に不要な処理を削減できることにあります.
例えば,みなさんは今は手元にエッジデバイスがあり,このデバイスの動作確認をシリアルモニタで行っているので,シリアルを利用するかと思いますが,実際にIoTシステムを運用する際にはエッジデバイスがPCと接続されているような状況は少ないと思います.
なので,わざわざエッジデバイス側の処理結果をシリアル上に出力しても誰もみてくれないので,運用時は不要な機能となってしまします.
また,Private LoRa通信モジュールの通信設定変更に関しても,エッジデバイスが立ち上がる(電源が入れられる)度に行う必要はありません.最初の一回だけ設定の変更を行って保存しておけば,それで問題ないですよね.加えて,Private LoRa通信設定は「save」コマンドを入力する度にEEPROMに保存されるのですが,このメモリには書き込み回数の限度がありますので,不要な書き込みは避けることを推奨します.
以上のことから,エッジデバイスの動きを手元で確認したい場合は,デバッグモードをONにしてシリアルモニタで動作を確認して,運用時にはOFFにすることや,必要以上のPrivate LoRa通信設定変更を行わないなどの工夫がIoTシステム運用の上では大切です.
Private LoRaゲートウェイにデータを集約する
前章でエッジデバイスが完成しましたので,次はエッジデバイスが発信している温湿度センサデータを集めます.
今回の記事では,Private LoRa通信ゲートウェイとしてES920GWX2を使用します.
ターミナルエミュレータの準備
ES920GWX2のPrivate LoRa通信設定はターミナルエミュレータを利用して行うので,以下を参考にインストールとターミナルエミュレータの設定変更を行います.
Windowsをお使いの方の場合
Windows環境ではターミナルエミュレータとして,「Teraterm」を使用します.以下の記事を参考にインストールをお願い致します.
インストールが完了したら,以下の手順でTeratermの設定を変更します.
- ES920GWX2とPCをUSBケーブルで接続します.
- ES920GWX2の電源をONにします.(このとき電源供給を行うアダプタは純正のものを使用するようにしてください)
- Teratermを起動します.
- 「シリアル」からES920LRGWが接続されているポートを選択します.
- メニューバーの「設定」→「端末」を選択します.
- 「改行コード」にある「送信(M)」を「CR+LF」に変更し,ローカルエコーにチェックを入れます.
- メニューバーの「設定」→「シリアルポート」を選択します.
- 「スピード(E)」を「115200」に変更します.
- Teraterm内でEnterキーを入力し,「>COM」と出力されれば完了です.
Macをお使いの方の場合
Mac環境ではターミナルエミュレータとして「Coolterm」を使用します.以下の記事からインストールをお願い致します.
インストールが完了したら,以下の手順でCooltermの設定を変更します.
- ES920GWX2とPCをUSBケーブルで接続します.
- ES920GWX2の電源をONにします.(このとき電源供給を行うアダプタは純正のものを使用するようにしてください)
- Cooltermを起動します.
- メニューバーの「Connection」→「Options...」を選択します.
- 「Serial Port」の「Port」をES920LRGWが接続されているポートに接続し,「Baudrate」を「115200」に変更します.
- 「Terminal」の「Enter Key Emulation」が「CR+LF」になっていることを確認し,「Local Echo」にチェックを入れます.
- 「Connect」をクリックします.
- Coolterm内でEnterキーを入力し,「>COM」と出力されれば完了です.
ES920GWX2の設定を変更する
次はPrivate LoRa通信ゲートウェイであるES920GWX2の通信設定を変更します.
ES920GWX2には,Private LoRa通信モジュールが4つ搭載されており,それぞれModule1,Module2,Module3,Module4と名付けられています.
どのモジュールを使ってもPrivate LoRa通信が可能ですが,本記事では,Module1のみを使用することを考えます.
さて,ES920GWX2の設定変更を行います.準備は前章で完了しているので,まずはご使用のターミナルエミュレータで「show」コマンドを入力してみてください.すると以下のような画面が表示されます.(筆者はCooltermを使用してます)
ここで,Module1と書いてある部分の設定を見ると,PANIDやAES Keyなど本記事で作成したエッジデバイスとは異なるPrivate LoRa通信設定になっています.
そこで,ES920GWX2 取扱説明書を参考にしてコマンドを入力し,設定の変更を行います.以下の手順に沿って設定を変更してください.
- 「bw」コマンドを入力します.
- 「please set RF Module number (1 - 4) >」と聞かれるので「1」を入力します.(この手順は他の設定項目でも毎回選択します)
- 設定したい帯域幅を聞かれるので,「2. 125kHz」を選択するために「2」を入力します.
- 「sf」コマンドを入力します.
- 2.と同様の手順を行います.
- 設定したい拡散率として「7」を入力します.
- 「panid」コマンドを入力します.
- 2.と同様の手順を行います.
- 設定したいPANIDとして「ABCD」を入力します.
- 「ownid」コマンドを入力します.
- 2.と同様の手順を行います.
- 設定したいOWNIDとして「0000」を入力します.
- 「aeskey」コマンドを入力します.
- 2.と同様の手順を行います.
- 設定したい暗号化キーとして「0123456789ABCDEF0123456789ABCDEF」を入力します.
- 「save」コマンドを入力します.
- ES920GWX2の電源を入れ直します.
ここまでで,ES920GWX2の設定は完了です.「show」コマンドを入力してModule1の設定が以下のようになっていれば問題ありません.
Private LoRa通信疎通の確認
さて,以上でエッジデバイスから,Private LoRa通信を使ってゲートウェイに温湿度センサデータを送信できるようになったはずです.それぞれのデバイスからちゃんと通信がうまくいってるか確認してみます.
エッジデバイス側の様子
ゲートウェイ側の様子
上の画像のようにエッジデバイス側に搭載されているES920LR2から「OK」のレスポンスが返ってきており,ゲートウェイ側にデータが届いている様子が確認できました.
ここまでで,本記事の目的である以下の項目を達成しました.お疲れ様でした!
- 温湿度センサとAdafruit Metro M4とES920LR2でエッジデバイスを作成する
- エッジデバイスからPrivate LoRa通信ゲートウェイにデータを集約する
また,本記事では,エッジデバイスを一つしか作成しませんでしたが,これを複数作成してセンサネットワークを構築することも可能です.
その際には,デバイス同士の区別ができるようにしたいと思いますので,それぞれのエッジデバイスごとにOWNIDを変えるなどの工夫をされると良いです.
おわりに
Private LoRa通信を利用したIoTシステムを実装することを最終目的として,今回の記事ではエッジデバイスを作成し,このデバイスから得られるデータをゲートウェイに集約するところまでを解説しました.
次回の記事では,ゲートウェイに集約したけど誰にも覚えてもらえていないデータたちをデータベースに格納したり,Webアプリケーション上に表示したりできるように解説を行う予定です.
参考
SHT15搭載 温湿度センサモジュール
Adafruit Metro M4 - スイッチサイエンス
エッジデバイスって結局なに?機械学習との関係は?
ES920LR2 - 株式会社EASEL
Arduino IDEのインストールと設定(Windows, Mac, Linux対応)- Indoor Corgi
Adding Third Party Boards to the Arduino v1.6.4+ IDE
SERCOM機能でGPIOが足りない話② - Qiita
SHT1x - ESP/ReadSHT1xValues.ino at master・beegee-tokyo/SHT1x-ESP
ES920LR2コマンド仕様ソフトウェア説明書
プライベートLoRaゲートウェイ ES920GWX2 - 株式会社EASEL
【ゼロからわかる】Teratermのインストールと使い方
CoolTerm ダウンロードしてインストールします | Mac
ES920GWX2 取扱説明書
Private LoRa通信関連の記事シリーズ
Private LoRa通信モジュールに関する記事をいくつか書いておりますので,興味がございましたら合わせてご覧ください.
Discussion