Rhino WAN
概要
Rhino WANは、LoRaWAN™対応のArduino®互換機です。 無線モジュールに統合されたSTM32L0はARM Cortex-M0+ベースの超低消費電力32bitマイコンで、Arduino IDEを使って簡単にプログラミングできます。 The Things Network V3などLoRaWAN™互換のネットワークに対応します。 入手性の良い乾電池数本、あるいは塩化チオニルリチウム電池1本で長期間の動作が期待でき、メンテナンスの難しい場所のノードに最適です。
本品はオープンソース・ハードウェアGrasshopperを日本国内向けに再設計した派生型で、設計データを公開しています。 ブレッドボードで試作した後、そのまま実機へ組み込むことができます。 本品はオープンソース版の設計を見直した改良版です。
ファームウェアはArduino® SAM D21プロセッサ搭載機種のコアから有志の手によって移植され、これらのソースコードはGitHubで管理されています。 高度なプログラミングが要求される場合は、SWD接続により従来の開発環境もお使いいただけます。 ST社提供のファームウェアI-CUBE-LRWANと開発環境Keil MDKが無償で利用できます。
ジャンパJP2は電源入力部の保護ダイオードをバイパスするもので、電源電圧からの電圧降下を無くすことができます。 この場合、USB電源5Vとの衝突や逆接続に対する保護が無くなりますので注意が必要です。 本品はUSBに関して独自のVendorIDを取得していませんので、ST社のUSBドライバが適用されます。
ユースケース
- 機械設備や施設の稼働管理
- メーター検針や在庫管理
- 健康診断と生存確認
- スマート農業や鳥獣被害対策
- 河川の水位監視
- 公共構造物の診断と異常検知
- 防犯と遠隔警備
- 動産や家畜の追跡
- 交通行動パターンの収集
- GPS/RSSI救難信号発信器
- コンクリートの打設管理
- 土砂災害の予兆検知
- 海洋観測データの収集
- ノード間通信によるM2M自律制御
仕様
- 基板仕様:FR4 4-Layer 40.64mmL×17.78mmW
- 無線モジュール:村田製作所 CMWX1ZZABZ-078
- 集積チップ:STM32L082CZY, SX1276
- PC接続コネクタ:USB2.0 microUSB TypeB(TypeAB形搭載)
- 定格電源電圧:3.5~5.5VDC
- レギュレータ出力:3.3VDC/150mA
- 無線送信時消費電流:47mA@14dBm
- 停止モード消費電流:2.1µA
- 動作温度範囲:-10~60℃
- 外形寸法図
- 回路図
- ピン配置表
- ファームウェア LoRaWAN™ Class A v1.0.2B
- Fritzing部品ファイル
周辺機材
本品でLoRa®通信を行うには、50ΩのU.FL-SMA変換ケーブルと下記の適合アンテナいずれかが必要です。 これらは電子部品の通販サイトで購入することができます。
- 変換ケーブル:LPRS ARW-CAB-SMA-UFL-10, Taoglas CAB.719, Taoglas CAB.721
- 適合アンテナ:LPRS ANT-SS900
- 適合アンテナ:Linx Technologies ANT-916-CW-HWR-SMA
任意の無線機材と組み合わせる場合は、工事設計認証(技適)を維持するため無線モジュール製造元が指定するアンテナ利得の要件を満たす必要があります。
使用方法
- Arduino IDEの[ファイル]-[環境設定]-[追加のボードマネージャのURL]に以下のURLを登録します。
https://www.cyrola.co.jp/archive/package_cyrola_rhino_index.json - [ツール]-[ボード]-[ボードマネージャ...]から、"STM32L0 Boards by Cyrola Inc"パッケージをインストールします。
- [ツール]-[ボード]-[STM32L0 Boards]から、"Rhino-WAN-L082CZ"を選択します。
- データ転送用USBケーブルで本品をパソコンに接続します。
- [ツール]-[シリアルポート]から、"Rhino-WAN-L082CZ"と表示されたCOMポートを選択します。
- [ツール]-[シリアルモニタ(9600bps)]に表示されるDeviceEUI※をメモに書き留めてください。 通電して15秒後にDeviceEUIを表示し、その後LEDが点滅します。
- 別のボードでシリアル通信を試みる場合は、都度Arduino IDEを再起動してください。
AREFピンから基準電圧を入力しない場合は、ジャンパJP1を短絡して3V3に接続してください。 I2Cポートにはプルアップ抵抗が入っていません。 必要に応じて3V3にプルアップしてください。
本品をパソコンに接続すると、スケッチが動作する"Runモード"で起動します。 スケッチを書き込む時は自動的に"DFUモード"に切り替わります。 BOOT
ボタンを押しながらRESET
ボタンをクリックすると"DFUモード"で再起動します。 RESET
ボタンを単独でクリックすると"Runモード"で再起動します。
※ STM32L0のユニークデバイスIDから生成された数列です。 EUI-64™準拠のDeviceEUIが必要な場合は、ノードアドレスROMをご利用ください。 使い易いモジュールがこちらにあります。
電源特性
バッテリ駆動では、稼働時間、環境温度、機器の寸法も考慮してバッテリの構成を決める必要があります。 右図は、一定負荷における入力電圧VINとレギュレータ出力電圧3V3の関係をグラフにしたものです。 実線は保護ダイオードD2が入っている通常回路で、破線はジャンパJP2で保護ダイオードをバイパスした場合を示します。
水平の破線はSX1276が20dBm(100mW)の出力で無線送信できる供給電圧の最低ラインで、フルスペックの動作にはシステム電圧がこれを上回っている必要があります。 無線モジュールの最低動作電圧は2.2Vで、この水準では無線送信の最大出力が低下します。 なお本邦では電波法により13dBm(20mW)以下の出力に制限されています。
保護ダイオードをバイパスすることで、VF × ICCで生じる電力損失が無くなります。 これにより電源電圧の低下に対して持久力が増すほか、ユーザ側の回路を工夫してVINに複数の電源ソースを接続することも考えられます。
ICCが減少すると保護ダイオードのVFも小さくなり、3V3ピンが無負荷かつ停止モードにおいて、VFは40mV程度まで小さくなります。
サンプルスケッチ
DeviceEUIを確認する
次のスケッチを書き込むとシリアルモニタ(9600bps)にDeviceEUIを表示し、LEDが点滅します。 工場出荷時に書き込まれたスケッチです。
/* This example code is in the public domain. */
#include "LoRaWAN.h"
char buffer[32];
void setup(void)
{
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
// 15秒待機
delay(15000);
LoRaWAN.begin(AS923);
if (Serial == 1)
{
// DeviceEUI表示
Serial.println("devEUI request");
LoRaWAN.getDevEui(buffer, 18);
Serial.println(buffer);
}
}
void loop(void)
{
// LED点滅
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
外部割り込みで停止モードから復帰する
本品のA4ポートを10kΩ抵抗でGNDにプルダウンしてください。 次のスケッチを書き込むと、停止モードで割り込みを待ちます。 A4ポートにHIGH信号を入力すると、Runモードに復帰してボード上のLEDが1秒間点灯します。 その後、停止モードに戻ります。
/* This example code is in the public domain. */
#include "STM32L0.h"
volatile bool state = false;
void setup(void)
{
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
attachInterrupt(A4, WKUP1, RISING);
}
void loop(void)
{
if (state == true)
{
state = false;
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
}
STM32L0.stop();
}
void WKUP1(void)
{
STM32L0.wakeup();
state = true;
}
アナログ入出力機能をテストする
本品のA0ポートとA2ポートを直結し、次のスケッチを書き込むとアナログ入出力のフィードバックテストを始めます。 テスト開始時にSTM32L0のUniqueIDとDeviceEUI、VDDA(AREF)電圧、USB電源接続の有無、内部温度をシリアルモニタに表示します。
/* This example code is in the public domain. */
#include "STM32L0.h"
#include "LoRaWAN.h"
#define myDAC A0
#define myADC A2
uint32_t UID[3] = {0, 0, 0};
char buffer[32];
float VDDA, VBUS, Temperature;
float DACvalue = 0.0f;
float ADCvalue = 0.0f;
void setup(void)
{
Serial.begin(9600);
delay(5000);
Serial.println("Serial enabled!");
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
STM32L0.getUID(UID);
Serial.print("STM32L0 MCU UID = 0x"); Serial.print(UID[0], HEX); Serial.print(UID[1], HEX); Serial.println(UID[2], HEX);
LoRaWAN.getDevEui(buffer, 18);
Serial.print("STM32L0 Device EUI = "); Serial.println(buffer);
pinMode(myADC, INPUT);
analogReadResolution(12); // 12-bit ADC instead of 8-bit default
pinMode(myDAC, OUTPUT);
}
void loop(void)
{
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
VDDA = STM32L0.getVDDA();
VBUS = STM32L0.getVBUS();
Temperature = STM32L0.getTemperature();
Serial.print("VDDA = "); Serial.println(VDDA, 2);
if(VBUS == 1) Serial.println("USB Connected!");
Serial.print("STM32L0 MCU Temperature = "); Serial.println(Temperature, 2);
for (int ii = 0; ii < 256; ii++)
{
analogWrite(myDAC, ii); // write/read voltage in 3.3/256 V increments every 100mSec
DACvalue = 3.30f * ((float) ii) / 255.0f; // should be written
delay(100);
ADCvalue = VDDA * ((float) analogRead(myADC)) / 4095.0f; // is actually read
Serial.print("DAC output is "); Serial.print(DACvalue, 3);
Serial.print(" V, ADC input is "); Serial.print(ADCvalue, 3); Serial.println(" V");
}
STM32L0.stop(5000);
}
The Things NetworkにABP接続しデータを送信する
本品にアンテナを接続し、3項目の定数とアンテナの利得を設定してください。 スケッチを書き込むとThe Things NetworkにABP接続し、データを送信し始めます。 このデータをCayenneに転送すると、地図上にピンが現れます。
/* This example code is in the public domain. */
#include "STM32L0.h"
#include "LoRaRadio.h"
#include "LoRaWAN.h"
// 以下3項目にThe Things Networkコンソール記載の定数を設定
const char *devAddr = "00000000"; // Device Address
const char *nwkSKey = "00000000000000000000000000000000"; // Network Session Key
const char *appSKey = "00000000000000000000000000000000"; // App Session Key
void setup(void)
{
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
Serial.begin(9600);
delay(1000);
LoRaRadio.begin(923200000);
LoRaRadio.setLnaBoost(true);
LoRaWAN.begin(AS923);
LoRaWAN.setMaxEIRP(13.0f);
LoRaWAN.setADR(false);
LoRaWAN.setDataRate(2);
// アンテナ利得 Default: +2.0dBi
// LoRaWAN.setAntennaGain(2.0f); // ANT-SS900
LoRaWAN.setAntennaGain(1.2f); // ANT-916-CW-HWR-SMA
// 空中線電力13dBm以下, ARIB STD-T108規定
LoRaWAN.setTxPower(13.0f);
// 送信前キャリアセンス動作, ARIB STD-T108規定
while (!LoRaRadio.sense(-80, 5)) delay(50);
// ABP認証で接続
LoRaWAN.joinABP(devAddr, nwkSKey, appSKey);
if (Serial == 1) Serial.println("JOIN( )");
}
void loop(void)
{
if (LoRaWAN.joined() && !LoRaWAN.busy())
{
if (Serial == 1)
{
Serial.print("TRANSMIT( ");
Serial.print("TimeOnAir: ");
Serial.print(LoRaWAN.getTimeOnAir());
Serial.print(", NextTxTime: ");
Serial.print(LoRaWAN.getNextTxTime());
Serial.print(", MaxPayloadSize: ");
Serial.print(LoRaWAN.getMaxPayloadSize());
Serial.print(", DR: ");
Serial.print(LoRaWAN.getDataRate());
Serial.print(", TxPower: ");
Serial.print(LoRaWAN.getTxPower(), 1);
Serial.print("dbm, UpLinkCounter: ");
Serial.print(LoRaWAN.getUpLinkCounter());
Serial.print(", DownLinkCounter: ");
Serial.print(LoRaWAN.getDownLinkCounter());
Serial.println(" )");
}
// 送信前キャリアセンス動作, ARIB STD-T108規定
while (!LoRaRadio.sense(-80, 5)) delay(50);
// CayenneLPPフォーマットで送信
// https://developers.mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload
// Mt.Fuji WGS84
LoRaWAN.beginPacket();
LoRaWAN.write(0x01); // 1バイト データチャンネル: Ch.1
LoRaWAN.write(0x88); // 1バイト データタイプ: GPS
LoRaWAN.write(0x05); // 3バイト 緯度 35.3607
LoRaWAN.write(0x65);
LoRaWAN.write(0x47);
LoRaWAN.write(0x15); // 3バイト 経度 138.7274
LoRaWAN.write(0x2B);
LoRaWAN.write(0x0A);
LoRaWAN.write(0x05); // 3バイト 高度 3772
LoRaWAN.write(0xC1);
LoRaWAN.write(0x70);
LoRaWAN.endPacket();
// 送信休止時間, ARIB STD-T108規定
delay(50);
}
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
// 停止モード
STM32L0.stop(9000);
}
The Things NetworkにOTAA接続しデータを送信する
The Things NetworkにOTAA接続し、データを送信し始めます。 セッションが切れた場合は再接続します。
/* This example code is in the public domain. */
#include "STM32L0.h"
#include "LoRaRadio.h"
#include "LoRaWAN.h"
// 以下3項目にThe Things Networkコンソール記載の定数を設定
const char *appEui = "0000000000000000";
const char *appKey = "00000000000000000000000000000000";
const char *devEui = "0000000000000000";
void setup(void)
{
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
Serial.begin(9600);
delay(10000);
LoRaRadio.begin(923200000);
LoRaRadio.setLnaBoost(true);
LoRaWAN.begin(AS923);
LoRaWAN.setMaxEIRP(13.0f);
LoRaWAN.setADR(false);
LoRaWAN.setDataRate(2);
LoRaWAN.setSaveSession(true);
// アンテナ利得 Default: +2.0dBi
// LoRaWAN.setAntennaGain(2.0f); // ANT-SS900
LoRaWAN.setAntennaGain(1.2f); // ANT-916-CW-HWR-SMA
// 空中線電力13dBm以下, ARIB STD-T108規定
LoRaWAN.setTxPower(13.0f);
// 送信前キャリアセンス動作, ARIB STD-T108規定
while (!LoRaRadio.sense(-80, 5)) delay(50);
// OTAA認証で接続
LoRaWAN.joinOTAA(appEui, appKey, devEui);
if (Serial == 1) Serial.println("JOIN( )");
}
void loop(void)
{
if (!LoRaWAN.busy())
{
if (!LoRaWAN.linkGateways())
{
// 送信前キャリアセンス動作, ARIB STD-T108規定
while (!LoRaRadio.sense(-80, 5)) delay(50);
// OTAA認証で再接続
LoRaWAN.rejoinOTAA();
if (Serial == 1) Serial.println("REJOIN( )");
}
if (LoRaWAN.joined())
{
if (Serial == 1)
{
Serial.print("TRANSMIT( ");
Serial.print("TimeOnAir: ");
Serial.print(LoRaWAN.getTimeOnAir());
Serial.print(", NextTxTime: ");
Serial.print(LoRaWAN.getNextTxTime());
Serial.print(", MaxPayloadSize: ");
Serial.print(LoRaWAN.getMaxPayloadSize());
Serial.print(", DR: ");
Serial.print(LoRaWAN.getDataRate());
Serial.print(", TxPower: ");
Serial.print(LoRaWAN.getTxPower(), 1);
Serial.print("dbm, UpLinkCounter: ");
Serial.print(LoRaWAN.getUpLinkCounter());
Serial.print(", DownLinkCounter: ");
Serial.print(LoRaWAN.getDownLinkCounter());
Serial.println(" )");
}
// 送信前キャリアセンス動作, ARIB STD-T108規定
while (!LoRaRadio.sense(-80, 5)) delay(50);
// CayenneLPPフォーマットで送信
// https://developers.mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload
// Mt.Fuji WGS84
LoRaWAN.beginPacket();
LoRaWAN.write(0x01); // 1バイト データチャンネル: Ch.1
LoRaWAN.write(0x88); // 1バイト データタイプ: GPS
LoRaWAN.write(0x05); // 3バイト 緯度 35.3607
LoRaWAN.write(0x65);
LoRaWAN.write(0x47);
LoRaWAN.write(0x15); // 3バイト 経度 138.7274
LoRaWAN.write(0x2B);
LoRaWAN.write(0x0A);
LoRaWAN.write(0x05); // 3バイト 高度 3772
LoRaWAN.write(0xC1);
LoRaWAN.write(0x70);
LoRaWAN.endPacket();
// 送信休止時間, ARIB STD-T108規定
delay(50);
}
}
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
// 停止モード
STM32L0.stop(9000);
}
その他のサンプルはこちらをご覧ください。
ダッシュボードの利用例
ThingsBoardでデータを表示する
ThingsBoardは、高度なユーザ管理機能を備えたオープンソースのダッシュボードです。 有償のProfessional Editionはホワイトラベリングに対応し、自社ブランドを冠したIoTサービスを提供することができます。
ここではThe Things Network V2とThingsBoard Professional Edition(TBPE)を統合して、サーモスタットから取得した2バイトの温度データを表示します。 TBPEサーバーの用意ができ、TTNに登録されたゲートウェイがデータを受信できる状態で作業を始めます。
TTNのApplicationsにtb_platformを追加し、そのDevicesにthermostat_aを登録します。 続いて、Custom - decoderを以下のように記述します。
function Decoder(bytes, port) {
var tempC = (bytes[0] << 8 | bytes[1]);
return {
temperature: tempC / 100
}
}
試験的に 07 E9 を投入すると、以下のようにデコードされます。
{
"temperature": 20.25
}
TBPEにテナント管理者でログインし、Data Converterを追加します。
Name:ttn_converter
Type:Uplink
Decoderは以下のように記述します。 TTNとTBPEでは扱うフィールド名が異なるため、これらが対応するように値を割り付けています。
var data = decodeToJson(payload);
var deviceName = data.dev_id;
var deviceType = data.app_id;
var result = {
deviceName: deviceName,
deviceType: deviceType,
telemetry: {
temperature: data.payload_fields.temperature
}
};
function decodeToString(payload) {
return String.fromCharCode.apply(String, payload);
}
function decodeToJson(payload) {
var str = decodeToString(payload);
var data = JSON.parse(str);
return data;
}
return result;
続いて、Integrationを追加します。
Name:ttn_integration
Type:TheThingsNetwork(ドロップダウンリストから選択)
Uplink data converter:ttn_converter(ドロップダウンリストから選択)
Region:asia-se
Application ID:tb_platform
Access Key:(TTNのtb_platformで使用しているAccess Keyを貼り付け)
TBPEが正しくデータを受信できるか検証するため、TTNのApplications > tb_platform > Devices > thermostat_a - SIMULATE UPLINKから 07 E9 を試験送信します。 これまでの設定が正しければ、TBPEのDevice Group > All > thermostat_a > Latest telemetryが Key=temperature, Value=20.25 を受信します。 Rhino WANからデータを送信しても、同様の結果が得られます。
受信したテレメトリ値をクリックすると、右上にShow on widgetボタンが現れます。 ここから値の表示に適したウィジェットを選び、Add to dashboardボタンでダッシュボードに追加します。
こんなときは
スケッチが書き込めません
Arduino IDEでスケッチを書き込む際、エラーメッセージが出て正しく書き込めていないことがあります。 このような時は手動で"DFUモード"に切り替えます。 BOOT
ボタンを押しながらRESET
ボタンをクリックし、"DFUモード"で再起動します。
それでも書き込めない時は、デバイスドライバを更新します。 こちらからZadig 2.6をダウンロードします。 zadig-2.6.exeを起動して、[Options]-[List All Devices]にチェックを入れます。 "DFUモード"でボードを再起動すると、プルダウンリストから STM32 BOOTLOADER が選べるようになるのでこれを選択し、書き換え先に WinUSB (v6.1.7600.16385) を指定してデバイスドライバを更新します。
プルダウンリストに Rhino WAN とある場合は、"DFUモード"に切り替えてください。
COMポートが現れません
パソコンとシリアル通信をする際、ボードを接続してもパソコン側にCOMポートが現れないことがあります。 このような時は、デバイスドライバを更新します。 こちらからZadig 2.6をダウンロードします。 zadig-2.6.exeを起動して、[Options]-[List All Devices]にチェックを入れます。 RESET
ボタンをクリックし、"Runモード"でボードを再起動します。 プルダウンリストから Rhino WAN が選べるようになるのでこれを選択し、書き換え先に USB Serial (CDC) を指定してデバイスドライバを更新します。
プルダウンリストに STM32 BOOTLOADER とある場合は、"Runモード"に切り替えてください。
価格
配送方法はご希望の条件でお見積りいたします。
- Rhino-WAN-L082CZ 1台 6,820円(税込)
- 梱包送料 別途見積
- 梱包送料 2台まで 264円(税込) クリックポスト利用時
- 供給状況:量産中
お客様の用途に合わせて、基板設計の変更・追加を承ります。
オンライン販売
1台だけご入用の場合はクレジットカードで購入いただけます。
- Rhino-WAN-L082CZ 1台 7,084円(梱包送料込, 税込)
- クリックポストを利用します。
- 配送先は日本国内に限ります。