Magicode logo
Magicode
7 min read

esp32で設定データの保存をしてみた

https://cdn.apollon.ai/media/notebox/6d442110-c5d6-410a-99b4-e0178e13d0d2.jpeg

はじめに

以前、esp32でmp3を再生したが、音量は書き込み時にハードコーディングしていた。
こちらの記事でを流用してタクトスイッチで音量調整をできるようにしたが、以前の設定値を記録できず、起動のたびに初期値に戻ってしまうので、esp32でのデータ保存について調べてみた。

環境

データ保存方法の候補

  1. SPIFFS
  2. 疑似EEPROM
  3. Preferences
  4. microSD
4のmicroSDは大げさなので、使わない。
1,2に関しては、こちらの記事 が詳しい。
この記事を読んでEEPROMを使おうかと思ったが、参考先のgithubでEEPROMは非推奨で、Preferencesを使えとあったので、3のPreferencesを使うことにする。
EEPROM is deprecated. For new applications on ESP32, use Preferences.

Preferencesの使い方

大まかな流れ

  1. bool begin(const char * name, bool readOnly=false, const char* partition_label=NULL) でnamespaceでpreferencesを開く
  2. get*, put*でデータの読み書きをする
  • データの型ごとにメソッドが用意されている。
  1. void end() で開いていたpreferencesを閉じる。

StartCounter

exampleのstart counterを動かしてみる。
これは起動した回数を保存して出力するサンプルである。
/*
 ESP32 startup counter example with Preferences library.
 This simple example demonstrates using the Preferences library to store how many times
 the ESP32 module has booted. The Preferences library is a wrapper around the Non-volatile
 storage on ESP32 processor.
 created for arduino-esp32 09 Feb 2017
 by Martin Sloup (Arcao)
*/

#include <Preferences.h>

Preferences preferences;

void setup() {
  Serial.begin(115200);
  Serial.println();

  // bool begin(const char * name, bool readOnly=false, const char* partition_label=NULL)
  // 第一引数のnamespaceでPreference領域を開く。第二引数をtrueにすると、Read-onlyになる。
  // 第三引数はちょっとよくわからない。
  // namespaceは 15 charasまで。
  // 成功したらtrue, 失敗したらfalseが返ってくる。
  preferences.begin("kj-app", false);

  // 第一引数のkeyに紐づいているデータをUIntで読み込む。
  // keyは15charasまで。
  // 第二引数は、keyに紐づいているデータがないときに帰ってくる、デフォルト値
  unsigned int counter = preferences.getUInt("counter", 0);

  counter++;
  Serial.printf("Current counter value: %u\n", counter);

  // size_t putUInt(const char* key, uint32_t value)
  // 第一引数のkeyに第二引数のデータを格納する。
  // 成功したら格納したデータのバイト数(4)を返し、失敗したら0を返す。
  preferences.putUInt("counter", counter);

  // 開いているnamespaceの領域を閉じる。
  preferences.end();

  Serial.println("Restarting in 10 seconds...");
  delay(10000);

  // Restart ESP
  ESP.restart();
}

void loop() {}
結果は下記。2から始まってるのはモニターのタイミングかなあ。
Current counter value: 2
Restarting in 10 seconds...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (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:2
load:0x3fff0030,len:1184
load:0x40078000,len:12784
load:0x40080400,len:3032
entry 0x400805e4

Current counter value: 3
Restarting in 10 seconds...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (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:2
load:0x3fff0030,len:1184
load:0x40078000,len:12784
load:0x40080400,len:3032
entry 0x400805e4

Current counter value: 4
Restarting in 10 seconds...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (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:2
load:0x3fff0030,len:1184
load:0x40078000,len:12784
load:0x40080400,len:3032
entry 0x400805e4

Current counter value: 5
Restarting in 10 seconds...

検証

型ごとにメソッド使っているが、それがずれたらどうなるだろうか?
上記のサンプルで、putUint()をputInt()にしてみたら、エラーは怒らないがずっと出力結果が1になった。
エラーが出れば気が付けるが、そうではなさそうなので注意が必要そう。
Current counter value: 1
Restarting in 10 seconds...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (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:2
load:0x3fff0030,len:1184
load:0x40078000,len:12784
load:0x40080400,len:3032
entry 0x400805e4

Current counter value: 1
Restarting in 10 seconds...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (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:2
load:0x3fff0030,len:1184
load:0x40078000,len:12784
load:0x40080400,len:3032
entry 0x400805e4

Current counter value: 1
Restarting in 10 seconds...

構造体の保存

設定情報が増えてきたら、構造体で管理したくなるかもしれない。
その時は、bytesにシリアライズして、保存するようだ。
https://github.com/espressif/arduino-esp32/blob/master/libraries/Preferences/examples/Prefs2Struct/Prefs2Struct.ino   
ちなみに、 prefs.putBytes("schedule", schedule, 3*sizeof(schedule_t)); で3をかけているのは、schedule_tのデータが3個あるから。
uint8_t content[] = {9, 30, 235, 255, 20, 15, 0, 1}; // two entries で二つデータを作っていて、
schedule[2] = {8, 30, 20, 21}; // add a third entry (unsafely) でもう一つを追加し、合計3つのデータがあるため。

終わりに

esp32で設定値を保存するために、Preferencesを使ってみた。

Discussion

コメントにはログインが必要です。