PR

M5stack / ESP32マイコン内部に領域をもつEEPROMの使い方

M5stack ESP32マイコン内部に領域をもつEEPROMの使い方 組み込み機器

電源を切っても情報を保存 させたい

ESP32マイコンやM5stackにて生じる、こうした悩みを解決します。

動画でも本記事を説明しています!

立プロ

新卒でメーカーに入り、10年間組み込みの現場で設計を行う。
今は個人事業主として自作の組み込み機器開発や、エージェント様に紹介いただき業務委託を行っています。
C,C#,JavaScript, Vue, PHP, VBA, GAS, Kotlinなど、扱う言語が増えゆく日々。

立プロをフォローする

EEPROMとは

EEPROM(=Electrically Erasable Programmable Read-Only Memory)は、電気的に書き換え可能なメモリです。

情報はコンデンサに電荷をためて保持されるため、電源を切ってもデータを保持することができます。

ESP32だとEEPROMライブラリがあるので簡単に実装できます。

例えば、接続するWi-FiのSSIDやパスワードなどを記憶するのに使用すると便利です。

使い方、考え方

EEPROMは指定したアドレスを起点に1バイトごとに読み書きを行います。

そのためまず設計を行うにあたって、 どの番地に何の情報を入れるのか決めると良いです。

例えば0x00番地から0x20番地までをwi-fiのSSIDを入れる文字列領域とするとか。

0x00のような書き方は16進数によるもので、例えば 0x01 は1、 0x10は16、0xFFは255になります。EEPROMはメモリ空間を学ぶことになるので、 変数の型によるメモリ消費量の違いとか、異なる変数同士の演算によってどうなるかとかもわかるようになります。

学んでおいて損はないですよ!

サンプルコード

#include <EEPROM.h>
#define ADDR_SSID 0x00

void setup() {
  Serial.begin(115200);
  EEPROM.begin(50); //50byte
}

int time = 0;
void loop() {
  EEPROM.writeString(ADDR_SSID,"tatepro-EEPROMtest");

  if(millis() - time > 1000){
    time = millis();
    String temp = EEPROM.readString(ADDR_SSID);
    Serial.println(temp);
  }
}

EEPROM.begin(50);で50バイト分のメモリ領域を確保しています。

writeStringで起点となる番地と文字列を格納、今回で言うとADDR_SSID=0x00番地にtatepro-EEPROMtestを格納します。

そしてreadStringで0x00番地から50バイト分のデータを読み出します。これをtemp変数に入れてシリアルモニタでtemp変数を見ると、tatepro-EEPROMtestが返ってくるはずです、1秒毎に。

このとき注意しないといけないのが、実際の中身は

tatepro-EEPROMtest\0\0\0\0\0\0\0\0\0...\0

のように、null埋めされた50バイト分のデータになっています。

0x00番地に書き込んでいるのは上記nullを含んだ50バイトです。

なので、今回サンプルなのでこんな簡単に書きましたけど、実際使う時は起点となる番地に1文字ずつ入れていき、格納する文字がnullだと検出した時点で書き込み/読み出し終了とする処理を入れないと使い物にならないです。

writeStringやreadStringが標準で含まれていて便利そうですけど、実際使うには関数を自作した方がよいです、というか必須になるかな、と。

私が実際に使っているのは下記の関数。どなたかネットに落ちてるやつをいただいたような気がするのですが…忘れました。

void eeprom_write(int startaddr, int endaddr, String data) {
  byte Byte_data[EEPROM_MAXSIZE];
  data.getBytes(Byte_data, EEPROM_MAXSIZE);
  int k;
  for(k = startaddr; k <= endaddr; k++){
    EEPROM.put(k, '\0');
    EEPROM.put(k, Byte_data[k - startaddr]);
  }

  EEPROM.commit(); // EEPROMに書き込み確定
}

String eeprom_read(int startaddr, int endaddr) {
  String data_from_rom = "";
  char c;
  int i;
  for(i = startaddr; i <= endaddr; i++){
    c = EEPROM.get(i, c);
    if(c == '\0') break;
    data_from_rom = data_from_rom + String(c);
  }

  return data_from_rom;
}

void shiftdata(int fromaddr, int toaddr, int size){
  String data = "";
  data = eeprom_read(fromaddr, (fromaddr + size - 1));
//  showdata(data);
  if(data!=""){
    eeprom_write(toaddr, (toaddr + size - 1), data);  
  }
}

起点と終点を指定して、もしnullがあればそこで終了といった具合に動きます。参考になれば幸いです。

実運用上の注意

メーカーでエンジニアやっていた時はEEPROMはできるだけ使用しないようにしていました。

というのも、EEPROMはコンデンサに電荷をためて情報を保存する仕組みであり、そのため静電気などで電荷が抜けてしまいデータが消失する可能性があります。

そのため、機器の設定などの一時的な情報の保存には適していますが、重要な測定データなどの永続的な保存に使用するのは危険です。

絶対にデータを保持しなければならない場合は、FLASH領域や別の外部メモリにデータを保存することをおすすめします。

ただ、一般的にはこうした説明になりますが、ESP32に関しては、EEPROMはROM領域内にメモリ確保しているので、たぶんデータは消失しないです。
もし消失した場合は、マイコンごと壊れてると思います。
厳密にいうと、EEPROMではなくて情報メモリ(Info memory)と表現するのが適切だと私は考えています。

補足:EEPROMの番地について

ESP32ではEEPROM用に領域が予め確保されています。

EEPROM領域は自分で変更することもできますが、別記事で紹介させてください。

まとめ

EEPROM(=Electrically Erasable Programmable Read-Only Memory)は、電気的に書き換え可能なメモリです。

EEPROMは指定したアドレスを起点に1バイトごとに読み書きを行います。

コメント

タイトルとURLをコピーしました