私は近くの里山地域に畑を借り、そこで野菜を育てながら、屋外でのIoT実証実験を行っています。
畑にモバイルWi-Fiルータを設置し、それを50Wソーラーパネルで常時稼働させることで、畑に設置したいくつかのIoTデバイス(主にM5Stamp Pico)やIoTカメラ(主にTimer Camera)で取得したデータをWebサーバに送信しています。
また、Wi-Fiの通信距離をのばすために、ESP32でつくったWi-Fi中継機も設置しています。
現状のシステム構成は以下のようになっています。
さて、先日「ESP-NOW」という無線通信方式について調査しました。
例えばIoTデバイスとして「M5Stamp S3」を使い、10分毎に「ESP-NOW」でデータ送信する場合、単三型Ni-MH電池(2000mAh)4本で316日にわたり連続稼働できるという机上計算結果になりました。CR2032ボタン(225mAh)電池2本でも1ヶ月以上連続稼働できる計算です。
畑での無線通信をWi-FiからESP-NOWに変更すれば、用途や利用期間によってはIoTデバイスに取り付けているソーラーパネルが不要になり、デバイスをもっとシンプルなものにすることができるかもしれません。
その場合、システム構成は以下のようになりそうです(ESP-NOWの通信距離についてはまだ調べていませんので、中継機が必要かどうかは分かりません)。
この図を見ていると気になってくるのが、ESP-NOW受信用に設置している「ESP32」です。
すぐ近くに設置してあるモバイルWi-FiルータにWi-Fiでデータ送信しており、そもそも無駄な使い方になっています。また、ひとつのESP32でESP-NOWとWi-Fiを同時使用するのは少し面倒なようです(これについてもまだ調べていません)。
モバイルWi-Fiルータを撤去し、携帯電話通信網でESP32デバイスから直接Webサーバにデータ送信することができれば、よりスッキリした構成になりそうです。
そんな訳で今回、「M5Stamp CAT-Mモジュール」を試してみることにしました。
ESP32デバイスと「M5Stamp CAT-Mモジュール」をつなぎ、直接このデバイスから携帯電話通信網を使ってWebサーバにデータ送信できれば、上記の構成が実現できそうです。
今回は、ディスプレイ付きの「ATOMS3」と「M5Stamp CAT-Mモジュール」をつないで動作確認することにしました。
「M5Stamp CAT-Mモジュール」はこちらです。
SIMカードは、モバイルWi-Fiルータ用に契約している「イオンモバイル」のmicroSIMカードを使います。
契約しているのは「データプラン〜タイプ2(NTTドコモ回線)」です。
モバイルWi-Fiルータからカードを抜き取り、「M5Stamp CAT-Mモジュール」のスロットに差し込みます。「M5Stamp CAT-Mモジュール」の各端子にはピンヘッダも取り付けておきます。
「ATOMS3」のGROVEポートに「M5Stamp CAT-Mモジュール」をつなぎます。
以下のようにつなぎます。
ATOMS3 | M5Stamp CAT-Mモジュール |
---|---|
G | GND |
5V | 5V |
G2 | Rx |
G1 | Tx |
20秒毎に「ATOMS3のチップID」と「ランダムな値(3桁の整数を10で割った値)」を、携帯電話通信網を使ってWebサーバに送信します。
スケッチは以下のとおりです。「M5Stamp CAT-Mモジュール」の使い方が全く分からないので、今回は こちら に記載されているスケッチを、ほぼそのまま流用させていただきました。SIMカードのAPN情報は「イオンモバイル」のWebページに記載されている内容です。
スケッチで参照している「TinyGSM」ライブラリに若干の人手修正が必要です。それについても上記の記事に記載されているとおりに実施しました。
#define TINY_GSM_MODEM_SIM7080
#include <M5AtomS3.h>
#include <TinyGsmClient.h>
const char apn[] = "n-aeonmobile.com";
const char lte_user[] = "user@n-aeonmobile.com";
const char lte_pass[] = "0000";
const int rx_pin = 1; // GROVE 4th pin of ATOMS3
const int tx_pin = 2; // GROVE 3rd pin of ATOMS3
unsigned long interval = 20; // unit:sec
TinyGsm modem(Serial1);
TinyGsmClient client(modem);
boolean sendRequest(float val0) {
: 省略
}
void setup() {
delay(500);
M5.begin(true, true, false, false);
esp_sleep_enable_timer_wakeup(interval*1000*1000);
Serial1.begin(115200, SERIAL_8N1, rx_pin, tx_pin);
M5.Lcd.clear();
M5.Lcd.setCursor(0, 0);
M5.Lcd.println("Wait...");
delay(3000);
// モデム初期化
M5.Lcd.println("Initializing modem...");
modem.init();
String modemInfo = modem.getModemInfo();
M5.Lcd.println("Modem Info: " + modemInfo);
// 接続
M5.Lcd.println("Connecting to "+ String(apn));
while (!modem.gprsConnect(apn, lte_user, lte_pass)) {
M5.Lcd.println("NG.");
delay(10000);
M5.Lcd.println("retry");
}
M5.Lcd.println("OK.");
// 接続待ち
M5.Lcd.print("Waiting for network...");
if (!modem.waitForNetwork()) {
M5.Lcd.println(" fail");
delay(10000);
return;
}
M5.Lcd.println(" success");
bool res = modem.isGprsConnected();
M5.Lcd.printf("GPRS status: %s\n", res ? "connected" : "not connected");
}
void loop() {
// Get Data
float val0 = random(0, 1000) / 10.0;
M5.Lcd.clear();
M5.Lcd.setCursor(0, 0);
M5.Lcd.println(val0);
// Send Data
M5.Lcd.println("Send Data");
if(!sendRequest(val0)) esp_deep_sleep_start();
M5.Lcd.println("Send request is finished.");
delay(interval*1000);
}
ACアダプターで「ATOMS3」のUSBポートに電源供給すると、GROVEポート経由で「M5Stamp CAT-Mモジュール」にも電源供給され、動作開始します。
問題なく、データをWebサーバに送信することができました。
ACアダプターの代わりに単三型Ni-MH電池4本をつなぎ、こちら の記事と同じ方法で消費電流波形を観測してみました。
1分間の消費電流値の推移をグラフ化していますので、この期間中に3回データ送信しています。
データ送信中は「150〜200mA」程度、待機中も「85mA」程度の電流を消費しています。
先頭部分(CAT-Mモジュールへの接続から1回目のデータ送信まで)を拡大してみました。
何回か実施して、波形を重ね合わせてみましたが、いずれもよく似た消費電流の推移となりました。
私の使っているモバイルWi-Fiルータ(HUAWEI E5785)は、3000mAhの内蔵バッテリーで12時間連続駆動可能となっています。Li-Poバッテリーの電源電圧は3.7Vなので、このルータの平均消費電力は「3000mAh × 3.7V / 12h = 925mW」という計算になります。
今回の調査では、平均消費電流値は110mA程度、同時に測定した電源電圧は5.6V程度だったので、このデバイスの組み合わせでの平均消費電力は「110mA × 5.6V = 616mW」となります。
モバイルルータより若干小さい程度で、それ程大きな差はないという結果になりました。
次に、1回のデータ送信を完了したらdeep sleepに移行するようにスケッチを変更しました。
#define TINY_GSM_MODEM_SIM7080
#include <M5AtomS3.h>
#include <TinyGsmClient.h>
const char apn[] = "n-aeonmobile.com";
const char lte_user[] = "user@n-aeonmobile.com";
const char lte_pass[] = "0000";
const int rx_pin = 1; // GROVE 4th pin of ATOMS3
const int tx_pin = 2; // GROVE 3rd pin of ATOMS3
unsigned long interval = 20; // unit:sec
TinyGsm modem(Serial1);
TinyGsmClient client(modem);
boolean sendRequest(float val0) {
: 省略
}
void setup() {
delay(500);
M5.begin(true, true, false, false);
esp_sleep_enable_timer_wakeup(interval*1000*1000);
Serial1.begin(115200, SERIAL_8N1, rx_pin, tx_pin);
M5.Lcd.clear();
M5.Lcd.setCursor(0, 0);
M5.Lcd.println("Wait...");
delay(3000);
// モデム初期化
M5.Lcd.println("Initializing modem...");
modem.init();
String modemInfo = modem.getModemInfo();
M5.Lcd.println("Modem Info: " + modemInfo);
// 接続
M5.Lcd.println("Connecting to "+ String(apn));
while (!modem.gprsConnect(apn, lte_user, lte_pass)) {
M5.Lcd.println("NG.");
delay(10000);
M5.Lcd.println("retry");
}
M5.Lcd.println("OK.");
// 接続待ち
M5.Lcd.print("Waiting for network...");
if (!modem.waitForNetwork()) {
M5.Lcd.println(" fail");
delay(10000);
return;
}
M5.Lcd.println(" success");
bool res = modem.isGprsConnected();
M5.Lcd.printf("GPRS status: %s\n", res ? "connected" : "not connected");
// Get Data
float val0 = random(0, 1000) / 10.0;
M5.Lcd.clear();
M5.Lcd.setCursor(0, 0);
M5.Lcd.println(val0);
// Send Data
M5.Lcd.println("Send Data");
if(!sendRequest(val0)) esp_deep_sleep_start();
M5.Lcd.println("Send request is finished.");
esp_deep_sleep_start();
}
void loop() {}
先日の調査(こちら)で、「ATOMS3」のディープスリープ中の消費電流値は非常に小さいという結果が得られています。
よって、このスケッチで動かした時の、ディープスリープ中の消費電流値は、ほぼ「M5Stamp CAT-Mモジュール」の待機中の消費電流値ということになります。
消費電流波形は以下のようになりました。
ディープスリープ中も最低でも20mA程度の電流消費があります。「M5Stamp CAT-Mモジュール」は待機中でもそれなりの電流消費があるようです。
なお、「M5Stamp CAT-Mモジュール」は、電源の取り扱いが結構シビアなようです。
上記のとおり「ACアダプタ」→「ATOMS3のUSBポート」→「ATOMS3のGROVEポート」→「CAT-Mモジュールの5V端子」という経路で電源供給した場合、「ACアダプタ」と「ATOMS3のUSBポート」の間に電流測定用のセンサを挿入しただけで、ネットワーク接続ができなくなりました。
また、「ACアダプタ(電圧:約5V)」の代わりに「Ni-MH電池4本(電圧:約5.6V)」で電源供給すると、ネットワーク接続できるまでの時間が、「ACアダプタ」で電源供給していた時と比べて格段にはやくなりました。
畑に設置する場合は、余裕を持って少し大きめのソーラーパネルで動かすなどした方が良さそうです。