M5StackのコアであるESP32系にはCPUクロックを落として省電力化する機能があります。
ただし、これの呼び出しタイミングを誤ると、シリアル通信などクロック依存のタスクに影響がでます。
そのため、CPUクロック変更命令はM5.begin()の前に呼び出しましょう。
実際のところ
状況
試作中の環境ノードの省電力化を試み、CPU速度を落としてみました。
void setup() { // M5Stack初期化 M5.begin(); M5.Power.begin(); //... // CPU周波数削減(省電力化のため) setCpuFrequencyMhz(40); // シリアル通信初期化 Serial.begin(115200); while (!Serial) { delay(100); } //... }
目論見通り消費電力は落ち、計測ロジックも遅くならなかったので特に不満は無かったのですが……
ちょっと挙動を見ようとシリアルを繋いだところ
rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1344
load:0x40078000,len:13964
load:0x40080400,len:3600
entry 0x400805f0
M5Stack initializing...
[ 377][E][sd_diskio.cpp:199] sdCommand(): Card Failed! cmd: 0x00
[ 383][E][sd_diskio.cpp:806] sdcard_mount(): f_mount failed: (3) The physical drive cannot work
[ 692][E][sd_diskio.cpp:199] sdCommand(): Card Failed! cmd: 0x00
OK
�f␘����`f~␆��...
などと、それまで動いていたデバッグログが滅茶苦茶なことに
対策
M5stack BasicのコアであるESP32シリーズのシリアル通信は、(考えてみりゃ当然なのですが)CPUクロックを基準に生成されています。
beginした後にクロックを弄ると、ボーレートが狂うので今回のような事態になるという事。
という訳で、setCpuFrequencyMhzメソッドはM5.begin()の前に置かないとダメです。
void setup() { // CPU周波数削減(省電力化のため) // 重要: M5.begin()の前に設定しないとシリアル通信が文字化けする setCpuFrequencyMhz(40); // M5Stack初期化 M5.begin(); M5.Power.begin(); // シリアル通信初期化 Serial.begin(115200); while (!Serial) { delay(100); } //... }
補足情報
M5stackは仕様上、先にCPUクロックを弄ってしまうとアウトのようですが、
素のESP32系ボードは必ずしもそういう仕様ではないようで
// ESP32の普通のボードなら以下のような書き方もOKなケースがある
uint32_t Freq = 0;
void setup()
{
pinMode(GPIO_pin, OUTPUT);
Serial.begin(115200);
setCpuFrequencyMhz(10);
Freq = getCpuFrequencyMhz();
Serial.print("CPU Freq = ");
Serial.print(Freq);
Serial.println(" MHz");
// ....