Проблема с сохранением переменной «char» в EEPROM на ESP32.
Я создаю проект, в котором мне нужно сохранить учетные данные Wi-Fi в EEPROM. На данный момент я могу хранить массив bool в EEPROM, но не могу хранить переменные char
из-за сбоя ESP32. Я не могу поделиться полным кодом, так как он ОЧЕНЬ длинный, но вот проблемные функции:
Чтобы сохранить в EEPROM:
/////////////////////////////////// РАБОТАЮЩИЙ////////////////////////////////
void saveToEEPROM() {
// Сохраняем содержимое массива в памяти EEPROM
for (int i = 0; i < NUM_PARAM_ITEMS; i++) {
EEPROM.write(i, menu_items_param_bool[i]);
}
/////////////////////////////////////////////////// /////////////////////////////////////
//////////////////////////////////НЕ РАБОТАЕТ////////////// //////////////////
// Сохраняем учетные данные WiFi в EEPROM, если не пусто
int offset = NUM_PARAM_ITEMS;
if (strlen(ssid1) > 0) {
for (int i = 0; i < strlen(ssid1); i++) {
EEPROM.write(offset + i, ssid1[i]);
}
offset += strlen(ssid1);
EEPROM.write(offset, '\0'); // завершаем нулем строку SSID1
}
offset++;
if (strlen(password1) > 0) {
for (int i = 0; i < strlen(password1); i++) {
EEPROM.write(offset + i, password1[i]);
}
offset += strlen(password1);
EEPROM.write(offset, '\0'); // завершаем нулем строку Password1
}
offset++;
if (strlen(ssid2) > 0) {
for (int i = 0; i < strlen(ssid2); i++) {
EEPROM.write(offset + i, ssid2[i]);
}
offset += strlen(ssid2);
EEPROM.write(offset, '\0'); // завершаем нулем строку SSID2
}
offset++;
if (strlen(password2) > 0) {
for (int i = 0; i < strlen(password2); i++) {
EEPROM.write(offset + i, password2[i]);
}
offset += strlen(password2);
EEPROM.write(offset, '\0'); // завершаем строку Password2 нулем
}
EEPROM.commit(); // Не забудьте вызвать функцию commit(), чтобы сохранить данные в EEPROM
}
Чтобы прочитать данные из EEPROM:
void readFromEEPROM() {
//////////////////////////////////РАБОТАЮЩИЙ/////////////// /////////////////
// Читаем содержимое памяти EEPROM и восстанавливаем его в массив
for (int i = 0; i < NUM_PARAM_ITEMS; i++) {
menu_items_param_bool[i] = EEPROM.read(i);
}
//////////////////////////////////НЕ РАБОТАЕТ////////////// /////////////////////
// Читаем учетные данные WiFi из EEPROM, если они не пусты
int offset = NUM_PARAM_ITEMS;
// Чтение SSID1
int ssid1Length = EEPROM.read(offset);
if (ssid1Length > 0) {
for (int i = 0; i < ssid1Length; i++) {
ssid1[i] = (char)EEPROM.read(offset + i + 1);
}
ssid1[ssid1Length] = '\0'; // завершаем нулем строку SSID1
Serial.print("SSID1: ");
Serial.println(ssid1);
}
offset += ssid1Length + 1;
// Читаем пароль1
int password1Length = EEPROM.read(offset);
if (password1Length > 0) {
for (int i = 0; i < password1Length; i++) {
password1[i] = (char)EEPROM.read(offset + i + 1);
}
password1[password1Length] = '\0'; // завершаем нулем строку Password1
Serial.print("PASSWORD1: ");
Serial.println(password1);
}
offset += password1Length + 1;
// Чтение SSID2
int ssid2Length = EEPROM.read(offset);
if (ssid2Length > 0) {
for (int i = 0; i < ssid2Length; i++) {
ssid2[i] = (char)EEPROM.read(offset + i + 1);
}
ssid2[ssid2Length] = '\0'; // завершаем нулем строку SSID2
Serial.print("SSID2: ");
Serial.println(ssid2);
}
offset += ssid2Length + 1;
// Читаем пароль2
int password2Length = EEPROM.read(offset);
if (password2Length > 0) {
for (int i = 0; i < password2Length; i++) {
password2[i] = (char)EEPROM.read(offset + i + 1);
}
password2[password2Length] = '\0'; // завершаем строку Password2 нулем
Serial.print("PASSWORD2: ");
Serial.println(password2);
}
}
И переменные для сохранения и чтения:
char ssid1[32] = "ssid1"; // SSID первой сети Wi-Fi
char password1[64] = "password1"; // Пароль первой сети Wi-Fi
char ssid2[32] = "ssid2"; // SSID второй сети Wi-Fi
char password2[64] = "password2"; // Пароль второй сети Wi-Fi
Может ли кто-нибудь мне помочь?
@Loic Daigle, 👍0
Обсуждение1 ответ
Лучший ответ:
В вашем коде имеется несколько проблем.
- Если
strlen(anystring)
равен нулю, вы ничего не пишете, а увеличиваетеoffset
. - Вы пытаетесь прочитать длину строк из EEPROM, но никогда не записываете их туда.
Некоторые вещи сложны, но их можно упростить.
- Вам не нужно явно писать
'\0'
(маркер конца строки), поскольку каждая из ваших строк уже включает его. - Увеличьте
offset
непосредственно в курсе.
Это возможное исправленное решение. Он использует длину и маркер конца строки для каждой сохраненной строки.
// Запись любой строки
int anystringLength = strlen(anystring);
EEPROM.write(offset, anystringLength);
offset++;
for (int i = 0; i <= anystringLength; i++) {
EEPROM.write(offset, anystring[i]);
offset++;
}
// Читаем любую строку
int anystringLength = EEPROM.read(offset);
offset++;
for (int i = 0; i <= anystringLength; i++) {
anystring[i] = (char)EEPROM.read(offset);
offset++;
}
// начало вывода отладки
Serial.print("any String: ");
Serial.println(anystring);
// конец отладочного вывода
Примечание. Чтобы прояснить ситуацию, использование offset
и его приращение разделены. Хотя вы можете их объединить. Однако краткий код обычно интерпретируется неправильно.
Это еще одно возможное решение. Вместо того, чтобы ожидать длину, записанную перед строкой, читайте ее, пока не найдете маркер конца строки.
Цикл записи записывает все символы, включая последний маркер конца строки. Это работает и для пустых строк.
int i;
// Пишем любую строку
i = 0;
do {
char c = anystring[i];
EEPROM.write(offset, c);
offset++;
i++;
} while (c != '\0');
Цикл чтения делает то же самое в противоположном направлении. Использование цикла do
- while
гарантирует, что маркер конца строки будет прочитан в любом случае.
int i;
// Читаем любую строку
i = 0;
do {
char c = EEPROM.read(offset);
anystring[i] = c;
offset++;
i++;
} while (c != '\0');
// начало вывода отладки
Serial.print("any String: ");
Serial.println(anystring);
// конец отладочного вывода
Как и в оригинале, в решениях отсутствует проверка ошибок, например, слишком длинных строк, которые оставлены читателю в качестве упражнения.
Еще один бонусный балл вы получите, если вы извлечете эти циклы в функции. Это упрощает код и удаляет дубликаты. [Изменить] Я обнаружил, что класс EEPROM
уже предоставляет writeString()
и readString()
. Вам следует прочитать его документацию и рассмотреть возможность использования.
- ESP32: лучший способ встраивания сертификатов
- Как установить начальное значение eeprom при перепрошивке ESP32
- заставить EEPROM.h использовать пользовательский раздел eeprom
- Arduino IDE EEPROM put(), затем read() возвращает разные данные на ESP32
- Что не так с тем, как я записываю и/или считываю адреса EEPROM?
- Esp32: загрузить файл eeprom
- EEPROM: управление сопоставлением адресов между версиями прошивки
- Является ли использование malloc() и free() действительно плохой идеей для Arduino?
в чем конкретно проблема? ...
но не переменные Char
не описывает, что на самом деле происходит... пожалуйста, обновите свой вопрос выше... не *добавляйте комментарий* ниже, @jsotolaВ вашей процедуре чтения вы пытаетесь прочитать длину строки из EEPROM, но вы никогда не сохраняли там длину, а только сами строки с нулевым завершением. Чтобы это работало, вам нужно будет записать
strlen()
в EEPROM непосредственно перед строкой, @chrisl