following sketch will run totally fine and as expected :
#include <Wire.h>
#include "SparkFun_External_EEPROM.h"
ExternalEEPROM ExtEEPROM;
char username[33] = "";
char password[65] = "";
void setup()
{
Serial.begin(115200);
delay(1000);
Wire.begin();
#define EEPROM_ADDRESS 0b1011000 // 0x58
ExtEEPROM.setMemorySize(256000/8); // 256kbit = 32kbyte
ExtEEPROM.setPageSize(64); // 64 byte page size.
ExtEEPROM.enablePollForWriteComplete();
ExtEEPROM.setPageWriteTime(10); // max. ms for AT24C128
if (ExtEEPROM.begin(EEPROM_ADDRESS, Wire) == false)
{
Serial.println("No memory detected. Freezing.");
while (1);
}
Serial.println("Memory detected!");
String uuu = "myusername";
String ppp = "mypassword";
uuu.toCharArray(username, sizeof(username) - 1);
ppp.toCharArray(password, sizeof(password) - 1);
Serial.print("password=");Serial.println(password);
ExtEEPROM.put(0, username);
//delay(100);
ExtEEPROM.put(0 + sizeof(username), "greatnewpassword");
}
void loop() {
char xxx[33] = "";
ExtEEPROM.get(0, xxx);
Serial.print("xxx=");Serial.println(xxx); // prints the username
char yyy[33] = "";
ExtEEPROM.get(0 + sizeof(username), yyy);
Serial.print("yyy=");Serial.println(yyy); // prints the password
delay(1000);
}
However, if I replace ExtEEPROM.put(0 + sizeof(username), "greatnewpassword");
to ExtEEPROM.put(0 + sizeof(username), password);
, then yyy
prints empty in the serial monitor. Why?
3 Answers 3
As Majenko already mentions:
.get() and .put() should only be used for atomic, self-contained, types like int or float, not pointers like char *.
Not sure what atomic means here, but you may .put and .get any data type, especially a struct.
struct EPROMData {
char username[33];
char password[65];
};
EPROMData data {"myusername","mypassword"};
void setup() {
...
ExtEEPROM.put(0,data);
}
void loop() {
EPROMData d;
ExtEEPROM.get(0,d);
Serial.print("user="); Serial.println(d.username);
...
}
Sure, if the data type is a pointer or a String object (containing a pointer only), you won't be happy with .put / .get
-
1By atomic I mean "it is a thing complete in itself". A struct is complete. An int is complete. A char * is not complete since it doesn't contain the data, it is only a pointer to it. So it's not "atomic". Same goes for a String object, since the object doesn't contain the string data, only a pointer to allocated memory that contains the string data.Majenko– Majenko2022年03月03日 00:08:15 +00:00Commented Mar 3, 2022 at 0:08
.get
and .put
are being passed a char pointer, not the contents of a char array. Thus you're not writing the content of the string but the address in memory where it's being stored.
With a string literal that is fixed and never changes, so what you write and what you read are fine. With a variable though the address could be anything, and storing the address of some RAM where a string is stored is pointless.
.get()
and .put()
should only be used for atomic, self-contained, types like int
or float
, not pointers like char *
.
Instead you need to be using the .read(address, buffer, size)
and .write(address, buffer, size)
functions to read and write the contents of your char arrays.
-
In the OP's code,
get()
andput()
are being passed actual arrays, not pointers. As the arrays are being passed by reference, they do not decay to pointers.Edgar Bonet– Edgar Bonet2022年03月03日 08:27:13 +00:00Commented Mar 3, 2022 at 8:27
problem seems to be the lib I am using. I think it can not handle data overlapping page size.
if I replace from this
char username[33] = "";
char password[65] = "";
to this:
char username[16] = "";
char password[16] = "";
everything works fine as it saves and reads from the EEPROM via I2C.
any_boolean == false
, use!any_boolean
. If you think think, you should make sure that anyone understands, then I'd recommend(any_boolean == false) == true
. :-Dsizeof
is an operator, not a function, so usesizeof variable
. However, its operand can be a type, and then it needs parentheses for syntactIcal reasons. This leads to this ubiquitous bad habit to write it as a function.password
, rather than a pointer produced by its decay (likechar *foo = password; ExtEEPROM.put(..., foo);
)?