RSコンポーネンツさんのオンラインショップrs-online.comでDRAGINO社のLoRa GPS HATを購入して手元に届いたので設定して使ってみました。
以前よりLoRa IoT スターターキットを使っていましたので、その応用となります。
センサーデバイスから取得したデータの可視化にはクラウドサービスである「Cayenne」を使います。
LoRa IoTスターターキットとCayenneの使い方については、以下の書籍で詳しく紹介されていますので
そちらをご覧ください。
長距離まで届く無料のIoTネットワークサービス The Things Network
「LoRaWAN」をみんなでシェアして使う (工学社 吉田 秀利、尾鷲 彰一)
https://www.kohgakusha.co.jp/books/detail/978-4-7775-2043-5
使用する機器
1)Raspberry Pi 3 B+
2)ゲートウェイ DORAGINO LoRa GPS HAT-JP
【写真1】
【写真2】
写真1の左がRaspberry Pi 3 B+、右がLoRa GPS HATです。
写真2はRaspberry PiにLoRa GPS HATを載せた状態です。
3)センサーデバイス DORAGINO LoRa Mini Wireless Module、DHT-11(温湿度センサー)
LoRa MiniとDHT-11を接続します。
LoRa Miniの3V3ポートにDHT-11のVCC、GNDポートにGND、A0ポートにDATAをそれぞれ接続します。
こちらのWirelress ModuleとセンサーはLoRa IoTスターターキットに含まれています。
詳しくは以下のページをご覧ください。
Raspberry Piの起動用SDカードの用意
今回は手元にあった2018-11-13-raspbian-stretch-fullを使いました。
適宜、公式サイトからダウンロードしてインストールしてください。
ゲートウェイ側ソースコードの取得
Raspberry Piで動作させるLoRa GPS HAT用のプログラムをgithubからダウンロードしてきます。https://github.com/bokse001/dual_chan_pkt_fwd.git
設定ファイルの編集
その中にある設定ファイルglobal_config.jsonを以下のように変更します。
{
"SX127x_conf":
{
"freq": 923400000,
"freq_2": 923200000,
"spread_factor": 10,
"pin_nss": 6,
"pin_dio0": 7,
"pin_nss_2": 6,
"pin_dio0_2": 7,
"pin_rst": 3,
"pin_led1":4,
"pin_NetworkLED": 22,
"pin_InternetLED": 23,
"pin_ActivityLED_0": 21,
"pin_ActivityLED_1": 29
},
プログラムの修正
以下 の内容をdual_chan_pkt_fwd.cppに追加します。
// Tx Power Register
#define REG_PA_CFG 0x09
// Power Setting for Japan ARIB STD-T108
// 20mW=13dBm
// SX1276 RegPaConfig(0x09), Val=0x3f
// bit 7 PaSelect = 0 select RFO
// bit 6-4 MaxPower = 3 Pmax=10.8+0.6*3=12.6 < 13
// bit 3-0 OutputPower = 0x0f Pout=Pmax-(15-0x0f)=12.6
// SX1272 RegPaConfig(0x09), Val=0x0e
// bit 7 PaSelect = 0 select RFO
// bit 6-4 unused = 0
// bit 3-0 OutputPower = 0xe Pout=-1 + OutputPower = -1 + 0x0e = 13dBm
int PWR_JPN_1276 = 0x3f;
int PWR_JPN_1272 = 0xe;
周波数設定の後に追加します.
// Set Tx Power for Japan
if (sx1272) {
writeRegister(REG_PA_CFG, PWR_JPN_1272);
} else {
// sx1276
writeRegister(REG_PA_CFG, PWR_JPN_1276);
}
2019年4月25日訂正:
writeRegister(REG_PA_CFG,PWR_JPN_1272);
writeRegister(REG_PA_CFG,PWR_JPN_1276);
となっているところは関数の仕様が変わっていますので
WriteRegister(REG_PA_CFG,PWR_JPN_1272, CE);
WriteRegister(REG_PA_CFG,PWR_JPN_1276, CE);
に変更してください。(先頭のwがW(大文字)になる、引数にCEを追加)
こちらの内容は@Densyoさんのqiitaを参考にしています。
プログラムのコンパイル
ここまでの修正が終わったらプログラムをコンパイルします。
この手順は以下のページを参照してください。
プログラムの実行
プログラムを実行すると以下のように表示されてゲートウェイが動作していることがわかります。
pi@raspberrypi : ~/dual_chan_pkt_fwd $ sudo ./dual_chan_pkt_fwd
server: .address = router.eu.staging.thethings.network; .port = 1700; .enable = 1
server: .address = router.eu.thethings.network; .port = 1700; .enable = 0
Gateway Configuration
Takenori Tanaka (takenori_tanaka@niigata-sl.com)
Dual channel pkt forwarder
Latitude=37.83515930
Longitude=139.11381531
Altitude=3
Interface: eth0
Trying to detect module CE0 with NSS=6 DIO0=7 Reset=3 Led1=unused
SX1276 detected on CE0, starting.
Trying to detect module CE1 with NSS=6 DIO0=7 Reset=3 Led1=unused
SX1276 detected on CE1, starting.
Gateway ID: b8:27:eb:ff:ff:01:4a:6b
Listening at SF10 on 923.400000 Mhz.
Listening at SF10 on 923.200000 Mhz.
stat update: 2019-04-05 05:40:07 GMT no packet received yet
センサーデバイス側プログラムの準備
センサーデバイス側のサンプルコードが株式会社オープンウェーブのgithubで公開されています。
以下のコードはサンプルコードを参考に作成したものです。
このプログラムではLoRaWANからクラウドサービスCayenneにデータを渡すようになっています。
また、LoRaWANでは,デバイスとセキュアに通信するため暗号化して通信する仕組みが導入されています。通信開始時には「アクティベーション」により暗号鍵を交換します。この方式にはABPとOTAAの2種類があり、今回はABPを使用しています。
LoRaWANの暗号化システムについては以下のページに詳しく解説されています。
/*******************************************************************************
-
Copyright © 2015 Thomas Telkamp and Matthijs Kooijman
-
Changed 2017.11.01 OpenWave inc,
-
Permission is hereby granted, free of charge, to anyone
-
obtaining a copy of this document and accompanying files,
-
to do whatever they want with them without any restriction,
-
including, but not limited to, copying, modification and redistribution.
-
NO WARRANTY OF ANY KIND IS PROVIDED.
-
Change DEVADDR to a unique address!
-
Do not forget to define the radio type correctly in config.h.
-
Required Library:
-
Require Hardware:
-
- LoRa Shield + Arduino
-
- LoRa GPS Shield + Arduino
-
- LoRa Mini etc.
-
このサンプルは、The Things NetworkにABPで、DHT11の
-
温度、湿度のデータをCayenneLPPのペイロードで送信します。
-
2017.11.01 株式会社オープンウェーブ
*******************************************************************************/
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include "DHT.h"
#include "CayenneLPP.h"
#define dht_dpin A0 // Use A0 pin as Data pin for DHT11.
#define DHTTYPE DHT11 // DHT 11
/*
-
以下の、デバイスアドレス、ネットワークセッションキー、アプリケーションセッションキー
-
を、The Things Networkで取得した値に変更してください。
*/
// デバイスアドレス
static const u4_t DEVADDR = ここにデバイスアドレスを設定します;
// ネットワークセッションキー
static const PROGMEM u1_t NWKSKEY[16] = { ここにネットワークセッションキーを設定します };
// アプリケーションセッションキー
static const u1_t PROGMEM APPSKEY[16] = { ここにアプリケーションセッションキーを設定します };
// 以下の変数はOTAAでアクティベーションする際に、TTNから割り当てられる値となります。
void os_getArtEui (u1_t* buf) { }
void os_getDevEui (u1_t* buf) { }
void os_getDevKey (u1_t* buf) { }
static uint8_t mydata[4];
static osjob_t initjob,sendjob,blinkjob;
// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 20;
DHT dht(dht_dpin, DHTTYPE);
// Pin mapping
const lmic_pinmap lmic_pins = {
.nss = 10,
.rxtx = LMIC_UNUSED_PIN,
.rst = 9,
.dio = {2, 6, 7},
};
void do_send(osjob_t* j){
float h = dht.readHumidity();
float t = dht.readTemperature();
CayenneLPP lpp(51); // create a buffer of 51 bytes to store the payload
lpp.reset(); // clear the buffer
lpp.addTemperature(1, t); // on channel 1, add temperature, value 22.5°C
lpp.addRelativeHumidity(2, h); // channel 2, pressure
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println("OP_TXRXPEND, not sending");
} else {
// Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(1, lpp.getBuffer(), lpp.getSize(), 0);
Serial.println("Packet queued");
Serial.println(LMIC.freq);
}
// Next TX is scheduled after TX_COMPLETE event.
}
void onEvent (ev_t ev) {
Serial.print(os_getTime());
Serial.print(": ");
Serial.println(ev);
switch(ev) {
case EV_TXCOMPLETE:
Serial.println("EV_TXCOMPLETE (includes waiting for RX windows)");
if(LMIC.dataLen) {
// data received in rx slot after tx
Serial.print("Data Received: ");
Serial.write(LMIC.frame+LMIC.dataBeg, LMIC.dataLen);
Serial.println();
}
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
break;
default:
Serial.println("Other Event");
break;
}
}
void setup() {
memset(mydata, 0x00, 4);
Serial.begin(9600);
while(!Serial);
Serial.println("Starting");
delay(1000);
// LMIC init
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_reset();
//LMIC_setClockError(MAX_CLOCK_ERROR * 1/100);
// Set static session parameters. Instead of dynamically establishing a session
// by joining the network, precomputed session parameters are be provided.
#ifdef PROGMEM
// On AVR, these values are stored in flash and only copied to RAM
// once. Copy them to a temporary buffer here, LMIC_setSession will
// copy them into a buffer of its own again.
uint8_t appskey[sizeof(APPSKEY)];
uint8_t nwkskey[sizeof(NWKSKEY)];
memcpy_P(appskey, APPSKEY, sizeof(APPSKEY));
memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY));
LMIC_setSession (0x1, DEVADDR, nwkskey, appskey);
#else
// If not running an AVR with PROGMEM, just use the arrays directly
LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY);
#endif
// Disable link check validation
LMIC_setLinkCheckMode(0);
// TTN uses SF9 for its RX2 window.
LMIC.dn2Dr = DR_SF9;
// Set data rate and transmit power (note: txpow seems to be ignored by the library)
LMIC_setDrTxpow(DR_SF10,13);
dht.begin();
// Start job
do_send(&sendjob);
}
void loop() {
os_runloop_once();
}
センサーデバイスの起動
ArduinoIDEを使用してプログラムを書き込み、実行します。
デバイスでは温度と湿度を計測してデータ送信を開始します。
センサーデバイスからデータを受信するとゲートウェイ側のコンソールにその様子が表示されます。
pi@raspberrypi : ~/dual_chan_pkt_fwd $ sudo ./dual_chan_pkt_fwd
server: .address = router.eu.staging.thethings.network; .port = 1700; .enable = 1
server: .address = router.eu.thethings.network; .port = 1700; .enable = 0
Gateway Configuration
Takenori Tanaka (takenori_tanaka@niigata-sl.com)
Dual channel pkt forwarder
Latitude=37.83515930
Longitude=139.11381531
Altitude=3
Interface: eth0
Trying to detect module CE0 with NSS=6 DIO0=7 Reset=3 Led1=unused
SX1276 detected on CE0, starting.
Trying to detect module CE1 with NSS=6 DIO0=7 Reset=3 Led1=unused
SX1276 detected on CE1, starting.
Gateway ID: b8:27:eb:ff:ff:01:4a:6b
Listening at SF10 on 923.400000 Mhz.
Listening at SF10 on 923.200000 Mhz.
stat update: 2019-04-06 00:57:48 GMT no packet received yet
CE0 Packet RSSI: -43, RSSI: -96, SNR: 14, Length: 20 Message:’@…&.T…‘e…B#…’
rxpk update: {"rxpk":[{"tmst":416552586,"freq":923.4,"chan":0,"rfch":0,"stat":1,"modu":"LORA","datr":"SF10BW125","codr":"4/5","rssi":-43,"lsnr":14.0,"size":20,"data":"QIYbBCaAVAUBJ2UatrShjUIj0dI="}]}
stat update: 2019-04-06 00:58:18 GMT 1 packet received
CE0 Packet RSSI: -44, RSSI: -95, SNR: 14, Length: 20 Message:’@…&.U…x…8(…$’
rxpk update: {"rxpk":[{"tmst":453612330,"freq":923.4,"chan":0,"rfch":0,"stat":1,"modu":"LORA","datr":"SF10BW125","codr":"4/5","rssi":-44,"lsnr":14.0,"size":20,"data":"QIYbBCaAVQUBiXjB2DgopBgO8yQ="}]}
stat update: 2019-04-06 00:58:48 GMT 2 packets received
stat update: 2019-04-06 00:59:18 GMT 2 packets received
CE0 Packet RSSI: -45, RSSI: -96, SNR: 12, Length: 20 Message:’@…&.V…(…l…’
アプリケーションデータの確認
TTNのコンソールでアップロードされるデータを確認しました。
Cayenneでの表示
LoRaWANからCayenneにデータが上がってきますとコンソール画面でグラフ表示などで確認できます。
最後に
今回は簡単にできる範囲でゲートウェイ機能を使ってみただけですが、今後はGPS機能やフィールドに持ち出しての利用についても試していきたいと思っています。