EEPROMガイド

ArduinoボードのEEPROM(Erasable Programmable Read-Only Memory)の使い方を学びます。


LAST REVISION: 2022/09/28 17:44


Arduinoボード上のマイクロコントローラは、512バイトのEEPROMを搭載しています。EEPROMは、ボードの電源を切っても値が消えないメモリで、小さいハードドライブのようなものです。

EEPROMクラスの機能は、ボード用のプラットフォームに自動的に含まれています。つまり、追加のライブラリをインストールする必要はありません。

必要なハードウェア

以下の全てのボードはEEPROMを搭載しています。

EEPROM Clear

この例は、EEPROM.write()関数を使い、全てのバイトを0に設定し、新しい情報を書くために初期化します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
 * EEPROM Clear
 *
 * Sets all of the bytes of the EEPROM to 0.
 * Please see eeprom_iteration for a more in depth
 * look at how to traverse the EEPROM.
 *
 * This example code is in the public domain.
 */

#include <EEPROM.h>

void setup() {
  // initialize the LED pin as an output.
  pinMode(13, OUTPUT);
  
  /***
    Iterate through each byte of the EEPROM storage.
    Larger AVR processors have larger EEPROM sizes, E.g:
    - Arduino Duemilanove: 512 B EEPROM storage.
    - Arduino Uno:         1 kB EEPROM storage.
    - Arduino Mega:        4 kB EEPROM storage.
    Rather than hard-coding the length, you should use the pre-provided length function.
    This will make your code portable to all AVR processors.
  ***/

  for (int i = 0 ; i < EEPROM.length() ; i++) {
    EEPROM.write(i, 0);
  }

  // turn the LED on when we're done
  digitalWrite(13, HIGH);
}

void loop() {
  /** Empty loop. **/
}

EEPROM CRC

CRCは、データが変更されたり、破壊されたりしたかを判定するための簡単な手段です。この例は、EEPROMの値から直接CRCの値を計算します。このCRCは署名のようなもので、計算されたCRCの変化は、格納されたデータに変更があることを意味します。この例の目的は、EEPROMのオブジェクトが、配列のように利用できることを示すことです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/***

    Written by Christopher Andrews.

    CRC algorithm generated by pycrc, MIT licence ( https://github.com/tpircher/pycrc ).

    A CRC is a simple way of checking whether data has changed or become corrupted.

    This example calculates a CRC value directly on the EEPROM values.

    The purpose of this example is to highlight how the EEPROM object can be used just like an array.

***/

#include <Arduino.h>
#include <EEPROM.h>

void setup() {

  //Start serial

  Serial.begin(9600);

  while (!Serial) {

    ; // wait for serial port to connect. Needed for native USB port only

  }

  //Print length of data to run CRC on.

  Serial.print("EEPROM length: ");

  Serial.println(EEPROM.length());

  //Print the result of calling eeprom_crc()

  Serial.print("CRC32 of EEPROM data: 0x");

  Serial.println(eeprom_crc(), HEX);

  Serial.print("\n\nDone!");
}

void loop() {

  /* Empty loop */
}

unsigned long eeprom_crc(void) {

  const unsigned long crc_table[16] = {

    0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,

    0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,

    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,

    0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c

  };

  unsigned long crc = ~0L;

  for (int index = 0 ; index < EEPROM.length()  ; ++index) {

    crc = crc_table[(crc ^ EEPROM[index]) & 0x0f] ^ (crc >> 4);

    crc = crc_table[(crc ^ (EEPROM[index] >> 4)) & 0x0f] ^ (crc >> 4);

    crc = ~crc;

  }

  return crc;
}

EEPROM Get

この例の目的は、putメソッド・getメソッドと、writeメソッド・readとのふるまいの違いを示すことです。EEPROMから異なる変数を取得すると、変数のデータ型に関連したバイト数のデータを取得します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/***

    eeprom_get example.

    This shows how to use the EEPROM.get() method.

    To pre-set the EEPROM data, run the example sketch eeprom_put.

    This sketch will run without it, however, the values shown

    will be shown from what ever is already on the EEPROM.

    This may cause the serial object to print out a large string

    of garbage if there is no null character inside one of the strings

    loaded.

    Written by Christopher Andrews 2015

    Released under MIT licence.

***/

#include <EEPROM.h>

void setup() {

  float f = 0.00f;   //Variable to store data read from EEPROM.

  int eeAddress = 0; //EEPROM address to start reading from

  Serial.begin(9600);

  while (!Serial) {

    ; // wait for serial port to connect. Needed for native USB port only

  }

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

  //Get the float data from the EEPROM at position 'eeAddress'

  EEPROM.get(eeAddress, f);

  Serial.println(f, 3);    //This may print 'ovf, nan' if the data inside the EEPROM is not a valid float.

  /***

    As get also returns a reference to 'f', you can use it inline.

    E.g: Serial.print( EEPROM.get( eeAddress, f ) );

  ***/

  /***

    Get can be used with custom structures too.

    I have separated this into an extra function.

  ***/

  secondTest(); //Run the next test.
}

struct MyObject {

  float field1;

  byte field2;

  char name[10];
};

void secondTest() {

  int eeAddress = sizeof(float); //Move address to the next byte after float 'f'.

  MyObject customVar; //Variable to store custom object read from EEPROM.

  EEPROM.get(eeAddress, customVar);

  Serial.println("Read custom object from EEPROM: ");

  Serial.println(customVar.field1);

  Serial.println(customVar.field2);

  Serial.println(customVar.name);
}

void loop() {

  /* Empty loop */
}

EEPROM Iteration

この例の目的は、全てのEEPROMメモリ領域を異なる方法で走査する方法を示すことです。このコードだけでは動作しません。どこかで利用するソースコード片として使用してください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/***

    eeprom_iteration example.

    A set of example snippets highlighting the

    simplest methods for traversing the EEPROM.

    Running this sketch is not necessary, this is

    simply highlighting certain programming methods.

    Written by Christopher Andrews 2015

    Released under MIT licence.

***/

#include <EEPROM.h>

void setup() {

  /***

    Iterate the EEPROM using a for loop.

  ***/

  for (int index = 0 ; index < EEPROM.length() ; index++) {

    //Add one to each cell in the EEPROM

    EEPROM[ index ] += 1;

  }

  /***

    Iterate the EEPROM using a while loop.

  ***/

  int index = 0;

  while (index < EEPROM.length()) {

    //Add one to each cell in the EEPROM

    EEPROM[ index ] += 1;

    index++;

  }

  /***

    Iterate the EEPROM using a do-while loop.

  ***/

  int idx = 0;  //Used 'idx' to avoid name conflict with 'index' above.

  do {

    //Add one to each cell in the EEPROM

    EEPROM[ idx ] += 1;

    idx++;

  } while (idx < EEPROM.length());

} //End of setup function.

void loop() {}

EEPROM Put

この例の目的は、EEPROMにデータを書き込むEEPROM.put()メソッドの使い方を示すことです。書き込まれるバイト数は、書き込む変数のデータ型や構造に依存します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/***

    eeprom_put example.

    This shows how to use the EEPROM.put() method.

    Also, this sketch will pre-set the EEPROM data for the

    example sketch eeprom_get.

    Note, unlike the single byte version EEPROM.write(),

    the put method will use update semantics. As in a byte

    will only be written to the EEPROM if the data is actually

    different.

    Written by Christopher Andrews 2015

    Released under MIT licence.

***/

#include <EEPROM.h>

struct MyObject {

  float field1;

  byte field2;

  char name[10];
};

void setup() {

  Serial.begin(9600);

  while (!Serial) {

    ; // wait for serial port to connect. Needed for native USB port only

  }

  float f = 123.456f;  //Variable to store in EEPROM.

  int eeAddress = 0;   //Location we want the data to be put.

  //One simple call, with the address first and the object second.

  EEPROM.put(eeAddress, f);

  Serial.println("Written float data type!");

  /** Put is designed for use with custom structures also. **/

  //Data to store.

  MyObject customVar = {

    3.14f,

    65,

    "Working!"

  };

  eeAddress += sizeof(float); //Move address to the next byte after float 'f'.

  EEPROM.put(eeAddress, customVar);

  Serial.print("Written custom data type! \n\nView the example sketch eeprom_get to see how you can retrieve the values!");
}

void loop() {

  /* Empty loop */
}

EEPROM Read

この例は、EEPROMの各バイトをEEPROM.read()関数を使って読み込む方法を示します。また、Arduinoソフトウェア(IDE)のシリアルウインドウにそれらの値を表示する方法も示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
 * EEPROM Read
 *
 * Reads the value of each byte of the EEPROM and prints it
 * to the computer.
 * This example code is in the public domain.
 */

#include <EEPROM.h>

// start reading from the first byte (address 0) of the EEPROM
int address = 0;
byte value;

void setup() {
  // initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
}

void loop() {
  // read a byte from the current address of the EEPROM
  value = EEPROM.read(address);

  Serial.print(address);
  Serial.print("\t");
  Serial.print(value, DEC);
  Serial.println();

  /***
    Advance to the next address, when at the end restart at the beginning.

    Larger AVR processors have larger EEPROM sizes, E.g:
    - Arduino Duemilanove: 512 B EEPROM storage.
    - Arduino Uno:         1 kB EEPROM storage.
    - Arduino Mega:        4 kB EEPROM storage.

    Rather than hard-coding the length, you should use the pre-provided length function.
    This will make your code portable to all AVR processors.
  ***/
  address = address + 1;
  if (address == EEPROM.length()) {
    address = 0;
  }

  /***
    As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an
    EEPROM address is also doable by a bitwise and of the length - 1.

    ++address &= EEPROM.length() - 1;
  ***/

  delay(500);
}

EEPROM Update

この例の目的は、書き込む場所の以前の値と異なるときだけデータを書き込むEEPROM.update()メソッドの使い方を示すことです。1回の書き込みに3.3msかかるので、この方法は実行時間を節約します。また、EEPROMは、同一箇所へは100,000回の書き込み回数制限があるので、同じ値の書き込みを避けることで、EEPROMの寿命を延ばします。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/***
   EEPROM Update method

   Stores values read from analog input 0 into the EEPROM.
   These values will stay in the EEPROM when the board is
   turned off and may be retrieved later by another sketch.

   If a value has not changed in the EEPROM, it is not overwritten
   which would reduce the life span of the EEPROM unnecessarily.

   Released using MIT licence.
 ***/

#include <EEPROM.h>

/** the current address in the EEPROM (i.e. which byte we're going to write to next) **/
int address = 0;

void setup() {
  /** Empty setup **/
}

void loop() {
  /***
    need to divide by 4 because analog inputs range from
    0 to 1023 and each byte of the EEPROM can only hold a
    value from 0 to 255.
  ***/
  int val = analogRead(0) / 4;

  /***
    Update the particular EEPROM cell.
    these values will remain there when the board is
    turned off.
  ***/
  EEPROM.update(address, val);

  /***
    The function EEPROM.update(address, val) is equivalent to the following:

    if( EEPROM.read(address) != val ){
      EEPROM.write(address, val);
    }
  ***/


  /***
    Advance to the next address, when at the end restart at the beginning.

    Larger AVR processors have larger EEPROM sizes, E.g:
    - Arduino Duemilanove: 512 B EEPROM storage.
    - Arduino Uno:         1 kB EEPROM storage.
    - Arduino Mega:        4 kB EEPROM storage.

    Rather than hard-coding the length, you should use the pre-provided length function.
    This will make your code portable to all AVR processors.
  ***/
  address = address + 1;
  if (address == EEPROM.length()) {
    address = 0;
  }

  /***
    As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an
    EEPROM address is also doable by a bitwise and of the length - 1.

    ++address &= EEPROM.length() - 1;
  ***/

  delay(100);
}

EEPROM Write

この例は、アナログ入力0から読んだ値を、EEPROM.write()関数を使って書き込む方法を示します。書き込まれた値は、ボードの電源を切っても保持され、後で他のスケッチから読み込むこともできます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*

 * EEPROM Write

 *

 * Stores values read from analog input 0 into the EEPROM.

 * These values will stay in the EEPROM when the board is

 * turned off and may be retrieved later by another sketch.

 */

#include <EEPROM.h>

/** the current address in the EEPROM (i.e. which byte we're going to write to next) **/
int addr = 0;

void setup() {

  /** Empty setup. **/
}

void loop() {

  /***

    Need to divide by 4 because analog inputs range from

    0 to 1023 and each byte of the EEPROM can only hold a

    value from 0 to 255.

  ***/

  int val = analogRead(0) / 4;

  /***

    Write the value to the appropriate byte of the EEPROM.

    these values will remain there when the board is

    turned off.

  ***/

  EEPROM.write(addr, val);

  /***

    Advance to the next address, when at the end restart at the beginning.

    Larger AVR processors have larger EEPROM sizes, E.g:

    - Arduno Duemilanove: 512b EEPROM storage.

    - Arduino Uno:        1kb EEPROM storage.

    - Arduino Mega:       4kb EEPROM storage.

    Rather than hard-coding the length, you should use the pre-provided length function.

    This will make your code portable to all AVR processors.

  ***/

  addr = addr + 1;

  if (addr == EEPROM.length()) {

    addr = 0;

  }

  /***

    As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an

    EEPROM address is also doable by a bitwise and of the length - 1.

    ++addr &= EEPROM.length() - 1;

  ***/

  delay(100);
}

オリジナルのページ

https://docs.arduino.cc/learn/programming/eeprom-guide

最終更新日

October 23, 2022

inserted by FC2 system