M5Stack UnitCatM を Seeeduino XIAO で制御
前回はUnitCatM によるHTTP通信を確認しました。
ここではUnitCatM を制御するマイコンの検討を行いました。
目次
目標
本件の目標は以下の通りです。
- 格安データSIM探して契約:現在調査中
- 座標情報取得:基地局の位置情報で検討中
- 外部への通信:HTTP通信で決定
- コントローラ選定
- パワーセーブ
- ビンに詰める
- 川に投げる
ここでは目標④、⑤の検討を実施いたしました
コントローラ検討
これまではPCからATコマンドをおくって動作確認しておりましたが、実際にはマイコンからコマンド制御する必要があります。
ここではコントローラとしてSeeeduino XIAOを採用しました。
小さくてカワイイですし、しっかりめのパワーセーブ機能もあるためです。
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排除も検討したいです。
参考
UnitCatM
UnitCatMは電源の供給をイネーブルピン付きのDCDCから供給するようにし
通信時以外はXIAOでDCDCのENピンを制御して電源遮断でパワーセーブすることにしました。
これによって通信時以外のUnitCatMによる消費電力は0となります。
システム構成
バッテリは未定ですが現状のシステム構成は以下の通りです。
XIAOでATコマンドを送信し、更にDCDCのENピンを制御してUnitCatMをON/OFFします。
部品
- Seeeduino XIAO
- 5V 昇圧 DCDCコンバータ
- SIM7080G CAT-M/NB-IoT Unit
Arduino IDEコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
#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を契約して長期の動作確認を実施したいと考えております。