Retrieving strings from external eeprom - loosing first byte?

New here so please be gentle :slight_smile:

I'm using an Arduino for a camera slide project, needing a lot of text strings for the LCD menu system, so have opted to store these strings in an external eeprom.

Each string (max chars 20) is stored at the begiing of a page boundary, wastefull but should simplify the code as I won't need to worry about splitting strings across a boundary etc.

I can store the stings with now issue, I can also retrieve them BUT when I try to Serial.println(string) I loose the first byte.

I've spent all afternoon going around in circles!
I know I'm doing something stupid (as usual) but am in need of some pointers (please excuse the pun)....

Method 3 fails every time...So here we go, here's my code:

#include <Wire.h>

byte deviceaddress = 0x50;
const int numberOfTextLines = 4;
const int maxCharsPerLine = 20;
unsigned char dataFromEeprom[maxCharsPerLine];
char lcdTextBuffer;
bool flag=false;

// Start with a small array & see if I can manipulate this!

char lcdTextData[numberOfTextLines][maxCharsPerLine]={
    "Select Mode",            // 0  eeprom write byte location 0
    "Simple Time Lapse",      // 1  eeprom write byte location 64
    "Advanced Time Lapse",    // 2  eeprom write byte location 128
    "Day-Time Videos"         // 3  eeprom write byte location 192 etc.
    };



void setup() {
  // put your setup code here, to run once:
  Wire.begin();
  Serial.begin(9600);
}

void writeEEPROM(int deviceaddress, unsigned int eeaddress, char* data) 
{
  // Write a string of chars to eeprom
  // Only works upto page boundary
  // This is OK here as I'm only storing strings of max length 20 chars  
  unsigned char i=0;
  
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)((eeaddress) >> 8));   // MSB
  Wire.write((int)((eeaddress) & 0xFF)); // LSB

  do{ 
     Wire.write((byte) data[i]);
     i++;
  } while(data[i]);  
  Wire.endTransmission();
     
  delay(6);  // needs 5ms for page write
}

void readEEPROM(int deviceaddress, unsigned int eeaddress,  
                 unsigned char* data, unsigned int num_chars) 
{
  unsigned char i=0;
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
 
  Wire.requestFrom(deviceaddress,num_chars);
 
  while(Wire.available()) data[i++] = Wire.read();

}

void loop() {
  // put your main code here, to run repeatedly:
   
    if(flag==false){
      
      int eeaddress = 0;
      int numCharsToRead = 20; // this will need changing later for lookup table
     
     for(int i=0; i<numberOfTextLines;i++){
          char *tempStringBuffer = lcdTextData[i];
          
          writeEEPROM(deviceaddress,eeaddress,tempStringBuffer);
          
          Serial.print("1 : ");             // This works
          Serial.println(tempStringBuffer);
          
          Serial.print("2 : ");
          Serial.println("OK let's see if we can read this back");
          
          readEEPROM(deviceaddress,eeaddress,dataFromEeprom,numCharsToRead);
          *tempStringBuffer = (dataFromEeprom,numCharsToRead);

          Serial.print("3 : ");               // This does NOT work always looses the first byte?
          Serial.println(tempStringBuffer);
          // eventually I want to display this on an LCD
          
          Serial.print("4 : ");
          Serial.println("Actual string stored");
          
          Serial.print("5 : ");               // This works
          Serial.write(dataFromEeprom,numCharsToRead);
          Serial.println();
          
          
          Serial.print("6 : ");
          eeaddress+=64;
          Serial.println(eeaddress);
          Serial.println();
          delay(1000);
          }
      flag=true; 
    }   
}

I think you need a

			const uint8_t error = Wire.endTransmission();

after the requestFrom().

You should note that requestFrom() returns the number of bytes fetched which may not be he same as the number asked for. Also, you should read the bytes using something along the lines of

			for (uint16_t i = 0;
					(i < actualRead); i++)
			{
				*data++ = Wire.read();
                        }

Hi

Thanks for the reply...

I've changed the code as you suggetsed as below, but still having the same issue?

void readEEPROM(int deviceaddress, unsigned int eeaddress,  
                 unsigned char* data, unsigned int num_chars) 
{
  unsigned char i=0;
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
 
  Wire.requestFrom(deviceaddress,num_chars);

  // added this
  const uint8_t error =  Wire.endTransmission();
 
  //while(Wire.available()) data[i++] = Wire.read();
  // changed to:
  while(Wire.available()){
    for (uint16_t i =0; (i < num_chars); i++)
    { 
      *data++ = Wire.read();
    }
  }
}

You don't need Wire.available() as in

  //while(Wire.available()) data[i++] = Wire.read();
  // changed to:
  while(Wire.available()){

You just need to read the values since they have already been received and you only read the number from the return value of the Wire.requestFrom() call.

      int numCharsToRead = 20; // this will need changing later for lookup table
...
          char *tempStringBuffer = lcdTextData[i];
...
          *tempStringBuffer = (dataFromEeprom,numCharsToRead);

What are you thinking this does?

Hi Arduarn

Thanks for pointing out my stupidity! I knew I was doing something wrong....

Code now modified as below & all OK...

#include <Wire.h>

byte deviceaddress = 0x50;
const int numberOfTextLines = 4;
const int maxCharsPerLine = 20;
unsigned char dataFromEeprom[maxCharsPerLine];
char lcdTextBuffer;
bool flag=false;

// Start with a small array & see if I can manipulate this!

char lcdTextData[numberOfTextLines][maxCharsPerLine]={
    "Select Mode",            // 0  eeprom write byte location 0
    "Simple Time Lapse",      // 1  eeprom write byte location 64
    "Advanced Time Lapse",    // 2  eeprom write byte location 128
    "Day-Time Videos"         // 3  eeprom write byte location 192 etc.
    };

int numCharsToRead [4] = {    // Number of charcters for each line
  11,
  17,
  19,
  15
};


void setup() {
  // put your setup code here, to run once:
  Wire.begin();
  Serial.begin(9600);
}

void writeEEPROM(int deviceaddress, unsigned int eeaddress, char* data)
{
  // Write a string of chars to eeprom
  // Only works upto page boundary
  // This is OK here as I'm only storing strings of max length 20 chars 
  unsigned char i=0;
 
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)((eeaddress) >> 8));   // MSB
  Wire.write((int)((eeaddress) & 0xFF)); // LSB

  do{
     Wire.write((byte) data[i]);
     i++;
  } while(data[i]); 
  Wire.endTransmission();
     
  delay(6);  // needs 5ms for page write
}

void readEEPROM(int deviceaddress, unsigned int eeaddress, 
                 unsigned char* data, unsigned int num_chars)
{
  unsigned char i=0;
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
 
  Wire.requestFrom(deviceaddress,num_chars);
  const uint8_t error =  Wire.endTransmission();
  for (uint16_t i =0; (i < num_chars); i++)
    { 
      *data++ = Wire.read();
    }

}

void loop() {
   
    if(flag==false){
     
      int eeaddress = 0;
     
     for(int i=0; i<numberOfTextLines;i++){
          char *tempStringBuffer = lcdTextData[i];

          // Write data to eeprom
          writeEEPROM(deviceaddress,eeaddress,tempStringBuffer);
          
          // now to read the data back
          readEEPROM(deviceaddress,eeaddress,dataFromEeprom,numCharsToRead[i]);

         // now print the data out
          for(int j=0;j<numCharsToRead[i];j++){
            Serial.print((char)dataFromEeprom[j]);
          }
          Serial.println();
         
          eeaddress+=64;
          }
      flag=true;
    }  
}