United Statesからアクセスのようです。言語設定をEnglishに切り替えますか?
Switch to English site
Skip to main content

DRAGINO LoRa GPS HAT -JPとLoRa Mini Wireless Moduleを使って温度、湿度データをクラウドサービスで表示してみた

DORAGINO製のラズパイ用LoRa通信モジュール、LoRa GPS HAT(技適対応版)をRSコンポーネンツさんで購入したので設定して使ってみました。既に同社のLoRa IoT スターターキットを使った事があったので、その応用で設定できました。

 

57160365_666403690471180_5305996580229218304_n_9d128eef742345098974785b62413347397d2074.png

センサーデバイスから取得したデータの可視化にはクラウドサービスである「Cayenne」を使っています。LoRa IoTスターターキットとCayenneの使い方については、以下の書籍で詳しく紹介されていますので、そちらをご覧ください。

The Things Network
 「LoRaWAN」をみんなでシェアして使う
 -- 長距離まで届く無料のIoTネットワークサービス- - 』(工学社 吉田 秀利、尾鷲 彰一)

工学社リンク
Amazonリンク

使用する機器

1)Raspberry Pi 3 B+ 
2)ゲートウェイ DORAGINO LoRa GPS HAT-JP
3)センサーデバイス DORAGINO LoRa Mini Wireless Module
4)温湿度センサー DHT-11

左がRaspberry Pi 3 B+、右がLoRa GPS HATです。
1_d7dd557abe56ceb65d46bec67499d06d00a5f1a8.jpg 

Raspberry PiにLoRa GPS HATを載せた状態です。
_3058f909287061cf660b4b81b7eeec453425567c.png

DORAGINO LoRa Mini Wireless Moduleに DHT-11(温湿度センサー)を接続します。LoRa Miniの3V3ポートにDHT-11のVCCを、GNDポートにGNDを、A0ポートにDATAを、それぞれ接続します。
31_f5153c575d8c51c6dad2eaf7846f5352aca11c51.jpg

こちらのWirelress ModuleとセンサーはLoRa IoTスターターキットに含まれています。詳しくはこちらのページをご覧ください。

Raspberry Piの起動用SDカードの用意

今回は手元にあった2018-11-13-raspbian-stretch-fullを使いました。適宜、公式サイトからダウンロードしてインストールしてください。

■ゲートウェイ側の準備

ソースコードの取得

Raspberry Piで動作させるLoRa GPS HAT用のプログラムをgithubからダウンロードしてきます。

設定ファイルの編集

その中にある設定ファイル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);
}

こちらの内容は@Densyoさんのqiitaを参考にしています。

訂正情報です。

上のプログラムは下のように関数名の最初のwを大文字Wに、引数の最後に,CEを追加してください。

// Set Tx Power for Japan
if (sx1272) {
  WriteRegister(REG_PA_CFG, PWR_JPN_1272, CE);
} else {
// sx1276
  WriteRegister(REG_PA_CFG, PWR_JPN_1276, CE);
}

 

プログラムのコンパイル

ここまでの修正が終わったらプログラムをコンパイルします。
この手順はこちらのページを参照してください。

プログラムの実行

プログラムを実行すると以下のように表示されてゲートウェイが動作していることがわかります。

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 (c) 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!
 * See http://thethingsnetwork.org/wiki/AddressSpace
 *
 * Do not forget to define the radio type correctly in config.h.
 *
 * Required Library: 
 *    * https://github.com/matthijskooijman/arduino-lmic 
 *    * https://github.com/adafruit/DHT-sensor-library
 *    * https://github.com/adafruit/Adafruit_Sensor
 * 
 * Require Hardware:
 *    * LoRa Shield + Arduino
 *    * LoRa GPS Shield + Arduino 
 *    * LoRa Mini etc. 
 *    
 *    このサンプルは、The Things NetworkにABPで、DHT11の
 *    温度、湿度のデータをCayenneLPPのペイロードで送信します。
 *    
 *    2017.11.01 株式会社オープンウェーブ
 *******************************************************************************/

#include 
#include <hal/hal.h>
#include 
#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....'

Cayenneでの表示

LoRaWANからCayenneにデータが上がってきますとコンソール画面でグラフ表示などで確認できます。

41_53be8c9e3584479755bd18aaa8cfb37df4e0b44f.png

最後に

今回は簡単にできる範囲でゲートウェイ機能を使ってみただけですが、今後はGPS機能やフィールドに持ち出しての利用についても試していきたいと思っています。

新潟エスラボ株式会社 代表取締役 帳票設計ツールの開発に従事後、新潟エスラボ株式会社を設立し、ソフトウェア開発販売、IoTシステム開発を行なっています。 https://niigata-sl.com
DesignSpark Electrical Logolinkedin