現時点の情報です、最新情報は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の電流計だと、精度がものたりないし、電流プローブは高くて手にはいらないのでマルチメーターかなと思っています。
上記あたりが電流の精度が高いかな?
ただ、このためだけに購入するにはちょっと高いので考え中です。
コメント