0
Platform
  • Hardware: [nodemcu amica ESP8266MOD]
  • Core Version: [nodemcu-master-21-modules-2018-03-17-17-09-10]
  • Development Env: [Arduino IDE|]
  • Operating System: [Windows|]

Settings in IDE

  • Module: |Nodemcu]
  • Flash Mode: [qio|dio|other]?
  • Flash Size: [1MB]
  • lwip Variant: [v2 Lower Memory]
  • Reset Method: [nodemcu]
  • Flash Frequency: [40Mhz]
  • CPU Frequency: [80Mhz]
  • Upload Using: [SERIAL]
  • Upload Speed: [115200] (serial upload only)

Problem Description

hi, in my code i did a simple thing. i get the data from jSon object and write them to the EEPROM. once i write them to eeprom i can read the relevant data from that writing function handleFinishWizard() (i have put reading functions here n there to find where is the problem) .When i write data and finish it i can read the data.once its over when the program moved to the loop, eeprom data are corrupted and it doesnt display anything. i attached the output in debug message. whats the problem here?

[MCVE] Sketch

code in github CODE LINK

Debug Messages

```
add 1
aid 1
station: c0:ee:fb:ed:3b:0e join, AID = 1
value on EEPROM ADD: 
OnePlus 3T
test123@abc
test.com

value on EEPROM ADD: 
OnePlus 3T
test123@abc
test.com

value on EEPROM ADD: 
OnePlus 3T
test123@abc
test.com

value on EEPROM ADD: 
OnePlus 3T
test123@abc
test.com

value on EEPROM ADD: 
OnePlus 3T
test123@abc
test.com

value on EEPROM saveBefore: 
⸮?

⸮?

value on EEPROM saveBefore: 
⸮?

⸮?

value on EEPROM saveBefore: 
⸮?

⸮?

value on EEPROM saveBefore: 
⸮?

⸮?

value on EEPROM saveBefore: 
⸮?

⸮?

value on EEPROM save: 




value on EEPROM save: 




value on EEPROM save: 

```

4
  • use SPIFFS with 8266, so much better than EEPROM
    – dandavis
    Mar 18, 2018 at 12:55
  • @dandavis yes after the problem i moved to SPIFFS. saved data in json format.easy
    – namila007
    Mar 18, 2018 at 18:24
  • EEPROM has 100K cycles of recording data and then it will probably stop. Have you written to this EEPROM more than 100K times?
    – tony gil
    Jul 15, 2019 at 12:47
  • 1
    @tonygil no, this happened because of I wrote pointers instead of values
    – namila007
    Jul 17, 2019 at 4:27

1 Answer 1

1

Look at this code:

void setupCredentials(const char *ssid, const char *password,
                      const char *link) {
  int addr = 0;

  EEPROM.begin(512);
  addr = sizeof(int);
  EEPROM.put(addr, ssid);
  delay(10);
  addr += sizeof(st_ssid);
  EEPROM.put(addr, password);
  delay(10);
  addr += sizeof(st_password);
  EEPROM.put(addr, link);
  delay(10);
  EEPROM.commit();

You are calling EEPROM.put(addr, ssid) with ssid being a const char*. A pointer to some memory location. Notice that you only give it a start address and a pointer, not the length of your data.

Have a look at the implementation of the put function:

  template<typename T> 
  const T &put(int const address, const T &t) {
    if (address < 0 || address + sizeof(T) > _size)
      return t;
    if (memcmp(_data + address, (const uint8_t*)&t, sizeof(T)) != 0) {
      _dirty = true;
      memcpy(_data + address, (const uint8_t*)&t, sizeof(T));
    }

    return t;
}

What it essentially does is copy your given object const T &t into its internal _databuffer. The size of the data saved is determined by sizeof(T).

In your example t = ssid, T = const char* and sizeof(T) = sizeof(char*) = 4 and addr= sizeof(int) = 4.

What you are doing here is not to save the string that ssid points to in memory but the pointer value of ssid. After you leave the function the data pointed to by ssid will be de-allocated at some point and the memory will be overwritten by something else.

When you do a print directly in the function you are retrieving the pointer value of ssid 3 times and print that value. At that point the data is still there and everything is okay. Then if you print it again after leaving the function you get garbage because the local data is gone after the function call handleSetup is left.

What you want here is to not use a const char* in your second argument to a EEPROM.put(address, object) call but a char [20], for example. This way the put will work correctly.

Example:

// Assume EEPROM.begin() was called already
void EEPROM_SaveSSID(const int address, const char* str) {
    char ssid_buf[20];
    strncpy(ssid_buf, sizeof(ssid_buf) - 1, str);
    EEPROM.put<char[20]>(address, ssid_buf[0]); //sizeof(ssid_buf) = 20
    //don't forget to EEPROM.commit(); and EEPROM.end()
}

/* read SSID into a pre-allocated buffer */
void EEPROM_ReadSSID(const int address, char ssid_buf[20]) {
    EEPROM.get(address, ssid_buf); //sizeof(ssid_buf) = 20
}

If you do not like the semantics of these C++-templates auto-determining the size of read/write calls, you can always use bytewise read and write calls:

void EEPROM_SaveSSID(const int address, const char* str) {
    for(size_t i = 0; i < strlen(str)) {
        EEPROM.write((int)(address + i), str[i]);
    }
}

/* always read 20 bytes starting from given address into buffer */
void EEPROM_ReadSSID(const int address, char ssid_buf[20]) {
    for(size_t i = 0; i < sizeof(ssid_buf); i++) {
        ssid_buf[i] = EEPROM.read((int)(address + i));
    }
}

See "EEPROM" (actually: Flash-emulated EEPROM) implementation code at https://github.com/esp8266/Arduino/tree/master/libraries/EEPROM.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.