Нужна помощь с EEPROM, не сохраняющим значения массива на ESP8266 после перезапуска

У меня проблемы с программой. Я пытаюсь сохранить загруженную строку в массив, а затем записать этот массив в EEPROM. Я запускаю программу, загружаю новый массив и сохраняю его в EEPROM. все значения отображаются правильно, пока я не перезагрузлю или не выключу устройство. Я уверен, что перезаписываю или что-то очевидное, но я ломаюсь и прошу помощи.

Подпрограммы чтения и записи EEPROM находятся в нижней части кода. Я вызываю EEPROM_Write() в server.on после разбора http get.

EDIT: по отзывам удалено все, кроме функции, с помощью EEPROM.commit(); предложение включено... все еще не работает

void EEPROM_Write(){
Serial.begin(115200);
EEPROM.begin(280);
  // сохраняем значения в EEPROM
  for (int i = 0; i < pwmarray1Size; i++)
  {
    Serial.println(pwmarray1[i]);
    EEPROM.put( EEPROMStartAdress + (i * sizeof pwmarray1[0]), pwmarray1[i]);
  }
  Serial.println();
  EEPROM.commit();
 // EEPROM.end();
}

, 👍1

Обсуждение

что такое EEPROMStartAdress? вы можете поместить весь массив в EEPROM одним «путем», @Juraj


1 ответ


1

У ESP нет настоящей EEPROM. Вместо этого класс EEPROM для ESP использует флэш-память. Существует разница в реализации этого класса между Arduino и ESP:

В ESP все данные, которые вы записываете, сначала помещаются в буфер в оперативной памяти. Вам нужно вызвать EEPROM.commit(), чтобы фактически записать эти данные в базовую флэш-память.

Поэтому вам нужно добавить

EEPROM.commit();

до конца вашей функции EEPROM_Write(), иначе данные останутся в ОЗУ и, таким образом, будут потеряны при выключении питания или сбросе.


Я думаю, что ваша проблема (помимо фиксации) заключается не в вашей функции EEPROM_Write(), а в функции EEPROM_Read(). Если это работает неправильно, вы просто не сможете увидеть, правильно ли записываются данные. В вашем коде (который можно увидеть в истории редактирования) у вас есть эта функция:

void EEPROM_Read(){
   //загружаем массив pwmarray1 с сохраненными значениями в EPROM
  for (int x = 0; x < pwmarray1Size; x++){
    EEPROM.get(EEPROMStartAdress + (x * sizeof pwmarray1[0]), pwmarray1[x]);
        Serial.print("loading program from EPROM: "); 
    Serial.println(pwmarray1[x]);
    }
}

Хотя в EEPROM_Write() вы вызываете EEPROM.begin(280) каждый раз, вы не EEPROM.end() это там, и вы также не начинаете EEPROM в функции EEPROM_Read(). Я не уверен в базовой реализации, но у меня она начала работать, когда я начал и закончил объект EEPROM в обеих функциях.

Я написал тестовый код, который я составил из вашего кода и который для меня правильно сохраняет и читает массив через объект EEPROM во флэш-память. Он правильно сохраняет данные при сбросах и циклах питания. Вы можете управлять им через Serial Monitor. Просто введите c (для очистки массива до нуля), r (для чтения массива из EEPROM/flash) или i (для увеличения всех элементы массива и сохранить их в EEPROM/flash).

#include <EEPROM.h>

#define EEPROM_SIZE 280

int array[60] = {0};
const unsigned arraySize = sizeof array / sizeof array[0];

#define EEPROMStartAdress 0

void setup(){
  Serial.begin(115200);
  Serial.println("//////////////////////////////////////");
  delay(2000);
}

void loop(){
  if(Serial.available()){
    char c = Serial.read();
    switch(c){
      case 'c':
        for(uint8_t i=0;i<arraySize;i++) array[i] = 0;
        EEPROM_Write();
        Serial.println("EEPROM RESET");
        break;
      case 'r':
        EEPROM_Read();
        break;
      case 'i':
        for(uint8_t i=0;i<arraySize;i++) array[i] += 1;
        EEPROM_Write();
        break;
    }
  }
}

void EEPROM_Write(){
  EEPROM.begin(EEPROM_SIZE);
  // сохраняем значения в EEPROM
  for (int i = 0; i < arraySize; i++)
  {
    EEPROM.put( EEPROMStartAdress + (i * sizeof array[0]), array[i]);
  }
  EEPROM.commit();
  EEPROM.end();
}

void EEPROM_Read(){
  EEPROM.begin(EEPROM_SIZE);
  for (int x = 0; x < arraySize; x++){
    EEPROM.get(EEPROMStartAdress + (x * sizeof array[0]), array[x]);
    Serial.print(" ");
    Serial.print(array[x]);
    }
  Serial.println();
  EEPROM.end();
}

Удаление begin() и end() из EEPROM_Read(), а также end() из EEPROM_Write() дает мне те же результаты, которые вы описали как свою проблему.

,

этикетки вводят в заблуждение. Я использую «положить» и «получить». могу ли я использовать EEPROM.commit() после установки?, @deathrace2020

put и get - это просто оболочки для записи и чтения, которые помогают вам записывать более сложные данные, чем отдельные байты. На заднем фоне происходит то же самое. Так что да, вы можете использовать EEPROM.commit() после EEPROM.put()., @chrisl

Я добавил EEPROM.commit() и до сих пор не получаю значения, хранящиеся в EEPROM. Знаете ли вы, влияет ли расположение «EEPROMStartAdress»?, @deathrace2020

хорошо, я потратил 30 часов, глядя и пытаясь заставить эту работу работать безрезультатно. я проанализировал тест до одного числа. разместил новый вопрос здесь: https://stackoverflow.com/questions/62415395/eps8266-writing-number-to-eeprom-fails-to-write-returns- 0?fbclid=IwAR1QxJ_EXw8jqKaiLLNoDsChW2l0CpGUlQcm Tu3WrKaijchN4qc_8Mn5quo, @deathrace2020

В настоящее время я работаю над тестовым скетчем, но на данный момент моя функция your работает с моим ESP32. Я сделаю минимальный работающий тестовый скетч, который вы сможете протестировать на своей плате. Может быть, я смогу сделать это завтра вечером. EEPROMStartAdress просто сообщает функции, с чего начать запись в выделенном EEPROM. Не должно быть проблемой., @chrisl

если EEPROMStartAdress больше, чем выделенный размер, @Juraj

@deathrace2020 Теперь я смог точно воспроизвести и получить исправление. Я добавил решение, а также тестовый скетч, который я использовал, к ответу., @chrisl

вы можете записать весь массив одним вводом и прочитать его одним получением. `end' вызывает 'commit', @Juraj