はじめに
LTE-M通信では省電力のためPSMとeDRXという機能があるということで実際に調べてみました
まず送信や受信をしないときにモデムの電源を切れば良いのではと思いますが以下のような理由により推奨されていません
LTEは、IoT通信モジュールの電源を頻繁にオン・オフするようには設計されていません。モジュールの観点からは、オンとオフの切り替えプロセスは非常に迅速に行われますが、ネットワークの観点からは、信号メッセージが大幅に増加し、セルラーネットワークに大きな負担がかかります。
-ソラコム デバイス実装ガイドライン より引用
https://soracom.jp/files/device_guideline.pdf
そこで eDRX(Extended Discontinuous Reception)や PSM(Power Saving Mode)といった省電力ネットワーク機能が用意されています
eDRX は、基地局を探索する時間間隔を延ばす機能です。また、PSM は、基地局の探索を一定時間停止する機能です。
ソラコムユーザードキュメント より
eDRX / PSM に向いているユースケースについて
eDRX のみ サーバーからデバイスに向かう通信を、大きな遅延なく受信する。
PSM のみ サーバーからデバイスに向かう通信は存在しない。
センサーデータをアップロードするならPSM、デバイスを外部から
操作したいならeDRXが向いているということらしい
spresen sedevelopment-guidesの波形をみるとイメージしやすい
ピークになっている時のみ受信可能でそれ以外の待機時は消費電流を抑えている
実験
使用機材
・Spresense メインボード
・Spresense LTE 拡張ボード(オンボードアンテナモデルCXD5602PWBLM1)
https://developer.sony.com/ja/spresense/specifications
・soracom sim(plan-D ドコモ)
・Power Profiler Kit II (PPK2) 電流計測用
https://www.nordicsemi.jp/tools/ppk2/
PPK2のVOUTをLTE 拡張ボードのMAINPOWERピンに繋いで5V入力
送信仕様
・CPUClockをデフォルトは156MHzのところを8Mhzまで下げる
・soracomの Unified Endpoint にUDPで送信
・soracomにはバイナリーパーサーを使ってバイト数を減らせる方法もありますが、
今回はjson形式の文字列をそのまま送ります
・送信し終わったらudp.stop()して300秒(5分)待機し
電源投入から3回目の送信が終わるまで(3回送信)の消費電力と待機中の平均消費電流を計測
スケッチ
参考記事
https://qiita.com/nara256/items/7cd69918f583245e3b5a
#include <LTE.h>
#include <LowPower.h>
#include <EEPROM.h>
#include <lte/lte_api.h>
#define APP_LTE_APN "soracom.io" // replace your APN
#define APP_LTE_USER_NAME "sora" // replace with your username
#define APP_LTE_PASSWORD "sora" // replace with your password
#define APP_LTE_IP_TYPE (LTE_NET_IPTYPE_V4V6) // IP : IPv4v6
#define APP_LTE_AUTH_TYPE (LTE_NET_AUTHTYPE_CHAP) // Authentication : CHAP
#define APP_LTE_RAT (LTE_NET_RAT_CATM) // RAT : LTE-M (LTE Cat-M1)
// Soracom の接続先情報
const char* server = "uni.soracom.io"; // Soracomのエンドポイント
const int port = 23080; // Soracom のポート番号
char count ;
// LTEオブジェクト
LTE lteAccess;
LTE lte;
LTEUDP udp;
int setup_edrx() {
//eDRXの設定を記述する
//設定値は https://developer.sony.com/spresense/spresense-api-references-sdk/structlte__edrx__setting.html を参照。
lte_edrx_setting edrx_setting;
edrx_setting.enable = false; // eDRXを有効にする
edrx_setting.act_type = LTE_EDRX_ACTTYPE_WBS1; // LTE-Mを使用する場合は LTE_EDRX_ACTTYPE_WBS1 を設定しておく
edrx_setting.edrx_cycle = LTE_EDRX_CYC_6144; // eDRXサイクルを 61.44 sec に設定する
edrx_setting.ptw_val = LTE_EDRX_PTW_256 ; // PTWを 2.56sec に設定する
int ret = lte_set_edrx_sync(&edrx_setting); // eDRX を設定する
Serial.print("lte_set_edrx_sync result="); Serial.println(ret);
return ret;
}
int get_edrx() {
lte_edrx_setting edrx_setting;
int ret= lte_get_current_edrx_sync(&edrx_setting);
Serial.print("lte_get_edrx_sync result="); Serial.println(ret);
printf("eDRX Active Type: %d\n", edrx_setting.act_type);
printf("eDRX Enabled: %s\n", edrx_setting.enable ? "Yes" : "No");
if (edrx_setting.enable && edrx_setting.act_type != LTE_EDRX_ACTTYPE_NOTUSE) {
printf("eDRX Cycle: %d\n", edrx_setting.edrx_cycle);
printf("Paging Time Window: %d\n", edrx_setting.ptw_val);
} else {
printf("eDRX is not active or not used.\n");
}
return ret;
}
int setup_psm() {
//psmの設定を記述する
//設定値は https://developer.sony.com/spresense/spresense-api-references-sdk/structlte__psm__timeval.html を参照。
lte_psm_setting psm_setting;
lte_psm_timeval req_active_time;
lte_psm_timeval ext_periodic_tau_time;
psm_setting.enable = false;
psm_setting.req_active_time.unit = LTE_PSM_T3324_UNIT_2SEC; // 2s
psm_setting.req_active_time.time_val = 1; // 2*1=2s
psm_setting.ext_periodic_tau_time.unit = LTE_PSM_T3412_UNIT_30SEC; // 30s
psm_setting.ext_periodic_tau_time.time_val = 2; // 30*2=60s
int ret = lte_set_psm_sync(&psm_setting); // psm を設定する
Serial.print("lte_set_psm_sync result="); Serial.println(ret);
return ret;
}
int get_psm() {
lte_psm_setting psm_setting;
lte_psm_timeval req_active_time;
lte_psm_timeval ext_periodic_tau_time;
int ret= lte_get_current_psm_sync(&psm_setting);
Serial.print("lte_get_psm_sync result="); Serial.println(ret);
printf("PSM Enabled: %s\n", psm_setting.enable ? "Yes" : "No");
printf("Requested Active Time(T3324):\n");
printf(" Unit: %d\n", psm_setting.req_active_time.unit);
printf(" Time Value: %d\n", psm_setting.req_active_time.time_val);
printf("Extended Periodic TAU Time(T3412):\n");
printf(" Unit: %d\n", psm_setting.ext_periodic_tau_time.unit);
printf(" Time Value: %d\n", psm_setting.ext_periodic_tau_time.time_val);
return ret;
}
void setup() {
char apn[LTE_NET_APN_MAXLEN] = APP_LTE_APN;
LTENetworkAuthType authtype = APP_LTE_AUTH_TYPE;
char user_name[LTE_NET_USER_MAXLEN] = APP_LTE_USER_NAME;
char password[LTE_NET_PASSWORD_MAXLEN] = APP_LTE_PASSWORD;
Serial.begin(115200);
LowPower.begin();
//Clockを下げる https://developer.sony.com/spresense/spresense-api-references-arduino/group__lowpower.html#gaadd892046ae072f2a4024f2fe9bbc601
LowPower.clockMode(CLOCK_MODE_8MHz);
Serial.println("Starting Soracom UDP JSON example...");
// LTE接続の初期化
while (true) {
/* Power on the modem and Enable the radio function. */
if (lteAccess.begin() != LTE_SEARCHING) {
Serial.println("Could not transition to LTE_SEARCHING.");
Serial.println("Please check the status of the LTE board.");
for (;;) {
sleep(1);
}
}
//セッションの無通信監視タイマーの設定
setup_edrx();
setup_psm();
if (lteAccess.attach(APP_LTE_RAT,
apn,
user_name,
password,
authtype,
APP_LTE_IP_TYPE) == LTE_READY) {
Serial.println("attach succeeded.");
// タイマーの設定の確認
get_psm();
get_edrx();
break;
}
Serial.println("An error has occurred. Shutdown and retry the network attach process after 1 second.");
lteAccess.shutdown();
sleep(1);
}
}
void loop() {
// UDP通信の準備
if (!udp.begin(port)) {
Serial.println("Failed to start UDP client!");
delay(1000);
return;
}
// uptime を計算 (秒単位)
unsigned long uptime = millis() / 1000;
count = EEPROM.read(0);
// JSON形式のメッセージを作成
char jsonMessage[128];
snprintf(jsonMessage, sizeof(jsonMessage), "{ \"uptime\": %lu, \"count\": %d }", uptime, count);
// Soracom UDPでデータを送信
udp.beginPacket(server, port);
udp.write(jsonMessage, strlen(jsonMessage));
if (udp.endPacket()) {
Serial.printf("JSON message sent: %s\n", jsonMessage);
} else {
Serial.println("Failed to send JSON message.");
}
udp.stop();
count++;
EEPROM.write(0, count);
// 次回送信まで待機
delay(300*1000);
// LowPower.sleep(300);
}
delay 対 Lowpower.sleep でどちらが省電力か?
Lowpower.sleepの方が下がると予想していたが意外に差はなく
待機時平均電流は共に15~20mAの間だった
10分電気量計は10~12C(クーロン=アンペア・秒)
以降のテストはdelayを使用
PSMを設定
psm_setting.enable = true;
psm_setting.req_active_time.unit = LTE_PSM_T3324_UNIT_2SEC; // 2s
psm_setting.req_active_time.time_val = 1; // 2*1=2s
psm_setting.ext_periodic_tau_time.unit = LTE_PSM_T3412_UNIT_30SEC; // 30s
psm_setting.ext_periodic_tau_time.time_val = 2; // 30*2=60s
2秒のピークと60秒の待機がくりかえされている
平均の待機時電流は4.3mA
10分電気量計は4.6C
eDRXを設定
edrx_setting.enable = true; // eDRXを有効にする
edrx_setting.act_type = LTE_EDRX_ACTTYPE_WBS1; // LTE-Mを使用する場合は LTE_EDRX_ACTTYPE_WBS1 を設定しておく
edrx_setting.edrx_cycle = LTE_EDRX_CYC_6144; // eDRXサイクルを 61.44 sec に設定する
edrx_setting.ptw_val = LTE_EDRX_PTW_254 ; // PTWを 2.54sec に設定する
61.44s毎にピークが現れるはずですがはっきりとは分からず
平均の待機時電流は8.1mA
10分電気量計は6.7C
PSMとeDRXを両方設定
今回はなぜか同時設定するとPSMのみ有効になりeDRXは無効になりました
理由はわかりません
結果
PSMを使うことで約50%の省電力になった
ただし平均待機時電流4.3mAではバッテリー駆動のIoTデバイスまだまだ物足りないのでさらなる低消費電力化が必要
例えばWioBG770Aの場合PSMを使用すれば待機時平均75μAまで下げられるとのこと