Проблема с сохранением переменной «char» в EEPROM на ESP32.

esp32 eeprom char

Я создаю проект, в котором мне нужно сохранить учетные данные 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

Может ли кто-нибудь мне помочь?

, 👍0

Обсуждение

в чем конкретно проблема? ... но не переменные Char не описывает, что на самом деле происходит... пожалуйста, обновите свой вопрос выше... не *добавляйте комментарий* ниже, @jsotola

В вашей процедуре чтения вы пытаетесь прочитать длину строки из EEPROM, но вы никогда не сохраняли там длину, а только сами строки с нулевым завершением. Чтобы это работало, вам нужно будет записать strlen() в EEPROM непосредственно перед строкой, @chrisl


1 ответ


Лучший ответ:

1

В вашем коде имеется несколько проблем.

  1. Если strlen(anystring) равен нулю, вы ничего не пишете, а увеличиваете offset.
  2. Вы пытаетесь прочитать длину строк из EEPROM, но никогда не записываете их туда.

Некоторые вещи сложны, но их можно упростить.

  1. Вам не нужно явно писать '\0' (маркер конца строки), поскольку каждая из ваших строк уже включает его.
  2. Увеличьте 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(). Вам следует прочитать его документацию и рассмотреть возможность использования.

,