つれづれなる備忘録

日々の発見をあるがままに綴る

TinkercadによるArduinoシミュレーション41 ~ 内蔵メモリへの小数・文字データの読み書き

前回のArduinoの内蔵メモリ(EEPROM)へのデータの読み書きとして1バイトの整数(0-255)の例を紹介した。今回は小数や文字データをEEPROMに書き込み、読み出しする方法について紹介したい。

atatat.hatenablog.com

1. EEROMへの整数以外の読み書き

 前回までは1バイトの整数をEEPROMに書き込む場合はEEPROM.write(address, data)、指定のアドレスから読み出す場合はEEPROM.read(address)を用いていた。 今回の任意の形式のデータを書き込む場合はEEPROM.put(address, data)、読み出す場合はEEPROM.get(address,data)を用いる。仕組みとしては、EEPROMのアドレスには1バイトの整数値しか書き込めないが、EEPROM.put()を用いると小数や文字データは複数のアドレスに1バイトの整数が書き込まれる。読み出す場合はEEPROM.get(address,data)により読み出しを開始するアドレスと格納する変数に型式を定義しておけば複数のアドレスに書き込まれた1バイトの整数を変換して指定した変数に格納する。

2. EEPROMへの小数、構造体データの書き込み

 まずEEPROMへ単体の小数および構造体のデータを書き込む方法を部分的に示す。(最終的なスケッチは最後に載せる) 最初に小数、整数(1バイト)、文字から構成される構造体を以下のように宣言しておく。

struct MyObject {
float field1;
byte field2;
char name[10];
};

次にfloat型の変数fをEEPROMに書き込むには、データ(123.456)と書き込みを開始する先頭のアドレス(0)を指定してEEPROM.put(eeAddress,f)とすれば書き込める。

float f = 123.456f;  // float型を明記
int eeAddress = 0;   // 書き込むデータの最初のアドレス
EEPROM.put(eeAddress, f);

最初に宣言した構造体に小数、整数(1バイト)、文字を入力し、変数fを書き込むのに使用したアドレス数sizeof(float)だけ構造体データを書き込むアドレスをeeAddress+=sizeof(float)'としてシフトさせる。 データを書き込むにはEEPROM.put(eeAddress, customVar);`とすれば書き込める。

MyObject customVar = {
3.14f,
65,
"Working!"
};
eeAddress += sizeof(float); //最初に書き込みを行った小数に用いたアドレス数だけシフト
EEPROM.put(eeAddress, customVar);

3. EEPROMへの小数、構造体データの読み込み

 上でEEPROMに書き込んだデータを今度はEEPROMから読み込む方法を示す。最初に書き込んだfloat型のfを読み出すにはEEPROM.get( eeAddress, f );とする。 次に構造体を読み出すには、eeAddress = sizeof(float);としてシフトさせてからEEPROM.get( eeAddress, customVar );

 float f = 0.00f;
 int eeAddress = 0; //最初に読み出すアドレス番号
 EEPROM.get( eeAddress, f ); //最初に書き込んだ変数fを読み出す
 Serial.println( f, 3 );  //読み出したfをシリアルモニタに表示
 eeAddress = sizeof(float); //最初に読み込んだ小数分のアドレス数だけシフト
 MyObject customVar; //構造体の定義
 EEPROM.get( eeAddress, customVar ); //構造体の読み出し

Serial.println( "Read custom object from EEPROM: " );
Serial.println( customVar.field1 );  //読み出した構造体表示
Serial.println( customVar.field2 );
Serial.println( customVar.name );

4. EEPROMへの書き込み・読み出し例

 上のEEPROMの書き出し・読み出しを実行するスケッチを以下に示す。書き出し部分をwrite_data()、読み出し部分をread_data()という関数にして、Setup関数内で実行するようにした。またEEPROMに書き込まれているデータが1バイトの整数であることを確認するためにloop関数内でEEPROM.read()でアドレスごとに書き込まれているデータを表示させるようにした。

#include <EEPROM.h>

struct MyObject {
float field1;
byte field2;
char name[10];
};

int value, a;
void setup()
{
Serial.begin(9600);
write_data();
delay(1000);
read_data();
delay(1000);
}
  
void loop()
{
  
  value = EEPROM.read(a);

  Serial.print(a);
  Serial.print("\t");
  Serial.print(value);
  Serial.println();

  a = a + 1;

  if (a == 512)
    a = 0;

  delay(500);
 
}

void write_data(){
  
  float f = 123.456f;  // float型を明記
  int eeAddress = 0;   // 書き込むデータの最初のアドレス

  EEPROM.put(eeAddress, f);
  Serial.println("Written float data type!");

  MyObject customVar = {
    3.14f,
    65,
    "Working!"
  };

  eeAddress += sizeof(float); //最初に書き込みを行った小数に用いたアドレス数だけシフト

  EEPROM.put(eeAddress, customVar);
  Serial.println("Written custom data type!");

}

void read_data(){
  float f = 0.00f;
  int eeAddress = 0; //最初に読み出すアドレス番号

  Serial.print( "Read float from EEPROM: " );

  EEPROM.get( eeAddress, f );
  Serial.println( f, 3 ); 

  eeAddress = sizeof(float); 
  MyObject customVar; 
  EEPROM.get( eeAddress, customVar );

  Serial.println( "Read custom object from EEPROM: " );
  Serial.println( customVar.field1 );
  Serial.println( customVar.field2 );
  Serial.println( customVar.name );
}

上のスケッチをTinkercadで実行するとシリアルモニタに以下のように表示され、EEPROMへのデータの書き込み・読み出しができており、さらにEEPROMのアドレスごとには1バイトの整数が書き込まれていることが確認できる。

Written float data type!
Written custom data type!
Read float from EEPROM: 123.456
Read custom object from EEPROM: 
3.14
65
Working!
0   121
1   233
2   246
3   66
4   195
5   245
6   72
7   64
8   6

5. まとめ

 今回はEEPROMへの小数、構造体データの書き込み・読み出しの方法、仕組みについて紹介した。