LoRaWANハンズオン

Takashi Oguma edited this page Jul 31, 2017 · 9 revisions

LoRa Arduino 開発シールドを使用したハンズオン

2017年2月にソラコムからリリースされた ArduinoでLoRaWAN通信を可能にする LoRa Arduino 開発シールド AL-050Arduino UNO R3 、そして温度センサーを利用し、データ収集・蓄積サービス SORACOM Harvest でセンサーデータを可視化するハンズオンです

概要

※本ハンズオンは 30分~60分 程度を見込みます

全体構成

全体像

  1. Hello Arduino !! (Lチカ)
  2. 温度センサーで温度を計測する
  3. LoRaWANでデータ送信をしてSORACOM Harvestで可視化する
  4. あとかたづけ

準備するもの

  • 有効なSORACOMアカウント / 1つ
  • パソコン / 1台
  • Arduino UNO R3 / 1つ
  • Arduino UNO R3 ⇔ パソコン接続用 USBケーブル / 1本
  • LoRa Arduino 開発シールド / 1式
  • 温度センサー LM61CIZ / 1つ
  • ブレッドボード / 1つ
  • ジャンパワイヤ / 3本

準備するもの一覧

受講における注意点

  1. 本ドキュメントで利用するサービスには一部有料のものを含んでおります (e.g. SORACOM Harvest, SORACOM Funnel)
    受講に伴い発生した費用は原則として受講者にご負担いただいておりますので、係る費用について確認・ご理解いただいた上での受講をお願いいたします
  2. 本ドキュメントで発生した不具合等につきましては弊社は一切責任を負いません

金額の目安

  • SORACOM Harvest: 5円/LoRaデバイス/日 → 2,000回/日のリクエストに収まります
  • SORACOM Funnel: 600回のリクエスト → 約1円

ハンズオン

Hello Arduino !! (LEDをチカチカさせる 通称:Lチカ)

※この段階ではまだLoRa開発シールドは取り付けません

1. "blink" サンプルスケッチを読み込む

Arduino IDE から ファイル > スケッチ例 > 01.Basics > Blink を選んでください

ファイル > スケッチ例 > 01.Basics > Blink

すると、新しいウィンドウで Arduino上のLEDをチカチカ点滅させる Blinkスケッチ が開きます

2. コンパイル&Arduinoへの転送を行う

Blinkスケッチ をコンパイル&マイコンボードへの書き込みを行います。Arduinoを接続した状態で行ってください

コンパイルとArduinoへの書き込み

初めて Arduino を使う場合や、これまで使っていたのと違う機種の Arduino を使う場合は、書き込み時にエラーが発生するかもしれません。 その場合は「ツール」メニューから、「ボード」と「ポート」を正しく選択してください。

3. Arduino 上のLEDを確認する

LEDが1秒毎に点滅し始めれば成功です

LEDが点滅している様子

4. Arduino を停止する

Arduinoの停止の方法は、電源(USBケーブル)を抜くことです

マイコン全般に言えることはパソコンと違いシャットダウン処理などは原則として不要です

TRY; LEDを制御してみる

Blinkスケッチ はLEDは1秒(=1,000ミリ秒)ごとに点滅するようにコーディングされています
いろんな改造をしてみましょう

  1. 500ミリ秒毎に変えてみましょう
  2. 点灯は2秒、消灯は1秒と間隔を変えてみましょう
  3. モールス信号 "SOS" を表現してみましょう
    • ヒント: SOS => トントントン ツーツーツー トントントン
    • ヒント: トンは150ms、ツーは300ms、休止は600ms

トラブルシュート; コンパイル&転送時; "指定されたファイルがありません"

エラー画面

Arduinoを接続しているシリアルポートがOSから認識できていないと表示されます

  • 再接続をしてみてください
  • ツール > シリアルポートのメニューからArduinoが接続されてるシリアルポートを選択してください

温度センサーで温度を計測する

それでは温度センサー(LM61CIZ)を取り付け、温度を実際に計測してみましょう

※この段階ではまだLoRa開発シールドは取り付けません

1. 温度センサーを取り付ける

Arduinoを停止した後 1/Arduino本体 2/ブレッドボード 3/温度センサー(LM61CIZ) 4/ジャンパワイヤー それぞれを準備し、下記の通り接続してください

接続図

ブレッドボードと温度センサー(LM61CIZ)を実際につなげたところ

ブレッドボードと温度センサー(LM61CIZ)を実際につなげたところ 横から見た様子 Arduinoとの接続

注意点

  • 温度センサー(LM61CIZ)の取り付け向きに注意してください。平らになっている面がポイントです
  • ジャンパワイヤーの色自体には意味がありません。お好きな色をお使いください
    (一般的には電源 (VCCとかVsとか書かれている) には赤を、GNDには黒を使います)
  • Arduino上には複数 GND が存在します。どの GND に接続しても大丈夫です

2. 新たなスケッチを実行する

Arduinoとパソコンをつなげる

この時点では、前の Blinkスケッチ が動作しているため、LEDが点滅しています

注意点

  • この時点で温度センサー(LM61CIZ)が 「触れないくらいに熱くなってきた」「焦げ臭い匂いがしてきた」 場合は、USBケーブルを抜いてArduinoを停止し、再度接続を確認してください

新たなスケッチを作成する

ファイル > 新規ファイル を選択すると、新たなスケッチウィンドウが立ち上がります
骨組みコードが書かれていますが すべて削除したうえで 下記スケッチを張り付けてコンパイル&転送をしてください

※その際スケッチを保存するように言われることがありますが適切なファイル名を指定して保存してください

#define SENSOR_PIN 0 //analog pin
#define PROBE_INTERVAL 5000 //msec

void setup() {
  Serial.begin(9600);
}

void loop() {
  int v, tv;
  float t;
  v = analogRead(SENSOR_PIN);
  tv  = map(v, 0, 1023, 0, 5000);
  t = map(tv, 300, 1600, -300, 1000) / 10.0;
  char buf[7];
  dtostrf(t, -1, 2, buf); /* Arduino UNO R3 cannot cast float to char */
  Serial.println(buf);
  delay(PROBE_INTERVAL);
}

シリアルモニタを開く

実行し始めると、先ほどまで点滅していたLEDは点灯状態となります
計測された温度は シリアルモニタ というところに表示されるので、それを確認します

ツール > シリアルモニタ で下記のように温度が表示されていることがわかります

シリアルモニタの様子

シリアルモニタはArduino開発で最も一般的な入出力I/Fです。使い方は シリアルモニタの使い方 をご覧ください

トラブルシュート; Arduinoを停止(USBケーブルを抜いた)ら、パソコンのCPUが100%になる

"シリアルモニタ" のウィンドウを表示しているとCPU負荷がかかるようです

"シリアルモニタ" ウィンドウを閉じてください

LoRaWANでデータ送信をしてSORACOM Harvestで可視化する

それでは温度センサー(LM61CIZ)で計測した温度データをLoRaWANを経由してSORACOM Harvestに送信し可視化してみましょう

いったんArdinoは停止し、温度センサーもすべて取り外してください

1. LoRa開発シールドを取り付ける

Arduinoの上にLoRa開発シールドを取り付けます

LoRaシールドを取り付けた後の様子

注意点

  • LoRa開発シールドのピンは折れ曲がりやすいため、取り付け時および取り外しの際にはご注意ください(原則保証外です)

LoRaアンテナケーブルとアンテナを取り付けます

LoRaアンテナケーブルのコネクタ

LoRaアンテナ

注意点

  • LoRaアンテナケーブルのコネクタはとても小さいため、取り付けができていない場合もあります。不安がある場合はチューターにご確認ください。またコネクタを破損しないよう、取り付け時および取り外しの際にはご注意ください(原則保証外です)

2. 温度センサーを取り付ける(再)

LoRa開発シールドの上に、先ほどと同じ様に温度センサー(LM61CIZ)を取り付けます

LoRa開発シールドの上にセンサーを取り付けた様子

注意点

  • Arduino上の表記と若干違うため、ピンの位置は再度確認するようにしてください。位置自体は全く同じです

この時点で、下記のようになっているはずですので、確認をしてください

全体

3. スケッチを実行する

SORACOM-LoRaWAN Arduinoライブラリをダウンロードする

LoRa開発シールドをArduinoで利用するには、SORACOMからリリースされているソフトウェアライブラリをスケッチに取り込む必要があります

下記から最新版のZIPファイルをダウンロードしてください

SORACOM-LoRaWAN release ページ

ダウンロード

新たなスケッチを作成する

  1. Arduino IDE にて ファイル > 新規ファイル で新たなスケッチウィンドウを立ち上げます
  2. スケッチ > ライブラリをインクルード > .ZIP形式のライブラリをインストール... で、先ほどダウンロードした SORACOM-LoRaWAN-1.0.1.zip を選択してください
    インクルード
  3. 骨組みコードが書かれていますが すべて削除したうえで 下記スケッチを張り付けてコンパイル&転送をしてください
#define SENSOR_PIN 0 //analog pin
#define PROBE_INTERVAL 5000 //msec

#include <lorawan_client.h>
LoRaWANClient lorawan;

void setup() {
  Serial.begin(9600);
  if(! lorawan.connect(true))
  {
    Serial.println(" failed to connect. Halt...");
    for(;;){};
  }
  Serial.println("\nConnected.\n");
}

void loop() {
  int v, tv;
  float t;
  v = analogRead(SENSOR_PIN);
  tv  = map(v, 0, 1023, 0, 5000);
  t = map(tv, 300, 1600, -300, 1000) / 10.0;
  char buf[7];
  dtostrf(t, -1, 2, buf); /* Arduino UNO R3 cannot cast float to char */
  Serial.println(buf);
  char json[13];
  sprintf(json, "{\"t\":%s}", buf);
  Serial.println(json);
  lorawan.sendData(json);
  delay(PROBE_INTERVAL);
}

シリアルモニタを開く

実行し始めると、シリアルモニタは下記通りとなり、テキスト・JSONそれぞれの形式で温度が表示されるのと同時に、LoRaWAN通信をしている様子が確認できます

シリアルモニタの様子

4. SORACOM Harvestの設定をする

LoRaデバイスの登録状況を確認する

ソラコムコンソールにログインし Menu > LoRa デバイス管理 をクリックします

ここにはLoRa開発シールド購入後の登録が完了しているデバイスが表示されています

LoRaデバイス管理

表示されていない、対象のデバイスが無い場合は、まずLoRa開発シールド購入後の登録を行ってください

LoRaグループを追加する

Menu > LoRaグループ をクリックすると、LoRaグループ一覧が表示されます。この画面で 追加 をクリックします

LoRaグループ画面

ダイアログで下記の通り設定した後、グループ作成 をクリックします

  • グループ名: lora_demo0

LoRaグループ画面

下記の通り、先ほど作成した lora_demo0 が一覧に表示されます

LoRaグループ画面

LoRaグループにSORACOM Harvestの設定を施す

LoRaグループ一覧の中から lora_demo0 をクリックします

LoRaグループ

SORACOM Air for LoRaWAN 設定 を下記の通りにしてください
※通常は変更の必要はありませんが、変更したら 保存 をクリックしてください

  • SORACOM LoRa Space を利用: 利用する
  • LoRa ネットワークセットID: ------

LoRaグループ Air

同じページ内の SORACOM Harvest 設定 を下記の通りにした後 保存 をクリックしてください

  • ON

LoRaグループ Harvest

下記のダイアログが出ますので OK をクリックしてください

LoRaグループ Harvest確認

LoRaデバイスをLoRaグループに所属させる

Menu > LoRaデバイス管理 をクリックして、LoRaデバイス一覧を表示します

先ほど作成した lora_demo0 LoRaグループに所属させたいLoRaデバイスのチェックボックスを選択した後、操作 > 所属グループ変更をクリックしてください

ダイアログにて下記のように設定した後 グループ変更 をクリックしてください

  • 新しい所属グループ: lora_demo0

グループへ所属する

5. データの確認をする

LoRaデバイスをSORACOM Harvestが有効なLoRaグループに所属させた直後から、データの可視化が始まります
※SORACOM Air for セルラーのようにセッションの再接続が不要です

Menu > LoRaデバイス管理 をクリックし、データを表示させたいLoRaデバイスのチェックボックスを選択した後、操作 > データを確認 にてデータを確認することができます

SORACOM Harvest

変化を楽しむ

温度センサー(LM61CIZ)を指でつまんでみると温度が変化します

SORACOM Harvestは標準では手動での表示更新であるため更新ボタンを押す、もしくは自動更新をONにしてください

トラブルシュート; sendCmd: lorawan join otta の結果が "unseccess"

何回も unsuccess が表示される場合、LoRaWAN通信に失敗しています

unsuccessの例

  • LoRaWAN ゲートウェイと通信できる距離・環境であるか確認してください
  • LoRa開発シールドとLoRaアンテナの接続を確認してください

トラブルシュート; SORACOM Harvestにデータが表示されない

  • 表示期間が合ってないことがあります。調整してみてください

あとかたづけ

1. SORACOM Harvestの設定をする

SORACOM Harvestは有料のサービスです
ハンズオンが終了したら必ず設定を確認し、不要な課金が発生しないようにしてください

LoRaグループにSORACOM Harvestの設定を施す

Menu > LoRaグループ をクリックすると、LoRaグループ一覧が表示されます
LoRaグループ一覧の中から lora_demo0 をクリックします

LoRaグループ

SORACOM Harvest 設定 を下記の通りにした後 保存 をクリックしてください
※ONの時に出た様なダイアログは出ません

  • OFF

LoRaグループ Harvest

オプション; LoRaグループを削除する

LoRaグループ自体には費用は発生しませんが、不要な課金を避けるためにも削除をお勧めします

手順は以下の通り

  1. 削除対象のLoRaグループに所属しているLoRaデバイスをすべて解除する
  2. 削除対象のLoRaグループを表示し 高度な設定 から削除を実行する

ハンズオン (応用編 / SORACOM Funnel AWS IoT アダプタ)

2017/4/6にリリースされた SORACOM Funnel の新しいアダプタ SORACOM Funnel AWS IoT Adapter を利用して、LoRaデバイスからのデータをAWS IoT、さらにはAmazon Elasticsearch Serviceで可視化します

※本ハンズオンは 60分~90分 程度を見込みます

対象者

  • LoRa Arduino 開発シールドを使用したハンズオンにて SORACOM Harvestでデータの可視化まで達成でき、同じものを用意できる
  • 有効なAWSアカウントを持っている
    • 本ハンズオンにおいては有料サービスを利用するため課金されることをご理解ください
    • AWSの基本的なサービスは利用可能である
      • Amazon EC2のインスタンス作成・停止などの操作が行える
      • Amazon S3のバケット作成・削除などの操作が行える
      • AWS IAMのロールやポリシーを理解し、作成・削除などの操作が行える

全体構成

全体像

解説

SORACOM Air for LoRaWAN から SORACOM Funnel を通過した場合のデータフォーマットがHEXデータであるため※デコードが必要です
※SORACOM-LoRaWANライブラリを使用した場合。2017年4月現在

本ハンズオンでは AWS Lambda によってHEXデータを生データに変換し、改めてAWS IoTのルールエンジンにて振り分けて Amazon Elasticsearch Serviceへデータ送信を行います

SORACOM Air for LoRaWAN でデータ送信を行った場合において SORACOM Funnel で出力されるデータフォーマットについて

SORACOM Funnel では送信データ形式をいくつか選ぶことができます
LoRaデバイスから {"t":31.30} というJSONデータを送った場合、それぞれで下記のような違いがあります

送信データ形式: (指定しない) or テキスト → payloadsテキスト としてJSONデータが格納されており、実際は data にHEX形式で格納されています

// 指定なし or テキスト
{
  "operatorId": "OP00XXXXXXXX",
  "timestamp": 1491822045245,
  "destination": {
    "resourceUrl": "XXXXXXXXXXXX.iot.ap-northeast-1.amazonaws.com/testing_awsiot/#{deviceId}",
    "service": "aws-iot",
    "provider": "aws"
  },
  "credentialsId": "XXXXXXXXXXXXXX",
  "payloads": "{\"date\": \"2017-04-10T11:00:42.185191\", \"gatewayData\": [{\"date\": \"2017-04-10T11:00:42.185191\", \"rssi\": -47, \"snr\": 11.5, \"gwid\": \"000b78XXXXXXXXXX\", \"channel\": 926400000}], \"data\": \"7b2274223a32352e35307d\", \"deveui\": \"000b78fYYYYYYYYY\"}",
  "sourceProtocol": "lora",
  "deviceId": "000b78fYYYYYYYYY"
}

送信データ形式: (JSON) → すべてJSONとして取り扱っており payloads -> data にHEX形式で格納されています

// JSON
{
  "operatorId": "OP00XXXXXXXX",
  "timestamp": 1491822207364,
  "destination": {
    "resourceUrl": "XXXXXXXXXXXX.iot.ap-northeast-1.amazonaws.com/testing_awsiot/#{deviceId}",
    "service": "aws-iot",
    "provider": "aws"
  },
  "credentialsId": "XXXXXXXXXXXXXX",
  "payloads": {
    "date": "2017-04-10T11:03:24.386070",
    "gatewayData": [
      {
        "date": "2017-04-10T11:03:24.386070",
        "rssi": -103,
        "snr": -10.2,
        "gwid": "000b78XXXXXXXXXX",
        "channel": 923400000
      }
    ],
    "data": "7b2274223a32362e30307d",
    "deveui": "000b78fYYYYYYYYY"
  },
  "sourceProtocol": "lora",
  "deviceId": "000b78fYYYYYYYYY"
}

送信データ形式: (バイナリ) → payloadsJSONをBase64エンコードしたテキスト としてJSONデータが格納されており、実際は Base64デコードした後のJSONの data にHEX形式で格納されています

// binary
{
  "operatorId": "OP00XXXXXXXX",
  "timestamp": 1491822410301,
  "destination": {
    "resourceUrl": "XXXXXXXXXXXX.iot.ap-northeast-1.amazonaws.com/testing_awsiot/#{deviceId}",
    "service": "aws-iot",
    "provider": "aws"
  },
  "credentialsId": "XXXXXXXXXXXXXX",
  "payloads": "eyJkYXRlIjogIjIwMTctMDQtMTBUMTE6MDY6NDcuMTQ1Mzk1IiwgImdhdGV3YXlEYXRhIjogW3siZGF0ZSI6ICIyMDE3LTA0LTEwVDExOjA2OjQ3LjE0NTM5NSIsICJyc3NpIjogLTQyLCAic25yIjogMTAuMiwgImd3aWQiOiAiMDAwYjc4ZmZmZWIwMDAwNiIsICJjaGFubmVsIjogOTI2NDAwMDAwfV0sICJkYXRhIjogIjdiMjI3NDIyM2EzMzMxMmUzMzMwN2QiLCAiZGV2ZXVpIjogIjAwMGI3OGZmZmUwNTA3NDQifQ==",
  "sourceProtocol": "lora",
  "deviceId": "000b78fYYYYYYYYY"
}

// payloads => Base64 encode
{
  "date": "2017-04-10T11:06:47.145395",
  "gatewayData": [
    {
      "date": "2017-04-10T11:06:47.145395",
      "rssi": -42,
      "snr": 10.2,
      "gwid": "000b78XXXXXXXXXX",
      "channel": 926400000
    }
  ],
  "data": "7b2274223a33312e33307d",
  "deveui": "000b78fYYYYYYYYY"
}

要するに

  • FunnelからはJSONで出力される
  • 送信データ形式が 指定なし、テキスト、バイナリ においては、 payloads を必ず再JSONパースもしくはBase64エンコードする手間が必要
    • 送信データ形式がJSONにおいて、LoRaデバイスが壊れたJSONを送信した場合は TODO
  • すべてのケースにおいて payloads 内の data に HEX形式でデータ格納がされており、pack関数等で生データ化する必要あり

AWS Lambda

# runtime = python2.7
import json
import boto3
iot = boto3.client('iot-data', region_name='ap-northeast-1')

def lambda_handler(event, context):
    event["payloads"]["data"] = json.loads(event["payloads"]["data"].decode('hex')) # NOTE: Replace decoded hex data in payloads.data 
    iot.publish(topic='from_lambda/{0}'.format(event["deviceId"]), qos=0, payload=json.dumps(event))
    return None

AWS IoT / Rule

{
    "ruleArn": "arn:aws:iot:ap-northeast-1:YOUR_AWS_ACCOUNT_ID:rule/from_funnel",
    "rule": {
        "ruleName": "from_funnel",
        "awsIotSqlVersion": "2016-03-23",
        "description": "Receive data from SORACOM Funnel that throught to AWS Lambda",
        "ruleDisabled": false,
        "actions": [
            {
                "lambda": {
                    "functionArn": "arn:aws:lambda:ap-northeast-1:YOUR_AWS_ACCOUNT_ID:function:extract_funnel_payload_pub_to_awsiot"
                }
            }
        ],
        "sql": "SELECT * FROM 'from_funnel/#'"
    }
}

{
    "ruleArn": "arn:aws:iot:ap-northeast-1:YOUR_AWS_ACCOUNT:rule/from_lambda",
    "rule": {
        "ruleName": "from_lambda",
        "awsIotSqlVersion": "2016-03-23",
        "ruleDisabled": false,
        "sql": "SELECT * FROM 'from_lambda/#'",
        "actions": [
            {
                "elasticsearch": {
                    "endpoint": "https://search-testing-awsiot0-kqdmmlv3urjzxpeh72xocljz4e.ap-northeast-1.es.amazonaws.com",
                    "id": "${newuuid()}",
                    "type": "lora-tempture",
                    "index": "testing-awsiot0",
                    "roleArn": "arn:aws:iam::YOUR_AWS_ACCOUNT:role/testing_awsiot_put"
                }
            }
        ]
    }
}

手順

こうご期待!

ハンズオン (応用編 / 超音波測距センサー HC-SR04)

こうご期待!

ハンズオン (応用編 / HD44780互換LCDモジュール SD1602VBWB)

こうご期待!

ハンズオン (応用編 / ダウンリンク送信)

こうご期待!

Appendix: Arduino IDEのインストールと起動方法

ダウンロード&インストール

Download the Arduino IDEから、OSにあったファイルをダウンロードし、インストールしてください

  • "Support the Arduino Software" のページで JUST DOWNLOAD を選べばダウンロードできます (ぜひとも貢献をご検討ください)
  • Windowsの場合: Windows Installer が無難です。また、管理者権限でインストールしてください
  • macOSの場合: インストール時に Java SE も同時にインストールを要求される場合がありますが、Java SEもインストールしてください

起動方法

インストールが終われば Arduino IDEのアイコン がデスクトップやスタートメニューに現れるので、これで起動可能です

Appendix: LoRa Arduino 開発シールド(AL-050) の購入後の登録

LoRa開発シールドのDevEUI(LoRaWANにおけるデバイスID)はソラコムで管理※しており、ご利用者が直接管理する必要がありません
その代わりに、ご購入いただきLoRa開発シールドがお手元に届きましたら 受け入れ をソラコムコンソールから行っていただく必要があります
※2017年4月現在

Menu > 発注 をクリックしてください。受け入れ可能なLoRa開発シールドには 受け取り確認 が表示されているので、受け取り確認をクリックしてください

注文一覧

これで Menu > LoRaデバイス管理 に受け取り確認ができたデバイスが一覧に表示され、利用準備が整います

詳細はLoRaWAN ゲートウェイ/デバイス ハードウェアセットアップガイドをご覧ください

Appendix: Arduino IDE シリアルモニタの使い方

こうご期待!

Appendix: Arduino UNO R3を電池で動かす

Arduino UNO R3は 9Vの電池(006P)で動作させることが可能です

必要なもの

このような形になります

9V乾電池接続の図

持続時間

検証中です

Appendix: 各言語におけるデコード

Python 2.7

Base64デコード

import base64
raw_data = base64.b64decode(base64ed_str)

HEX文字列デコード

raw_data = '7b2274223a33312e33307d'.decode('hex')

Perl

Base64デコード

use MIME::Base64;
$raw_data = decode_base64($base64ed_str)

HEX文字列デコード

$raw_data =  pack("H*", "7b2274223a33312e33307d")

Ruby

Base64デコード

require 'base64'
raw_data = Base64.decode64(base64ed_str)

HEX文字列デコード

raw_data = ["7b2274223a33312e33307d"].pack("H*")