現時点の情報です、最新情報はM5StickC非公式日本語リファレンスを確認してください。
概要
GPIO系と通信系の消費電流を測定してみました。消費電流に波があるものも、ある瞬間的な消費電流を測定しているので、かなり誤差があります。
GPIOのpinMode(接続なし)
| 状態 | 消費電流(mA) | 増減(mA) |
| INPUT | 90.2 | 0.0 |
| INPUT_PULLUP | 90.2 | 0.0 |
| INPUT_PULLDOWN | 90.2 | 0.0 |
| OUTPUT LOW | 90.2 | 0.0 |
| OUTPUT HIGH | 90.2 | 0.0 |
| OUTPUT_OPEN_DRAIN LOW | 90.2 | 0.0 |
| OUTPUT_OPEN_DRAIN HIGH | 90.2 | 0.0 |
| ANALOG | 90.2 | 0.0 |
ピンに未接続な場合には、どのpinModeでも消費電流に差はありませんでした。
GPIOのpinMode(LED接続)
| 状態 | 消費電流(mA) | 増減(mA) |
| INPUT | 90.3 | 0.0 |
| INPUT_PULLUP | 90.4 | 0.1 |
| INPUT_PULLDOWN | 90.3 | 0.0 |
| OUTPUT LOW | 90.3 | 0.0 |
| OUTPUT HIGH | 90.9 | 0.6 |
| OUTPUT_OPEN_DRAIN LOW | 90.3 | 0.0 |
| OUTPUT_OPEN_DRAIN HIGH | 90.3 | 0.0 |
| ANALOG | 90.3 | 0.0 |
LEDと抵抗を接続してあります。OUTPUT HIGHで点灯した場合に0.6mAしか流れていないので、抵抗値が高すぎですが検証で明るすぎると面倒なので、かなり暗く光るようにしています。
INPUT_PULLUPでも少しだけ電流が流れていますので、うっすらと光っていました。それ以外のモードでは消費電流に差はありませんでした。
Bluetooth Serial
| 状態 | 消費電流(mA) | 増減(mA) |
| 起動直後 | 90.6 | 0.0 |
| SerialBT.begin() | 95.4 | 4.8 |
| SerialBT.disconnect() | 94.3 | 3.7 |
| SerialBT.end() | 93.1 | 2.5 |
開始しただけで、実際の接続がない状況での消費電流です。begin()で受信を開始すると同時に消費電流が増えました。実際に通信をするともっと増えると思いますが、頻度によってかなり増減すると思うので、今回は計測していません。
disconnect()をしても、当初よりも電流が流れた状態のままでした。end()で少し減りましたが、まだ当初より高い電流です。
ちなみに一度end()をするとbegin()をしても通信ができません。通信系は起動時にしか確保しないメモリーなどがあるみたいです。
BLE
| 状態 | 消費電流(mA) | 増減(mA) |
| 起動直後 | 90.7 | 0.0 |
| BLEDevice::init() | 142.9 | 52.2 |
| pBLEScan->start() | 133.2 | 42.5 |
| Scan完了 | 93.1 | 2.4 |
| BLEDevice::deinit(false) | 91.9 | 1.2 |
| BLEDevice::deinit(true) | 91.9 | 1.2 |
BLEは init() をした瞬間が一番電力使っていました。常に通信モジュールに電源供給しているのかもしれません。pBLEScanの間は電流が増減する波があり、Scanが終わると消費電流が安定しました。
deinit()ではメモリを開放するかのフラグがありましたが、どちらでも消費電流に違いはなく、起動直後の電流にも戻りませんでした。
Wi-Fi
| 状態 | 消費電流(mA) | 増減(mA) |
| 起動直後 | 91.3 | 0.0 |
| WIFI_OFF | 91.3 | 0.0 |
| WIFI_STA | 142.4 | 51.1 |
| WIFI_AP | 145.1 | 53.8 |
| WIFI_AP_STA | 144.1 | 52.8 |
| WiFi.begin() | 142.3 | 51.0 |
| WiFi.disconnect() | 142.6 | 51.3 |
ESP32のWi-Fiは子機にあたるSTA(ステーション)と、親機にあたるAP(アクセスポイント)モードがあり、オフとその両方とも使う4種類が設定できます。
WIFI_OFF以外を選択すると、その瞬間から消費電流が跳ね上がります。STAモードで接続をしてから、切断をしても消費電流はほぼ変わりませんでした。
実際に消費電流を下げるためにはWiFi.disconnect(true)で切断する必要があるのですが、WiFi.mode(WIFI_OFF)で全体をOFFにしたほうが、かんたんで安全なきがしました。
検証スケッチ
#include <M5StickC.h>
#include "BluetoothSerial.h"
#include "BLEDevice.h"
#include <WiFi.h>
BluetoothSerial SerialBT;
#include <Preferences.h>
Preferences preferences;
char wifi_ssid[33];
char wifi_key[65];
int lcd_breath = 12;
int led = 1;
int ir = 1;
int cpu = 0;
int cpu_f[] = {240, 160, 80, 40, 20, 10};
int gpio = -1;
int gpio_f[] = {INPUT, INPUT_PULLUP, INPUT_PULLDOWN, OUTPUT, OUTPUT_OPEN_DRAIN, ANALOG };
int bts = -1;
int ble = -1;
int wifi = -1;
int mode = 0;
enum {
MODE_LCD, // 0
MODE_LED, // 1
MODE_IR, // 2
MODE_BTN, // 3
MODE_CPU, // 4
MODE_GPIO, // 5
MODE_BTS, // 6
MODE_BLE, // 7
MODE_WIFI, // 8
MODE_MAX
};
// Set charge flag
void SetCharge(bool charge) {
// get param
Wire1.beginTransmission(0x34);
Wire1.write(0x33);
Wire1.endTransmission();
Wire1.requestFrom(0x34, 1);
uint8_t state = Wire1.read();
// set flag
if (charge) {
// ON
state = state | 0x80;
} else {
// OFF
state = state & 0x7f;
}
// set param
Wire1.beginTransmission(0x34);
Wire1.write(0x33);
Wire1.write(state);
Wire1.endTransmission();
}
void setup() {
M5.begin();
SetCharge(false);
// LED
pinMode(GPIO_NUM_10, OUTPUT);
digitalWrite(GPIO_NUM_10, HIGH);
// IR
pinMode(GPIO_NUM_9, OUTPUT);
digitalWrite(GPIO_NUM_9, HIGH);
// LCD display
M5.Lcd.print("Hello World");
}
void loop() {
M5.update();
// Mode Chenge
if ( M5.BtnB.wasPressed() ) {
mode++;
mode = mode % MODE_MAX;
Serial.printf("New Mode: %d\n", mode );
}
if ( mode == MODE_LCD ) {
// LCD
if ( M5.BtnA.wasPressed() ) {
lcd_breath++;
lcd_breath = lcd_breath % 13;
M5.Axp.ScreenBreath(lcd_breath);
Serial.printf("LCD Breath: %d\n", lcd_breath );
}
} else if ( mode == MODE_LED ) {
if ( M5.BtnA.wasPressed() ) {
led = !led;
digitalWrite(GPIO_NUM_10, led);
Serial.printf("LED: %d\n", led );
}
} else if ( mode == MODE_IR ) {
if ( M5.BtnA.wasPressed() ) {
ir = !ir;
digitalWrite(GPIO_NUM_9, ir);
Serial.printf("IR: %d\n", ir );
}
} else if ( mode == MODE_CPU ) {
if ( M5.BtnA.wasPressed() ) {
cpu++;
cpu = cpu % ( sizeof( cpu_f ) / sizeof( int ) );
setCpuFrequencyMhz(cpu_f[cpu]);
Serial.printf("CPU Frequency Mhz: %d\n", cpu_f[cpu] );
}
} else if ( mode == MODE_GPIO ) {
if ( M5.BtnA.wasPressed() ) {
gpio++;
gpio = gpio % 8;
switch ( gpio ) {
case 0:
// INPUT
pinMode( GPIO_NUM_26, INPUT );
Serial.printf("pinMode INPUT\n");
break;
case 1:
// INPUT_PULLUP
pinMode( GPIO_NUM_26, INPUT_PULLUP );
Serial.printf("pinMode INPUT_PULLUP\n");
break;
case 2:
// INPUT_PULLDOWN
pinMode( GPIO_NUM_26, INPUT_PULLDOWN );
Serial.printf("pinMode INPUT_PULLDOWN\n");
break;
case 3:
// OUTPUT LOW
pinMode( GPIO_NUM_26, OUTPUT );
digitalWrite( GPIO_NUM_26, LOW );
Serial.printf("pinMode OUTPUT LOW\n");
break;
case 4:
// OUTPUT HIGH
pinMode( GPIO_NUM_26, OUTPUT );
digitalWrite( GPIO_NUM_26, HIGH );
Serial.printf("pinMode OUTPUT HIGH\n");
break;
case 5:
// OUTPUT_OPEN_DRAIN LOW
pinMode( GPIO_NUM_26, OUTPUT_OPEN_DRAIN );
digitalWrite( GPIO_NUM_26, LOW );
Serial.printf("pinMode OUTPUT_OPEN_DRAIN LOW\n");
break;
case 6:
// OUTPUT_OPEN_DRAIN HIGH
pinMode( GPIO_NUM_26, OUTPUT_OPEN_DRAIN );
digitalWrite( GPIO_NUM_26, HIGH );
Serial.printf("pinMode OUTPUT_OPEN_DRAIN HIGH\n");
break;
case 7:
// ANALOG
pinMode( GPIO_NUM_26, ANALOG );
Serial.printf("pinMode ANALOG\n");
break;
}
}
} else if ( mode == MODE_BTS ) {
if ( M5.BtnA.wasPressed() ) {
bts++;
if ( bts == 0 ) {
SerialBT.begin("ESP32test");
Serial.printf("SerialBT.begin()\n");
} else if ( bts == 1 ) {
SerialBT.disconnect();
Serial.printf("SerialBT.disconnect()\n");
} else if ( bts == 2 ) {
SerialBT.end();
Serial.printf("SerialBT.end()\n");
bts = -1;
}
}
} else if ( mode == MODE_BLE ) {
if ( M5.BtnA.wasPressed() ) {
ble++;
if ( ble == 0 ) {
Serial.printf("BLEDevice::init()\n");
BLEDevice::init("");
} else if ( ble == 1 ) {
Serial.printf("pBLEScan()\n");
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(NULL);
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
} else if ( ble == 2 ) {
Serial.printf("BLEDevice::deinit(false)\n");
BLEDevice::deinit(false);
} else if ( ble == 3 ) {
Serial.printf("BLEDevice::deinit(true)\n");
BLEDevice::init("");
BLEDevice::deinit(true);
ble = -1;
}
}
} else if ( mode == MODE_WIFI ) {
if ( M5.BtnA.wasPressed() ) {
wifi++;
if ( wifi == 0 ) {
Serial.println("WIFI_OFF");
WiFi.mode(WIFI_OFF);
} else if ( wifi == 1 ) {
Serial.println("WIFI_STA");
WiFi.mode(WIFI_STA);
} else if ( wifi == 2 ) {
Serial.println("WIFI_AP");
WiFi.mode(WIFI_AP);
} else if ( wifi == 3 ) {
Serial.println("WIFI_AP_STA");
WiFi.mode(WIFI_AP_STA);
} else if ( wifi == 4 ) {
WiFi.mode(WIFI_STA);
// Wi-Fiアクセスポイント情報取得
preferences.begin("Wi-Fi", true);
preferences.getString("ssid", wifi_ssid, sizeof(wifi_ssid));
preferences.getString("key", wifi_key, sizeof(wifi_key));
preferences.end();
// connect to WiFi
Serial.printf("Connecting to %s ", wifi_ssid);
WiFi.begin(wifi_ssid, wifi_key);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
} else if ( wifi == 5 ) {
Serial.printf("WiFi.disconnect()\n");
WiFi.disconnect();
wifi = -1;
}
}
}
}
まとめ
GPIOは実際に使うまでpinMode自体で消費電流は変わらなかった。未使用のピンについては、わざわざ設定する必要はなさそうです。
無線系は一度使うと消費電流が上がったままになりやすいので、使ったあとに再起動をするか、変数をスローメモリに保存してから、タイマー0秒でのDeepSleepでの疑似リセットで、フレッシュな状態に戻したほうがいいのかもしれません。
もう少し突っ込んだ検証は、時系列で消費電流を計測する必要があり、手持ちの機材だと精度が足りないので保留します。
I2Cの電流計だと、精度がものたりないし、電流プローブは高くて手にはいらないのでマルチメーターかなと思っています。
上記あたりが電流の精度が高いかな?
ただ、このためだけに購入するにはちょっと高いので考え中です。



コメント