前回はUnitCatM によるHTTP通信を確認しました。
M5Stack UnitCatM で HTTP通信
ここではUnitCatM を制御するマイコンの検討を行いました。
目標
本件の目標は以下の通りです。
- 格安データSIM探して契約:現在調査中
- 座標情報取得:基地局の位置情報で検討中
- 外部への通信:HTTP通信で決定
- コントローラ選定
- パワーセーブ
- ビンに詰める
- 川に投げる
ここでは目標④、⑤の検討を実施いたしました

コントローラ検討
これまではPCからATコマンドをおくって動作確認しておりましたが、実際にはマイコンからコマンド制御する必要があります。
ここではコントローラとしてSeeeduino XIAOを採用しました。
小さくてカワイイですし、しっかりめのパワーセーブ機能もあるためです。
[amazonjs asin=”B086KXY929″ locale=”JP” title=”Seeed Studio Seeeduino XIAO-Arduino IDE 互換ボード SAMD21 Cortex M0+搭載 ブレッドボード互換 USB Type-C(3pcs)”]
XIAOのシリアル端子(D6, D7)からコマンドを送受信します。

しっかりシーケンスを組んで通信の開始や位置情報の取得、HTTP送信を実施します。


パワーセーブの検討
マイコン XIAO
XIAOは送信時以外はSleepさせて消費電力を抑えます。
サンプルコードWakeUpOnRTCInterrupt.ino のようにRTCによる設定時刻で起床するようにしたかったのですが
RTCInt.h がないとエラーがでるので
RTCの設定にはSeeed_Arduino_RTCライブラリを使用しました。
消費電流は Vin = 5Vで
起床時:14.4mA
Sleep時:1.46mA
とSleepが大きく効いておりました。
以下の参考記事によるとパワーオンLEDを切ると更に消費電力が減るとのことです。
場合によってはLED排除も検討したいです。
参考

システム構成
バッテリは未定ですが現状のシステム構成は以下の通りです。
XIAOでATコマンドを送信し、更にDCDCのENピンを制御してUnitCatMをON/OFFします。

部品
- Seeeduino XIAO
[amazonjs asin=”B086KXY929″ locale=”JP” title=”Seeed Studio Seeeduino XIAO-Arduino IDE 互換ボード SAMD21 Cortex M0+搭載 ブレッドボード互換 USB Type-C(3pcs)”]
- 5V 昇圧 DCDCコンバータ
[bc url=”https://akizukidenshi.com/catalog/g/gK-13065/”]
- SIM7080G CAT-M/NB-IoT Unit
[bc url=”https://shop.m5stack.com/products/sim7080g-cat-m-nb-iot-unit?variant=40493802160300″]


Arduino IDEコード
#include <EnergySaving.h>
#include "RTC_SAMD21.h"
#include "DateTime.h"
EnergySaving nrgSave;
RTC_SAMD21 rtc;
int state = 0;
int retry = 5;
String reply;
String location = "test";
void setup() {
Serial.begin(115200); //USBシリアル
Serial1.begin(115200); //ATコマンド シリアル
pinMode(5, OUTPUT); //DCDC ENピン
digitalWrite(5, LOW);
rtc.begin();
Serial.begin(115200);
nrgSave.begin(WAKE_RTC_ALARM);
}
void loop() {
int num = 0;
//ATコマンド
switch (state) {
case 0:
Serial1.write("AT\r\n");
break;
case 1:
Serial1.write("AT+CNACT=0,1\r\n");
break;
case 2:
Serial1.write("AT+CLBS=4,0\r\n");
break;
case 31:
Serial1.write("AT+SHCONF=\"URL\",\"http://データ送信先サーバ\"\r\n");
break;
case 32:
Serial1.write("AT+SHCONF=\"BODYLEN\",1024\r\n");
break;
case 33:
Serial1.write("AT+SHCONF=\"HEADERLEN\",350\r\n");
break;
case 34:
Serial1.write("AT+SHCONN\r\n");
break;
case 4:
Serial1.write("AT+SHSTATE?\r\n");
break;
case 5:
Serial1.print("AT+SHREQ=\"/hoge?location=" + location + "\", 1\r\n");
break;
}
//通信後Sleep
if(state == 6){
digitalWrite(5, LOW); //CAT-M OFF
state = 0;
//RTC時刻設定
DateTime now = DateTime(2021, 1, 1, 0, 0, 0); //DateTime(年,月,日,時間,分,秒)
rtc.adjust(now);
now = rtc.now();
//RTCアラームセット
DateTime alarm = DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute() + 1, now.second());
rtc.setAlarm(alarm);
rtc.enableAlarm(rtc.MATCH_HHMMSS);
//sleep
nrgSave.standby();
}
//5V Boost DCDC ON
if(state == 0){
digitalWrite(5, HIGH); //CAT-M ON
}
//HTTP getリクエスト
while(state == 5){
if(Serial1.available()) {
reply = Serial1.readStringUntil('\n');
Serial.println(reply);
}
num++;
if(reply.indexOf("SHREQ: \"GET\",200") >= 0) {
state = 6;
break;
}else if(num >= retry){
break;
}
delay(300);
}
//HTTPステート確認
while(state == 4){
if(Serial1.available()) {
reply = Serial1.readStringUntil('\n');
Serial.println(reply);
}
num++;
if(reply.indexOf("SHSTATE: 1") >= 0) {
state = 5;
break;
}else if(num >= retry){
break;
}
delay(300);
}
//HTTP設定
while(state == 31 || state == 32 || state == 33 || state == 34){
if(Serial1.available()) {
reply = Serial1.readStringUntil('\n');
Serial.println(reply);
}
num++;
if(reply.indexOf("OK") >= 0) {
if(state == 31) state = 32;
else if(state == 32) state = 33;
else if(state == 33) state = 34;
else if(state == 34) state = 4;
break;
}else if(num >= retry){
break;
}
delay(300);
}
//基地局位置情報
while(state == 2){
if(Serial1.available()) {
reply = Serial1.readStringUntil('\n');
Serial.println(reply);
}
num++;
if(reply.indexOf("+CLBS:") >= 0) {
reply.replace(" ", "-");
reply.replace("\r", "-");
location = reply;
state = 31;
break;
}else if(num >= retry){
break;
}
delay(300);
}
//通信開始
while(state == 1){
if(Serial1.available()) {
reply = Serial1.readStringUntil('\n');
Serial.println(reply);
}
num++;
if(reply.indexOf("ACTIVE") >= 0) {
state = 2;
break;
}else if(num >= retry){
break;
}
delay(300);
}
//AT導通確認
while(state == 0){
if(Serial1.available()) {
reply = Serial1.readStringUntil('\n');
Serial.println(reply);
}
num++;
if(reply.indexOf("OK") >= 0) {
state = 1;
break;
}else if(num >= retry){
break;
}
delay(300);
}
Serial.println(state);
//Serial.println(location);
delay(1000);
}
void alarmMatch(){
Serial.println("WakeUP");
}
以下のシーケンスでATコマンドをXIAOからUnitCatMに送っています。
・AT導通確認
・ネットワーク通信開始
・基地局位置情報取得
・HTTP設定
・HTTPステート確認
・HTTP 基地局位置情報を付与して getリクエスト
HTTP getリクエスト送信後はRTCアラームを設定してnrgSave.standby();でスリープに入ります。
ここではRTC時刻を2021年1月1日 00:00:00に設定し、
アラームを1分後の2021年1月1日 00:01:00として起床するようにしています。
位置情報サーバ送信→1分スリープ→起床→‥‥を繰り返します。
消費電流は Vin = 3.7Vで
通信時:45~167mA
Sleep時:1.55mA
でした。
通信頻度を抑えればかなり長期の運用が可能なのではないでしょうか。

おわりに
ついにコントローラの選定もでき、消費電力も抑えれそうなことがわかってきました。
次回はデータSIMを契約して長期の動作確認を実施したいと考えております。
次の記事
M5Stack UnitCatM の 消費電力とデータSIM契約