LoRaWAN 対応 ARDUINO MKR WAN 1300 を使ってみた ゲートウェイ接続編 福岡市LoRaWAN

前回 ARDUINO MKR WAN 1300 をArduino IDE で使えるように環境構築しましたので
今回は実際にLoRaWANゲートウェイに接続してみます。
先ずは自分が良く使っている福岡市LoRaWAN実証実験に接続します。
(福岡市に在住の皆様限定になってしまいますが、他の接続先でも基本は変わらないと思います。)

Arduino公式ページでLoRaWAN接続用のサンプルプログラムが公開されています。

なお、このサンプルプログラムはOTAAモードでの接続となります。
OTAAとABPの違いはこちらの記事を参考にしてください。

公開されているサンプルプログラム

/*
  Lora Send And Receive
  This sketch demonstrates how to send and receive data with the MKR WAN 1300 LoRa module.
  This example code is in the public domain.
*/

#include <MKRWAN.h>

LoRaModem modem;

// Uncomment if using the Murata chip as a module
// LoRaModem modem(Serial1);

#include "arduino_secrets.h"
// Please enter your sensitive data in the Secret tab or arduino_secrets.h
String appEui = SECRET_APP_EUI;
String appKey = SECRET_APP_KEY;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  while (!Serial);
  // change this to your regional band (eg. US915, AS923, ...)
  if (!modem.begin(EU868)) {
    Serial.println("Failed to start module");
    while (1) {}
  };
  Serial.print("Your module version is: ");
  Serial.println(modem.version());
  Serial.print("Your device EUI is: ");
  Serial.println(modem.deviceEUI());

  int connected = modem.joinOTAA(appEui, appKey);
  if (!connected) {
    Serial.println("Something went wrong; are you indoor? Move near a window and retry");
    while (1) {}
  }

  // Set poll interval to 60 secs.
  modem.minPollInterval(60);
  // NOTE: independently by this setting the modem will
  // not allow to send more than one message every 2 minutes,
  // this is enforced by firmware and can not be changed.
}

void loop() {
  Serial.println();
  Serial.println("Enter a message to send to network");
  Serial.println("(make sure that end-of-line 'NL' is enabled)");

  while (!Serial.available());
  String msg = Serial.readStringUntil('\n');

  Serial.println();
  Serial.print("Sending: " + msg + " - ");
  for (unsigned int i = 0; i < msg.length(); i++) {
    Serial.print(msg[i] >> 4, HEX);
    Serial.print(msg[i] & 0xF, HEX);
    Serial.print(" ");
  }
  Serial.println();

  int err;
  modem.beginPacket();
  modem.print(msg);
  err = modem.endPacket(true);
  if (err > 0) {
    Serial.println("Message sent correctly!");
  } else {
    Serial.println("Error sending message :(");
    Serial.println("(you may send a limited amount of messages per minute, depending on the signal strength");
    Serial.println("it may vary from 1 message every couple of seconds to 1 message every minute)");
  }
  delay(1000);
  if (!modem.available()) {
    Serial.println("No downlink message received at this time.");
    return;
  }
  char rcv[64];
  int i = 0;
  while (modem.available()) {
    rcv[i++] = (char)modem.read();
  }
  Serial.print("Received: ");
  for (unsigned int j = 0; j < i; j++) {
    Serial.print(rcv[j] >> 4, HEX);
    Serial.print(rcv[j] & 0xF, HEX);
    Serial.print(" ");
  }
  Serial.println();
}

このプログラムを Arduino IDE の新しいプログラムとしてコピペしてください。

とりあえずこのままコンパイルしてみると当然ながら エラー となります。
(コンパイルは ✔ ボタンをクリックします)

エラーの内容としては
1. MKRWAN.h が無い
2. arduino_secrets.h が無い
3. SECRET_APP_EUI と SECRET_APP_KEY が定義されていない
となります。

1つずつ潰していきます。
1.の MKRWAN.h に関しては MKRWAN library のインストールが必要となります。

MKRWAN library のインストール
スケッチ ⇒ ライブラリをインクルード ⇒ ライブラリを管理 の順にクリックして
とクリックして ライブラリマネージャー を起動します。

ライブラリマネージャーが表示されたら 検索入力欄に [MKRWAN] と入力してください。
以下のように表示が変わりますので
Support library for MKR WAN 1300 をインストールしてください。

正常にインストールされると表示が以下のようになります。

2.の arduino_secrets.h に関しては arduino_secrets.h を調べたら
SECRET_APP_EUI と SECRET_APP_KEY を定義しているだけでした。
よって、 #include “arduino_secrets.h” の一行を削除(コメントアウト)して
String appEui = “”;
String appKey = “”;
のようにappEuiとappKey直接設定するようにしました。
これで 3. のエラーも無くなります。
修正したソースコードは次のようになります。

/*
  Lora Send And Receive
  This sketch demonstrates how to send and receive data with the MKR WAN 1300 LoRa module.
  This example code is in the public domain.
*/

#include <MKRWAN.h>

LoRaModem modem;

// Uncomment if using the Murata chip as a module
// LoRaModem modem(Serial1);

// #include "arduino_secrets.h"
// Please enter your sensitive data in the Secret tab or arduino_secrets.h
String appEui = "77xxxxxxxxxxxx48";
String appKey = "FFxxxxxxxxxxxxxxxxxxxxxxxxxxxxBB";

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  while (!Serial);
  // change this to your regional band (eg. US915, AS923, ...)
  if (!modem.begin(EU868)) {
    Serial.println("Failed to start module");
    while (1) {}
  };
  Serial.print("Your module version is: ");
  Serial.println(modem.version());
  Serial.print("Your device EUI is: ");
  Serial.println(modem.deviceEUI());

  int connected = modem.joinOTAA(appEui, appKey);
  if (!connected) {
    Serial.println("Something went wrong; are you indoor? Move near a window and retry");
    while (1) {}
  }

  // Set poll interval to 60 secs.
  modem.minPollInterval(60);
  // NOTE: independently by this setting the modem will
  // not allow to send more than one message every 2 minutes,
  // this is enforced by firmware and can not be changed.
}

void loop() {
  Serial.println();
  Serial.println("Enter a message to send to network");
  Serial.println("(make sure that end-of-line 'NL' is enabled)");

  while (!Serial.available());
  String msg = Serial.readStringUntil('\n');

  Serial.println();
  Serial.print("Sending: " + msg + " - ");
  for (unsigned int i = 0; i < msg.length(); i++) {
    Serial.print(msg[i] >> 4, HEX);
    Serial.print(msg[i] & 0xF, HEX);
    Serial.print(" ");
  }
  Serial.println();

  int err;
  modem.beginPacket();
  modem.print(msg);
  err = modem.endPacket(true);
  if (err > 0) {
    Serial.println("Message sent correctly!");
  } else {
    Serial.println("Error sending message :(");
    Serial.println("(you may send a limited amount of messages per minute, depending on the signal strength");
    Serial.println("it may vary from 1 message every couple of seconds to 1 message every minute)");
  }
  delay(1000);
  if (!modem.available()) {
    Serial.println("No downlink message received at this time.");
    return;
  }
  char rcv[64];
  int i = 0;
  while (modem.available()) {
    rcv[i++] = (char)modem.read();
  }
  Serial.print("Received: ");
  for (unsigned int j = 0; j < i; j++) {
    Serial.print(rcv[j] >> 4, HEX);
    Serial.print(rcv[j] & 0xF, HEX);
    Serial.print(" ");
  }
  Serial.println();
}

※ appEui と appKey は伏字にしています。

このプログラムをボードに書き込んでシリアルモニターを起動すると

シリアルモニタ

のように表示されます。(一部伏せています)
ここに表示されている
Your device EUI is: a8xxxxxxxxxxxx0b がゲートウェイにデバイスを登録する時に必要になります。

次にLoRaWANゲートウェイにディバイスの登録を行います。
この部分は利用するゲートウェイによって異なります、今回は福岡市LoRaWAN実証実験のゲートウェイを例とします。

Device activation は OTAA モードになります。
DevEUI: はシリアルモニターに表示されたデータを入力します。
AppEUI: 任意の16進数8桁のデータ
Appkey: 任意の16進数16桁のデータ
ここで設定した AppEUI と Appkey をプログラムの
appEui と appKey に設定します。

最後にプログラムをもう一ヶ所変更します。
それはLoRaの周波数の設定です。
LoRaの周波数はヨーロッパ、アメリカ、アジアで異なっているので、日本の周波数に合わせる必要があります。
ソースコードの setup関数内の
if (!modem.begin(EU868)) {
の部分を
if (!modem.begin(AS923)) {
に変更します。

この修正したプログラムを ARDUINO MKR WAN 1300 に書き込んで起動すると、問題が無ければゲートウェイとの通信が始まります。

ARDUINO MKR WAN 1300 の シリアルモニタ

ゲートウェイ側

ARDUINO MKR WAN 1300 から送った “abcd” が ゲートウェイに届いているのが確認出来ました。
なお、このサンプルプログラムではシリアルモニタから送ったデータがゲートウェイに送られます。

これで、ARDUINO MKR WAN 1300 で正常に LoRaWANゲートウェイ と通信出来ることが確認出来ました。
実際にはもっと作り込む必要がありますが ARDUINO MKR WAN 1300 が使えるという検証が目的でしたので、その目的は達成できたと思っています。

以下のプログラムが今回の最終形です。

/*
  Lora Send And Receive
  This sketch demonstrates how to send and receive data with the MKR WAN 1300 LoRa module.
  This example code is in the public domain.
*/

#include <MKRWAN.h>

LoRaModem modem;

// Uncomment if using the Murata chip as a module
// LoRaModem modem(Serial1);

// #include "arduino_secrets.h"
// Please enter your sensitive data in the Secret tab or arduino_secrets.h
String appEui = "77xxxxxxxxxxxx48";
String appKey = "FFxxxxxxxxxxxxxxxxxxxxxxxxxxxxBB";

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  while (!Serial);
  // change this to your regional band (eg. US915, AS923, ...)
  if (!modem.begin(AS923)) {
    Serial.println("Failed to start module");
    while (1) {}
  };
  Serial.print("Your module version is: ");
  Serial.println(modem.version());
  Serial.print("Your device EUI is: ");
  Serial.println(modem.deviceEUI());

  int connected = modem.joinOTAA(appEui, appKey);
  if (!connected) {
    Serial.println("Something went wrong; are you indoor? Move near a window and retry");
    while (1) {}
  }

  // Set poll interval to 60 secs.
  modem.minPollInterval(60);
  // NOTE: independently by this setting the modem will
  // not allow to send more than one message every 2 minutes,
  // this is enforced by firmware and can not be changed.
}

void loop() {
  Serial.println();
  Serial.println("Enter a message to send to network");
  Serial.println("(make sure that end-of-line 'NL' is enabled)");

  while (!Serial.available());
  String msg = Serial.readStringUntil('\n');

  Serial.println();
  Serial.print("Sending: " + msg + " - ");
  for (unsigned int i = 0; i < msg.length(); i++) {
    Serial.print(msg[i] >> 4, HEX);
    Serial.print(msg[i] & 0xF, HEX);
    Serial.print(" ");
  }
  Serial.println();

  int err;
  modem.beginPacket();
  modem.print(msg);
  err = modem.endPacket(true);
  if (err > 0) {
    Serial.println("Message sent correctly!");
  } else {
    Serial.println("Error sending message :(");
    Serial.println("(you may send a limited amount of messages per minute, depending on the signal strength");
    Serial.println("it may vary from 1 message every couple of seconds to 1 message every minute)");
  }
  delay(1000);
  if (!modem.available()) {
    Serial.println("No downlink message received at this time.");
    return;
  }
  char rcv[64];
  int i = 0;
  while (modem.available()) {
    rcv[i++] = (char)modem.read();
  }
  Serial.print("Received: ");
  for (unsigned int j = 0; j < i; j++) {
    Serial.print(rcv[j] >> 4, HEX);
    Serial.print(rcv[j] & 0xF, HEX);
    Serial.print(" ");
  }
  Serial.println();
}

今後実際にセンサーからのデータを送信したり、LoRaWANゲートウェイとして TTN に接続する検証を行いたいと思っています。


1件のコメント

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください