M5Stack BasicでSigfox RFモニタを作る

M5Stack Basicを使ってSigfoxの超簡易版無線電波測定ツールを作ってみます。

>ただし、ここで取得できる電波状況はSigfoxの下り通信を使い、代表局のBase Station IDとそのRSSIを取得するだけのものですので、本来のSigfoxの品質評価指標（[Link Quality Indicator: LQI](https://qiita.com/ghibi/items/11acba7b61ad986a6559)）とはことなります。LQIを取得するためには、Data Advanced Callbackを使用する必要があり、その方法は[こちら](https://qiita.com/ghibi/items/48613708c36a9fd6d893)を参考にしてください。

#準備するもの
今回は、M5StackとSigfox Breakout Board [BRKWS01]を使います。

- [M5Stack Basic](https://www.switch-science.com/catalog/3647/)
- [M5Stack用プロトモジュール](https://www.switch-science.com/catalog/3650/) *これはなくてもとりあえず動くものは作れます
- [Sigfox Breakout Board [BRKWS01]] (https://www.kccs-iot.jp/solution/product/device32/)

![picture1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/e1816822-1147-b300-cc17-d27f6a815dd3.png)
左から、M5Stack Basic、プロトモジュール、Sigfox Breakout Boardとなっています。

#M5Stackでの開発準備
M5Stackは、[Arduino IDE](https://www.arduino.cc/en/Main/software)と[M5Flow（MicroPython）](http://flow.m5stack.com/)の2種類の開発環境が用意されていますが、ここでは、M5Flowを使うためには、M5Stackのファームウェアをアップデートしないといけないということもあり、Arduino IDEを使用することとします。
##Arduino IDEの準備
Arduino IDEは[こちら](https://www.arduino.cc/en/Main/software)からダウンロード、インストールしてください。Arduino IDEを使う場合は、M5Stack用に下記のソフトウェアおよびドライバが必要となります。

- ESP32ボード定義
- M5Stackライブラリ
- CP210X Driver

###ESP32ボード定義のインストール
Arduino IDEの[ファイル]_[環境設定]を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/8a5aeb2b-08b5-035b-dcfe-7b48ce686187.png)
追加のボードマネージャのURLに下記URLを貼り付けます。

`https://dl.espressif.com/dl/package_esp32_index.json`
その後、[ツール]\_[ボード]\_[ボードマネージャ]メニューを選択し、ボードマネージャを開きます。ESP32と検索すれば、`esp32 by Espressif Systems`が出てくると思いますので、インストールします。
###M5Stackライブラリのインストール
次に、[ツール]_[ライブラリの管理]メニューからライブラリマネージャを開き、`M5Stack by M5Stack` をインストールします。（M5Stackで検索）

###CP210X Driver
CP210Xドライバは、M5StackとPCとを接続するUDBケーブル用のドライバとなっており、[M5Stackの公式ページ](https://m5stack.com/pages/download)から、ご自身のOSにあったドライバをダウンロード、インストールします。

#M5StackとSigfox Breakout Boardを接続
まずは、プロトモジュールを使用せずに、M5Stack付属のピンケーブルを使ってSigfox Breakout Boardを接続します。接続後のイメージは下の写真のようになります。
![IMG_4858.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/460fee55-a6b2-260b-4c42-6241a876bdd4.jpeg)
少し分かりにくいので、配線例を下記に記します。Breackout Boardに3.3Vの入力と、UART用のTX/RXを接続することとなります。Breakout Boardの使い方については、[こちら](https://qiita.com/ghibi/items/37154bad78d9bb57e335)を参考にしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/eec1d520-5161-bec8-1e7c-f1c3728837ed.png)

#Sigfox下り通信
冒頭にも述べた通り、今回の仕組みは、Sigfoxの下り通信を使って返されるBase Station IDとRSSIを取得し、M5Stack上に表示するというものになっていますので、少しSigfox下り通信について説明しておきます。
Sigfoxの下り通信は、デバイスから上りメッセージを送信する際に、下り要求オプションを追加する事から始まります。通常上りメッセージは、SigfoxクラウドからアプリケーションサーバにCallbackされますが、その時に下り要求オプションが付いているメッセージは、アプリケーションサーバでJSON形式の応答を返すことにおり、元のデバイスまで、その下りメッセージが送信される仕組みとなっています。この仕組みを有効にするには、SigfoxクラウドのDevice Type設定でDownlink modeをCallbackに設定する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/18c145cb-ebfa-7183-60ee-ed109be079a4.png)

>ちなみに、上りメッセージは複数局で受信されますが、下りメッセージアは、最も有効な局（一局）から返信されます。

#Sigfox下りメッセージの準備
Sigfox下りメッセージに対応するために、SigfoxクラウドDevice Type設定のDownlink dataの設定をします。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/47d9d9f1-aa4b-260a-7cee-f93967a0af95.png)
Downlink modeは、通常はアプリケーションｓサーバを経由するため、**CALLBACK**を選択しますが、今回は、アプリケーションサーバを経由しない（つまり、Sigfoxクラウドから直接ダウンリンクを返す）ようにしたいので、**DIRECT**を選択します。
DIRECTを選択した場合、**Downlink data in hexa**という入力項目が有効になります。ここでは、デフォルト設定の通り、`{tapid}0000{rssi}`と設定しておきます。
>tapidは、下りメッセージを送信する局のID、rssiはその局が受信したメッセージの受信レベルを意味します。

#サンプルコード
M5Stack側のサンプルコードを以下に記します。

```m5stack.c
#include <M5Stack.h>
void setup() {
  M5.begin(true, false, true);
    
  M5.Power.begin();

  Serial.begin(9600);
  Serial2.begin(9600, SERIAL_8N1, 16, 17);

  M5.Lcd.clear(BLACK);
  M5.Lcd.setTextColor(YELLOW);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setCursor(65, 10);
  M5.Lcd.println("Sigfox RF monitor");
  M5.Lcd.setCursor(0, 35);
  M5.Lcd.println("A: Send Message");
  M5.Lcd.println("B: Send Message with DL");
  M5.Lcd.println("C: Check Device ID");
  M5.Lcd.setTextColor(RED);
}

void loop() {
  if (Serial2.available()) {
    displayResults(Serial2.readString());
  }
  M5.update();
 
  if (M5.BtnA.wasReleased()) {
    M5.Lcd.println("Send Message.");
    Serial2.println("AT$SF=1234");
  } else if (M5.BtnB.wasReleased()) {
    M5.Lcd.println("Send Message with Ack.");
    Serial2.println("AT$SF=5678,1");    
  } else if (M5.BtnC.wasReleased()) {
    M5.Lcd.print("Device ID: ");
    Serial2.println("AT$I=10");
  }
}

void displayResults(String ack)
{
  M5.Lcd.println(ack);
  int i = ack.indexOf("RX=");
  if (i >= 0) {
    ack.replace(" ", "");
    String bs = ack.substring(i + 6, i + 11);
    String rs = ack.substring(i + 15);
    signed int rssi = (int16_t)(strtol(rs.c_str(), NULL, 16));
    M5.Lcd.print("BSID: ");
    M5.Lcd.println(bs);
    M5.Lcd.print("RSSI: ");
    M5.Lcd.println(rssi);
  }
}
```
3種類のボタン（A/B/C）に応じたコマンドを用意していますが、RSSI確認に使うのは、ボタンBを押した時です。
ボタンBを押すと、`AT$SF=5678,1`というフレーム送信コマンドが、Serial2からBreakout Board側に送られるようにしています。5678は適当なPayloadですが、その後の**1**が、下り要求オプションとなります。
下り受信までには数十秒要しますが、送られてきた下りメッセージを、このモジュールは`RX=`で始まる応答として返すようです。その後のデータ配列は、Sigfoxクラウドで設定したDownlink data in hexaに従います。今回の場合は{tapid}0000{rssi}です。

#動作確認
Arduino IDEで、ボードの選択が**M5Stack-Core-ESP32**となっていること、シリアルポートがM5Stackとの接続ポートであることを確認後、スケッチのコンパイル及びマイコンボードへの書き込みを行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/665f583d-a10e-6044-15e7-8e673a73dcb4.png)
無事成功し、Bボタンを押すと、下の写真のように受信レベルが確認できると思います。
![IMG_4859.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/fcd7ba05-e502-003e-ef2b-a408a6f3b581.jpeg)

#M5Stackプロトモジュールで
Breakout Board基板が丸出しというのも気になる場合、M5Stackプロトモジュール内にモジュールを配置することにより、少しはスマートになるかと思います。プロトモジュールにはケーブル出しの穴もあるので、外部アンテナも付けやすいかと思います。（中段のグレーのモジュールがM5Stackプロトモジュールです。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/e22f2812-a095-10fb-f4cb-407acfd5a270.png)
ただ、純正のプロトモジュールのコネクタからの線だしが面倒なので、はんだ付け時にはがっかりするかもしれませんが。

[Sigfox Japan KCCS](https://qiita.com/organizations/sigfox)
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172313/d6ad10bc-75ba-8124-14d4-f144657c6473.png)](https://twitter.com/ghibi)