Hi everyone, I'm having a problem with the Arduino Mega EEPROM. i don't know why my EEPROM is randomly overwritten by Serial or client print. someone ever met this problem?
do i need to provide my code?
Oh, It's not randomly, but when i got request from client or send request to server, my struct that i put on EEPROM overwritten
My crystal ball is on vacation....
Can it possibly be a code issue?
I tried as simple as possible
- clear EEPROM
#include <EEPROM.h>
void setup()
{
Serial.begin(9600);
for (int i = 0; i < EEPROM.length(); i++)
{
EEPROM.write(i, 0);
}
Serial.println("Done");
}
void loop()
{
}
- run main code
#include <EEPROM.h>
#include <string.h>
#include <SPI.h>
#include <Ethernet.h>
#include <ArduinoJson.h>
#include <base64.hpp>
// data device
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip_device(192, 168, 0, 111);
String id_device = "000001";
String id_server = "999999";
// server data
struct addressAndKey
{
String ip;
String port;
String public_key_base64;
};
addressAndKey server_data;
addressAndKey destination_data;
// addressAndKey server_data = {"192.168.0.2", "8081", ""};
// addressAndKey destination_data = {"192.168.0.2", "8081", ""};
// status
String read_request;
int message_request = 0;
// server and client
EthernetServer server(80);
String getpublickey_path = "GET /publickey HTTP/1.0";
String postmsg_path = "POST /api/msg HTTP/1.0";
byte setup_needed = 0;
uint8_t public1[32], public2[32], private1[32];
int sss = 0;
void setup()
{
Serial.begin(9600);
delay(1000);
// if (1)
// Static key
if (EEPROM.read(0) == setup_needed)
{
char a[] = "12345678901234561234567890123456";
for (int i = 0; i < 32; i++)
{
public1[i] = a[i];
private1[i] = a[i];
}
Serial.println("Start new client");
server_data = {"192.168.0.100", "8081", "UxYcxXY3/eGocjpDz5kpHGhOSFEpnzK82GDF+iNUFA4="};
destination_data = {"192.168.0.100", "8081", "UxYcxXY3/eGocjpDz5kpHGhOSFEpnzK82GDF+iNUFA4="};
EEPROM.put(0, 1);
EEPROM.put(5, public1);
EEPROM.put(40, private1);
EEPROM.put(75, server_data);
EEPROM.put(145, destination_data);
uint8_t p[44];
char res[100];
encode_base64(public1, sizeof(public1), p);
Serial.println((char *)p);
encode_base64(private1, sizeof(public1), p);
Serial.println((char *)p);
Serial.println(server_data.ip);
Serial.println(server_data.port);
Serial.println(server_data.public_key_base64);
Serial.println(destination_data.ip);
Serial.println(destination_data.ip.length());
Serial.println(destination_data.port);
Serial.println(destination_data.public_key_base64);
}
else
{
Serial.println("Start load client");
EEPROM.get(5, public1);
EEPROM.get(40, private1);
EEPROM.get(75, server_data);
EEPROM.get(145, destination_data);
uint8_t p[44];
encode_base64(public1, sizeof(public1), p);
Serial.println((char *)p);
encode_base64(private1, sizeof(public1), p);
Serial.println((char *)p);
Serial.println(server_data.ip);
Serial.println(server_data.ip.length());
Serial.println(server_data.port);
Serial.println(server_data.public_key_base64);
Serial.println(destination_data.ip);
Serial.println(destination_data.ip.length());
Serial.println(destination_data.port);
Serial.println(destination_data.public_key_base64);
}
initConnection();
Serial.println("Client Ready");
}
void loop()
{
runClient();
}
void initConnection()
{
while (!Serial)
{
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Start Client");
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip_device);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware)
{
Serial.println("Ethernet shield was not foun Sorry, can't run without hardware. :(");
while (true)
{
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF)
{
Serial.println("Ethernet cable is not connecte");
}
// start the server
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
String runClient()
{
String type, base64;
// listen for incoming clients
EthernetClient client = server.available();
if (client)
{
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected())
{
while (client.available())
{
char c = client.read();
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (read_request.length() < 25)
{
read_request += c;
}
if (c == '\n' && currentLineIsBlank)
{
if (read_request.substring(0, 19) == "GET /publickey HTTP")
{
StaticJsonDocument<80> doc;
uint8_t p[50];
int len = encode_base64(public1, sizeof(public1), p);
doc["public_key"] = (String)(char *)p;
// Serial.println("Sending response");
// send a standard http response header
client.println("HTTP/1.0 200 OK");
client.println("Content-Type: application/json");
client.println();
serializeJsonPretty(doc, client);
client.stop();
}
else
{
client.stop();
}
}
else if (c == '\n')
{
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r')
{
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1000);
// close the connection:
read_request = "";
client.stop();
Serial.println(F("client disconnected"));
return base64;
}
}
DynamicJsonDocument _deserializeJson(EthernetClient client)
{
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 200;
DynamicJsonDocument doc(capacity);
DeserializationError error = deserializeJson(doc, client);
if (error)
{
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
client.stop();
}
return doc;
}
this is my serial port

-
send GET request to http://192.168.0.111/publickey
this is my request from postman
and this from serial monitor
-
press reset button
my EEPROM data overwriten. It getting worse when i use my full program

server_data is a struct of three Strings.
It makes no sense to EEPROM.put a String.
Any String will only "put" six bytes to EEPROM.
hmm, but when I'm not sending request it work fine
should i convert my string to char, and convert every singgle char to byte?
or any work around?
A String is a class.
When you "EEPOM.put" an instance of a String, only the private data of the class is written, not the contents of the string that it encapsulates.
Similarly, "get"ting back a String only retrieves the (potentially invalid) private data.
I found the solution, now I use this tutorial, but dont put these function inside function (i try to make my code clean) it doesn't work for me
The tutorial you reference states
You can only write bytes into the EEPROM. A String is an object which may contain many bytes. Also, be sure to understand that the String data type is specific to the Arduino language. It’s different from std::string and any other string data type you may find elsewhere.
To save a String into the EEPROM, we’ll have to write each byte separately, one by one.
I don't see where you follow that procedure.
