Save long int and float in EEPROM#

思路: 将长于一个字节的数值分成多个独立的字节分多次读写。最简单又高效的方法是使用 union。

使用 EEPROM.put() 和 EEPROM.get()#

Arduino 为8位处理器,在存储数据时,默认是写1字节。但 EEPROM 可以写任意长一字节的对象。

#include <EEPROM.h>
struct MyObject {
  float field1;
  byte field2;
  char name[10];
};

//Data to store.
MyObject customVar = {
  3.14f,
  65,
  "Working!"
};

EEPROM.put(eeAddress, customVar);

https://docs.arduino.cc/learn/built-in-libraries/eeprom#put

自定义方法#

How to write float value in EEPROM - Using Arduino / Programming Questions - Arduino Forum

1. The syntax of EEPROM.write() command is: EEPROM.write(address, byteData);

That means the allowable data range is: 0 to 255 (1-byte = 0x00 to 0xFF) -- only integer value and no fractional part.

2. When there is a floating point number (having integer and fractional part) like float x = 13.67, then four consecutive memory locations are needed to store the value f x. The said four memory locations will hole 32-bit (4x8) data which are generated according to binary332/IEEE-754 standard (Fig-1).

IEEE754Float

Figure-1:

3. Using write() method, we can store the value x of Step-2 by executing the following codes:


  float x = 13.67;
  byte *ptr;   
  ptr = (byte*)&x;  //ptr holds beginning address of 4-byte memory space containing value of x 
  for (int i = 0, address = 0; i < 4; i++, address++, ptr++)
  {
    EEPROM.write(address, *ptr);
  }

4. All the codes of Step-3 can be replaced by the following two lines of codes:

float   x =  13.67 ; 

put (address, x);

问题: 在不用 EEPROM.get() 方法时,怎么用自己的方法读回?

使用 Union#

这个方法非常底层,既可读也可写,不需要做转换,似乎是最好的方法。下面是原文[1]节选:

-11.7 is a float. When converted to binary it becomes: 11000001001110110011001100110011 This in hex is: C1 3B 33 33

The float is sent in reverse, so you get: 33 33 3B C1。你可以借助网站 [2] 可以帮助把浮点数转换成2进制的字面形式。

typedef union {
  float floatingPoint;
  byte binary[4];
} binaryFloat;

void setup() {
  // put your setup code here, to run once:
  binaryFloat hi;
  hi.floatingPoint = -11.7;
  Serial.begin(115200);
  Serial.write(hi.binary,4);
}

Unions a so cool! Basically the 'byte binary[4]' and 'float floatingPoint' are joined and share the same memory space, so you can access either, and if you change one, you change the other. You can have so much fun changing the byte array, and seeing what its floating point equivalent is

练习:用 Union 存取 int#

typedef union {
  float intNum;
  byte binary[2];
} binaryInt;

void setup() {
  // put your setup code here, to run once:
  binaryInt hi;
  hi.intNum = 0x1234;
  Serial.begin(9600);
  Serial.write(hi.binary,2);
}

Another easy example#

#include <EEPROM.h>

void writeIntIntoEEPROM(int address, int number)
{ 
  EEPROM.write(address, number >> 8);
  EEPROM.write(address + 1, number & 0xFF);
}

int readIntFromEEPROM(int address)
{
  return (EEPROM.read(address) << 8) + EEPROM.read(address + 1);
}

void setup() {
  Serial.begin(9600);
  writeIntIntoEEPROM(45, 18404);
  int number = readIntFromEEPROM(45);
  Serial.println(number);
}

void loop() {}

Arduino Store int into EEPROM - The Robotics Back-End

How To Save Values On Arduino With EEPROM - The Robotics Back-End

Reading more#

Sending 16 bit and 32 bit numbers with Arduino I2C – The Wandering Engineer

Saving Unsigned 16 Bit Integer to SD - Using Arduino / Storage - Arduino Forum

arduino due - How to package a 16 bit integer to send it with serial.write? - Arduino Stack Exchange