Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Problems Using Sparkfun's External_EEPROM Library

Status
Not open for further replies.

Visitor

Well-Known Member
I am very much new to Arduino, but have been making good progress figuring this all out with its semicolons and curly brackets! When I have messed up the punctuation somewhere, it only takes seconds to track down the error, which is a relief.

I'm using Sparkfun's External_EEPROM library to store 4 bytes of numeric data, followed by a String of text data. I'm allowed ample room to accommodate the String. I am saving this data in a subroutine, and reading it back to verify it was saved. Because of the problems I'm having, I actually read it back to a different variable to be certain. This works; I get the same String back that I've stored.

C++:
  myMem.put(Addr, KeySpecialFunctions); //(location, data)
  myMem.put(Addr + 4, KeyStr); //(location, data)

  // check storage
  myMem.get(Addr, KeySpecialFunctions); //(location, data)
  String ReadKeyStr;
  myMem.get(Addr + 4, ReadKeyStr); //(location, data)
  SerialUSB.println("EEPROM Readback");
  
  SerialUSB.println(KeySpecialFunctions, BIN);
  SerialUSB.println(ReadKeyStr);

The problem occurs when I read the memory locations in a second subroutine. The 4 bytes of numerical data are read fine, but the String data is scrambled. I read it twice, to different variables to be sure, and both have the same scrambled results.

Can anyone see whatever dump mistake I'm making?

C++:
  myMem.get(Addr + 4, KeyData); //(location, data)
  SerialUSB.print("Key string: ");
  SerialUSB.println(KeyData);
  SerialUSB.println("");

  String ReadKeyStr;
  myMem.get(Addr + 4, ReadKeyStr); //(location, data)
  SerialUSB.println("EEPROM Readback");
  SerialUSB.println(ReadKeyStr);
 
How is your C++...
The problem occurs when I read the memory locations in a second subroutine.
C++ uses scoped variables and some "may" need re-intializing... ie.. where do you set Addr ?
 
Addr is calculated at the start of each subroutine. It's correct since the 4 bytes of numeric data are read back correctly. Most of the EEPROM is empty during my testing phase.
 
So conversion is the issue? If the bytes are correct but the string is corrupt then its not the mem get function..

I have never used sparkfuns library so I think I'll go and read the library..

One thing I've always hated is C and C++ types and castings..
 
No, I'm saving 4 numeric bytes, which read correctly. The Sparkfun library allows saving a String directly, and reads it back as a string.

Hmmm. I could read the string as bytes and see if it makes sense.

Yes, C++ is making my head hurt with types and castings! But things are getting clearer as I work more with it.
 
Assuming the external eeprom is a 24C32 type (16 bit address required) then I wrote the following to dump the contents,
Code:
void showEEPROM(uint16_t addr,uint16_t lines){
  char lineBuff[128];
  for(uint16_t j=0;j<lines;j++){
    uint8_t values[8];
    addByte(addr>>8,lineBuff);
    addByte(addr&0xff,&lineBuff[2]);
    strcat(lineBuff," ");
    for(uint16_t i=0;i<8;i++){
      values[i] = readI2CByte(addr++);
    }
    uint8_t n=5;              //point to first unused byte
    for(uint8_t i=0;i<8;i++){
      addByte(values[i],&lineBuff[n]);
      strcat(lineBuff," ");
      n+=3;
    }
    for(uint8_t i=0;i<8;i++){
      if(values[i]<32)
        lineBuff[n++]='.';
      else
        lineBuff[n++]=values[i];
    }
    lineBuff[n]=0;
    Serial.println(lineBuff);
  }
}

void addByte(uint8_t dat,char* buf){
  *buf++=hex4(dat>>4);
  *buf++=hex4(dat&0x0f);
  *buf=0;
}

uint8_t hex4(uint8_t dat){
  return((dat<10)?dat+'0':dat+('A'-10));
}

uint8_t readI2CByte(uint16_t data_addr){
  byte data = NULL;
  while(!wireReady(EEPROM_ADDR));
  Wire.beginTransmission(EEPROM_ADDR);
  Wire.write(data_addr>>8);
  Wire.write(data_addr&0xff);
  Wire.endTransmission();
  Wire.requestFrom(EEPROM_ADDR, 1); //retrieve 1 returned byte
  //delay(5);
  if(Wire.available()){
    data = Wire.read();
  }
  return data;
}

boolean wireReady(uint8_t addr){
  Wire.beginTransmission(addr);
  return(Wire.endTransmission()==0);
}
It produces this kind of output,
Code:
0000 9A 91 3B 60 51 05 18 03 ⸮⸮;`Q...
0008 62 67 3B 60 DB 05 A3 05 bg;`⸮.⸮.
0010 8E 68 3B 60 DB 05 A5 05 ⸮h;`⸮.⸮.
0018 BA 69 3B 60 DD 05 A6 05 ⸮i;`⸮.⸮.
0020 E6 6A 3B 60 DE 05 A8 05 ⸮j;`⸮.⸮.
0028 12 6C 3B 60 E0 05 A9 05 .l;`⸮.⸮.
0030 3E 6D 3B 60 E0 05 AB 05 >m;`⸮.⸮.
0038 6A 6E 3B 60 E2 05 AC 05 jn;`⸮.⸮.
The calling variables are Address in memory, number of lines to print.

HTH

Mike.
Edit, missed the function wireReady.
Edit2, I wrote the wireReady() function as the Arduino does't seem to have anyway to check if a previous write has completed - all the libraries I looked at had a delay after any write. Maybe someone knows different.
 
Last edited:
If your external memory is different then you just need to rewrite the readI2CByte routine.

Mike.
edit, missed this line too,
#define EEPROM_ADDR 0x50
 
No, I'm saving 4 numeric bytes, which read correctly. The Sparkfun library allows saving a String directly, and reads it back as a string.

Hmmm. I could read the string as bytes and see if it makes sense.

Yes, C++ is making my head hurt with types and castings! But things are getting clearer as I work more with it.
I would read an array..

The use of a union is brilliant for serializing

union STREAMABLE {
char stream[4];
long value;
} myStream;

The long can now be accessed byte by byte..
 
The C++ String class isn't a simple array of chars like you're use to... it's a dynamically allocated array that can grow and shrink as operations on them are performed.

You would be better off forgetting about them for the time being and just use a fixed length char[] array. That will get you a normal C array where you just null terminate the end.

C "strings" are a bit of a PITA, but they don't have all the issues associated with dynamic arrays and malloc.
 
What I'm trying to do seems simple enough. I'm making an external macro keypad to send Windows shortcuts, text strings or whatever to launch/control programs, invoke program functions or even just send text strings like a URL or maybe a string to type out your address.

Windows shortcuts are easy, something like Ctrl+Alt+A...some function keys and a single character. I'm using a Seeed Xiao (SamD) board for this. A byte for the SamD is 32 bits, which works out nicely. I count 31 "function keys" to encode, so I use 31 bits of a byte to indicate which are needed for a particular shortcut key.

I'm storing data for the 45 possible keys (3 sets of 15) in EEPROM. I decided on the ridiculous limit of about 320 characters per string, which still doesn't fill a 32KB EEPROM. When a key on the keypad is pressed, I'll fetch the function key byte (4 bytes as far as the EEPROM is concerned) and string from the EEPROM and send the appropriate data to the PC.

The string data is going astray someplace between storing it in the EEPROM and recovering it. It looks like I'm not even getting the right number of characters when reading from the other subroutine and sometimes other strings I have used seem to be coming from the EEPROM. As Tumbleweed said, I think using strings are the biggest part of the problem. I'm frustrated, but making sense of C++ gradually.
 
Read up on using char arrays as strings in C, and just use them with C++. You'll have to put up with calling functions like strcat, strlen, etc, but it'll work much better.

It's likely the sparkfun library worked by accident with String arguments.
 
Read up on using char arrays as strings in C, and just use them with C++. You'll have to put up with calling functions like strcat, strlen, etc, but it'll work much better.

It's likely the sparkfun library worked by accident with String arguments.

....sort of worked.... :(
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top