PaperDIY は M5PM1 と基板上の電源回路を組み合わせて多段階の電源スイッチを実現しています。各電源レベルで異なる周辺機器やインターフェースへの電源を制御できます。用途に応じて必要な電源レベルだけを有効にし、使用しない周辺機器を停止することで、システム全体の消費電力を低減できます。
M5PM1 ドライバライブラリを使用して、電源出力、GPIO、充電制御、タイマー、スリープ機能を設定できます。
この電源レベルでは、バッテリーから M5PM1 と FPC-I2S インターフェースに給電し、その他の周辺機器は電源を切ることができます。バッテリーが完全に消耗していない限り、このレベルは維持され、M5PM1 による電源ボタンのオン / オフ操作に対応します。
この電源レベルではデバイスはスタンバイ状態です。バッテリーから M5PM1 への給電は継続され、L0 レベルで利用できる操作にも対応します。
このレベルでは ESP32-S3、microSD、ユーザーボタン、FPC-SPI インターフェースへの電源が追加で有効になります。M5PM1 の DCDC3V3_EN_PP が 3V3_L2 電源スイッチを制御し、ESP32-S3 の動作中は動作用電源になります。次の API で制御できます。
pm1.setDcdcEnable(true); // L2 ON
pm1.setDcdcEnable(false); // L2 OFF ESP32-S3 がスリープ状態のとき、電源は L2 レベルです。ESP32-S3 が動作中のとき、電源は L3A レベルです。ESP32-S3 は M5PM1 をスリープ状態にして、自身への電源を停止できます (L2 -> L1/L0)。
このレベルでは電子ペーパーの電源、FPC 制御信号、充電状態などを制御します。FPC インターフェースに接続された M5PM1 GPIO にはカスタム機能を割り当てることができ、M5PM1 API で電子ペーパーの電源、充電、その他のカスタム周辺機器を制御できます。
| M5PM1 | PYG0 | PYG1 | PYG2 | PYG3 | PYG4 |
|---|---|---|---|---|---|
| FPC - I2S | PY_G0 | ||||
| FPC - SPI | PY_G1 | PY_G4 | |||
| E-Paper | EPD_PWR | ||||
| Charge | CHG_STAT |
M5PM1 PYG2 は EPD_PWR に接続され、電子ペーパーパネルとドライバ回路の電源を制御します。電子ペーパーの昇圧回路は ESP32-S3 の GPIO46 (BST_EN) で有効にします。両方が有効な場合にのみ、画面を正常に更新できます。
pm1.gpioSetFunc(M5PM1_GPIO_NUM_2, M5PM1_GPIO_FUNC_GPIO);
pm1.gpioSetMode(M5PM1_GPIO_NUM_2, M5PM1_GPIO_MODE_OUTPUT);
pm1.gpioSetDrive(M5PM1_GPIO_NUM_2, M5PM1_GPIO_DRIVE_PUSHPULL);
pm1.gpioSetOutput(M5PM1_GPIO_NUM_2, true); // EPD_PWR ON PaperDIY のバッテリー電圧は BAT_ADC を通じて M5PM1 に入力され、readVbat() で読み取ることができます。
uint16_t batteryMv = 0;
if (pm1.readVbat(&batteryMv) == M5PM1_OK) {
Serial.printf("VBAT: %u mV\n", batteryMv);
} 充電の有効化は CHG_EN で制御します。充電状態は PYG3 の CHG_STAT から読み取り、Low レベルの場合は充電中です。
pm1.setChargeEnable(true); // 开启充电
pm1.gpioSetFunc(M5PM1_GPIO_NUM_3, M5PM1_GPIO_FUNC_GPIO);
pm1.gpioSetMode(M5PM1_GPIO_NUM_3, M5PM1_GPIO_MODE_INPUT);
pm1.gpioSetPull(M5PM1_GPIO_NUM_3, M5PM1_GPIO_PULL_UP);
uint8_t chgStat = 1;
if (pm1.gpioGetInput(M5PM1_GPIO_NUM_3, &chgStat) == M5PM1_OK) {
bool charging = (chgStat == 0); // CHRG 低电平表示正在充电
} M5PM1 はプログラムからスリープ状態に移行して、システム全体の消費電力を低減できます。デフォルトでは shutdown() を呼び出すと 3V3_L2 がオフになり、ESP32-S3 が停止して、M5PM1 の基本的な電源管理機能だけが維持されます。
pm1.shutdown(); スリープ中も外部回路への給電を継続する必要がある場合は、shutdown() を呼び出す前に必要な電源保持条件を設定してください。PaperDIY の電子ペーパーや FPC 周辺機器は、状態を保存せずに電源を切らないでください。
M5PM1 は、I2C バスが一定時間アイドル状態になると自動的に低消費電力モードへ移行できます。
pm1.setI2cSleepTime(10); // I2C 空闲 10 秒后进入低功耗模式 このモードに入ると、ESP32-S3 と M5PM1 間の最初の通信はチップのウェイクアップに使用されるため、有効な読み書きが完了しない場合があります。ウェイクアップ後の次の通信で対象レジスタを読み書きしてください。
M5PM1 はタイマーに対応しており、カウントダウン終了時に電源オン、電源オフ、リセット、フラグ設定などの動作を実行できます。
m5pm1_err_t timerSet(uint32_t seconds, m5pm1_tim_action_t action); typedef enum {
M5PM1_TIM_ACTION_STOP = 0b000, // 停止,无动作
// Stop, no action
M5PM1_TIM_ACTION_FLAG = 0b001, // 仅设置标志
// Set flag only
M5PM1_TIM_ACTION_REBOOT = 0b010, // 系统复位
// System reboot
M5PM1_TIM_ACTION_POWERON = 0b011, // 开机
// Power on
M5PM1_TIM_ACTION_POWEROFF = 0b100 // 关机
// Power off
} m5pm1_tim_action_t; デバイスの起動後、BtnA を押すと 3 秒後の電源オンを設定し、BtnB を押すと 3 秒後の電源オフを設定します。
#include <M5Unified.h>
#include <M5PM1.h>
M5PM1 pm1;
bool pm1Ready = false;
static void drawMessage(const char* line1, const char* line2)
{
M5.Display.clear();
M5.Display.setTextDatum(middle_center);
M5.Display.setFont(&fonts::FreeSansBold24pt7b);
M5.Display.drawString(line1, M5.Display.width() / 2, M5.Display.height() / 2 - 30);
M5.Display.setFont(&fonts::FreeSansBold18pt7b);
M5.Display.drawString(line2, M5.Display.width() / 2, M5.Display.height() / 2 + 35);
}
static void drawTimerHome()
{
M5.Display.clear();
M5.Display.setTextDatum(middle_center);
M5.Display.setFont(&fonts::FreeSansBold24pt7b);
M5.Display.drawString("M5PM1 TIMER", M5.Display.width() / 2, M5.Display.height() / 2 - 110);
M5.Display.setFont(&fonts::FreeSansBold18pt7b);
M5.Display.drawString("Btn A: power on after 3 seconds", M5.Display.width() / 2, M5.Display.height() / 2 - 35);
M5.Display.drawString("Btn B: power off after 3 seconds", M5.Display.width() / 2, M5.Display.height() / 2 + 20);
M5.Display.drawString("Press A or B to start the timer", M5.Display.width() / 2, M5.Display.height() / 2 + 75);
}
void setup()
{
auto cfg = M5.config();
cfg.clear_display = false;
M5.begin(cfg);
Serial.begin(115200);
M5.Display.setEpdMode(epd_mode_t::epd_text);
const m5pm1_err_t err =
pm1.begin(&M5.In_I2C, M5PM1_DEFAULT_ADDR, M5PM1_I2C_FREQ_100K);
pm1Ready = (err == M5PM1_OK);
if (!pm1Ready) {
Serial.printf("M5PM1 init failed: %d\n", err);
drawMessage("M5PM1 ERROR", "Check I2C");
return;
}
Serial.println("BtnA: power on after 3s");
Serial.println("BtnB: power off after 3s");
drawTimerHome();
}
void loop()
{
M5.update();
if (!pm1Ready) {
delay(1000);
return;
}
if (M5.BtnA.wasPressed()) {
drawMessage("Power OFF", "Power ON after 3s");
delay(500);
if (pm1.timerSet(3, M5PM1_TIM_ACTION_POWERON) == M5PM1_OK) {
Serial.println("Power-on timer configured");
pm1.shutdown();
} else {
Serial.println("Power-on timer configuration failed");
drawMessage("Timer ERROR", "Power-on failed");
}
}
if (M5.BtnB.wasPressed()) {
drawMessage("Power OFF", "After 3 seconds");
if (pm1.timerSet(3, M5PM1_TIM_ACTION_POWEROFF) == M5PM1_OK) {
Serial.println("Power-off timer configured");
} else {
Serial.println("Power-off timer configuration failed");
drawMessage("Timer ERROR", "Power-off failed");
}
}
delay(20);
}