EEPROMを使いこなす(Arduino詳解)

Arduino詳解その24です。前回の記事はこちらです。
>hirocom777.hatenadiary.org

EEPROMを使いこなすコツ

 前回はEEPROMを使って電源を切ってもデータを記憶して置く方法を紹介しました。今回はEEPROMを使うときの注意点についてまとめてみようと思います。

f:id:HiroCom777:20201031163435j:plain
・書込み回数に限度がある
 EEPROMのメモリ書き換え可能回数は約10万回程度で寿命を迎えるとされています。10万回というと多いように思われますがプログラミングでのメモリアクセスではあっという間です。用途を絞って書き換え頻度が少ない場合にのみ使用しましょう。また、書き込む前に値を確認して、書き込み値と異なる場合にのみ書き込むなどの工夫も有効だと思います。また、前回ご紹介したEEPROM.write()の代わりにEEPROM.update()を使用すると、値が異なるときだけ書き込みを実行します。

・書き込み時間がかかる
 EEPROMの書き込み時間は3.3mS必要で、他のメモリよりも時間がかかります。書き込んだ直後に読み出すなどの操作は誤動作のもとになります。読み出しの時間については特に注意は必要ありません。

・アドレスの管理に注意
 当然ですが、データを書き込むアドレスの管理はしっかりしなければなりません。読み出すアドレスを間違えれば期待する値は返ってきませんし、書き込んでしまえばデータは破壊されます。特に、複数バイトのデータ(整数型、長整数型、浮動小数点型等)を使用するときはデータが書き込まれている範囲を明確にしておきましょう。

 こんなところでしょうか。電源を切ってもデータが消えないのが特徴ですから、頻繁に書き換えることのない設定の記憶などに使用するのが正しい用途だと思います。

その他の使用方法

 前回ご紹介した関数以外にも、EEPROMを配列の様に使用する方法があります。以下にスケッチ例をご紹介します。

#include <EEPROM.h>

void setup() {
  Serial.begin(9600);
  for (int i = 0; i < 10; i++) {
    Serial.println(EEPROM[ i ]);
  }
}

void loop() {
  if (Serial.available()) {
    byte inputNumber = Serial.parseInt();
    for (int i = 0; i < 10; i++) {
      EEPROM[ i ] = inputNumber;
      inputNumber++;
      Serial.println(inputNumber);
    }
  }
}

 このスケッチは、ArduinoUNOを起動するとEEPROMのアドレス0から9までの値を読み取ってシリアルモニターに表示します。この状態でシリアルモニターの一番上の送信欄に0~255の数字を入力を入力してみてください。入力された値から1ずつ増えた値が表示されます。この状態でArduinoUNOをリセットすると、先に書き込んだ値が返ってきます。この様にEEPROM[アドレス]と記述すると、EEPROMの指定アドレスにアクセスできます。

まとめて読み書きする方法

 前回ご紹介したEEPROM.get()とEEPROM.put()。バイト型、整数型、長整数型、浮動小数点型のデータを読み書きできることはすでに述べましたが、それ以外にも構造体を使うことが出来ます。以下にスケッチ例をご紹介します。

#include <EEPROM.h>

struct structTest {
  byte byteValue;
  int intValue;
  long longValue;
  float floatValue;
};

structTest dataBlock;
int eepAddress = 0;

void setup() {
  Serial.begin(9600);
  EEPROM.get(eepAddress , dataBlock);
  Serial.println(dataBlock.byteValue);
  Serial.println(dataBlock.intValue);
  Serial.println(dataBlock.longValue);
  Serial.println(dataBlock.floatValue, 7);
}

void loop() {
  if (Serial.available()) {
    byte inputNumber = Serial.parseInt();
    dataBlock.byteValue = inputNumber;
    dataBlock.intValue = dataBlock.byteValue * 256;
    dataBlock.longValue = dataBlock.intValue * 65536;
    dataBlock.floatValue = float(dataBlock.intValue) / 13;

    EEPROM.put(eepAddress , dataBlock);
    Serial.println(dataBlock.byteValue);
    Serial.println(dataBlock.intValue);
    Serial.println(dataBlock.longValue);
    Serial.println(dataBlock.floatValue, 7);

    Serial.println();
    Serial.println(sizeof(dataBlock));
  }
}

このスケッチは、前回紹介したものを構造体で書き換えたものです。何だかすっきりしましたね。EEPROM.get()とEEPROM.put()で変数指定の項目に構造体を指定すると構造体にデータを読み出したり、構造体の内容をEEPROMに書き込んだりできます。実行して前回同様に操作すると、ちゃんと読み書きできていることが判ると思います。

構造体

 構造体というのは、様々なデータ型の変数を一つにまとめることが出来る箱のようなものです。以下に構造体の使い方を説明します。構造体を使うには、まず構造体の型を宣言します。内容は構造体の型の名前と構造体を構成するメンバ(変数)の型、名前を定義する必要があります。上記のスケッチ例にもありますが、以下の様に宣言します。

struct 構造体の型の名前{
データ型 メンバ名;
データ型 メンバ名;
データ型 メンバ名;
    ・
    ・
}

次に、宣言した型で構造体を宣言します。以下のような感じです。

宣言した構造体の型の名前 構造体の名前

宣言した構造体の各メンバにアクセスするには・・・

構造体の名前.メンバ名

で普通の変数と同じに使えます!!

sizeof演算子

 今回のスケッチ例は、データを書き込むと最後に11という数字を表示しています。これは、sizeof演算子を使って構造体の大きさ(バイト数)を取得して表示しているものです。sizeof演算子はかっこの中に、変数、配列、構造体などを指定するとそれらのバイト数を返します。今回の構造体は、バイト型(1バイト)、整数型(2バイト)、長整数型(4バイト)、浮動小数点型(4バイト)で構成されているので、すべて合わせて11バイトとなるわけです。
構造体は定義した内容でサイズが変わってきますので、EEPROMを使用する場合にはsizeof演算子を使って大きさを確認しながら使用するといいでしょう。

便利に使いこなしましょう!!

 いかがでしょうか。構造体は他にも色々な使い方が出来るのですが、とりあえず今回の使い方を覚えておけばいいと思います。
 次回は時間の管理方法について掘り下げていきたいと思います。お楽しみに!!
hirocom777.hatenadiary.org


Arduino UNO入門の連載記事はコチラからどうぞ!!