From EEPROM to SD and back to EEPROM

I developed the following functions to copy the contents of a serial EEPROM to the SD card and then back to the EEPEOM as a means to backup EEPROM data or copy an EEPROM.

void readFromEeprom()
{
  byte readVal = 0;

 myFile = SD.open("EEPROM.txt", FILE_WRITE);

  if(myFile)
  {
    SerialUSB.println(F("successfully opened EEPROM.txt"));    
  }
  else
  {
    SerialUSB.println(F("error opening EEPROM.txt"));
    return;
  } 

  
  for(unsigned long i=0; i<MEM_SIZE; i++)
  {
    // Read from EEPROM at the current address
    readVal = readAddress(i);

    // For debugging/info only
    if((i % KB_VAL == 0) && (i > 1))
    {
      unsigned long total = (unsigned long) (i / KB_VAL);
      SerialUSB.print(F("Wrote "));
      SerialUSB.print(total);
      SerialUSB.println(F(" Kb"));
    }

    // Write the value to the SD Card
    myFile.write(readVal);
  }
  myFile.close();
}

and

void readFromSD(){
  
  uint16_t i = 0;
  uint8_t byteData;
  File dataFile = SD.open("EEPROM.txt");
 
if(dataFile) {
    SerialUSB.println(F("successfully opened EEPROM.txt"));  }
  else
  {
    SerialUSB.println(F("error opening EEPROM.txt"));
    return ;
  } 

 
  while (i<MEM_SIZE && dataFile.available()){
   
       byteData=dataFile.read();
       writeEEPROM(EEPROM_I2C_ADDRESS,i,byteData);
       i++;
         
    // For debugging/info only
    if((i % KB_VAL == 0) && (i > 1))
    {
      unsigned long total = (unsigned long) (i / KB_VAL);
      SerialUSB.print(F("Wrote "));
      SerialUSB.print(total);
      SerialUSB.println(F(" Kb"));
    }
  }
  dataFile.close();
  }

However when the data copied appear to be corrupt although they appear at the correct position. See example below

Main BR ENTRANCE    ---->   Main eRrEoT AnCrne

Main BR entry spots    ---->  Main bRdeotmyssooss

Can anyone help spot the problem in the code?

You need to post the entire sketch. Who knows what readAddress() does exactly? Who knows what writeEEPROM() does exactly?

You are right!

include "Wire.h"
#include <SPI.h>
#include <SD.h>

#define EEPROM_I2C_ADDRESS 0x50
#define MAX_BYTE_VAL 255
#define MAX_BYTE_BLOCK 128
#define KB_VAL 1024

const unsigned long MEM_SIZE = 32768;//4096;

File myFile;

void setup() 
{
  Wire.begin();
  SerialUSB.begin(9600);
  while(!SerialUSB) {}

if (initSd()==false) { while(true){} }
  
// Read from EEPROM and write to SD card
 
//  readFromEeprom();   // Read from  EEPROM and write to SD
readFromSD();       // Read from SD and write to EEPROM
//verifyEEPROMWithFIlereadFromSD();  // verify agains file
  
  delay(2000);
  SerialUSB.println(F("Done"));
}

void loop() 
{

}

void readFromEeprom()
{
  byte readVal = 0;

 myFile = SD.open("EEPROM.txt", FILE_WRITE);

  if(myFile)
  {
    SerialUSB.println(F("successfully opened EEPROM.txt"));    
  }
  else
  {
    SerialUSB.println(F("error opening EEPROM.txt"));
    return;
  } 

  
  for(unsigned long i=0; i<MEM_SIZE; i++)
  {
    // Read from EEPROM at the current address
    readVal = readAddress(i);

    // For debugging/info only
    if((i % KB_VAL == 0) && (i > 1))
    {
      unsigned long total = (unsigned long) (i / KB_VAL);
      SerialUSB.print(F("Wrote "));
      SerialUSB.print(total);
      SerialUSB.println(F(" Kb"));
    }

    // Write the value to the SDE Card
    myFile.write(readVal);
  }
  myFile.close();
}

void verifyEEPROMWithFIlereadFromSD(){
  
  uint16_t i = 0;
  uint16_t fails=0;
  uint8_t byteData;
  File dataFile = SD.open("EEPROM.txt");
 
if(dataFile) {
    SerialUSB.println(F("successfully opened EEPROM.txt"));  }
  else
  {
    SerialUSB.println(F("error opening EEPROM.txt"));
    return ;
  } 

 
  while (i<MEM_SIZE && dataFile.available()){
   
       byteData=dataFile.read();
      if (byteData != readAddress(i))   {SerialUSB.print("Failed at addr #");SerialUSB.println(i); fails++;}
       else {SerialUSB.print("PASS addr #");SerialUSB.println(i);}
       
       i++;
         
    // For debugging/info only
    if((i % KB_VAL == 0) && (i > 1))
    {
      unsigned long total = (unsigned long) (i / KB_VAL);
      SerialUSB.print(F("Checked "));
      SerialUSB.print(total);
      SerialUSB.println(F(" Kb"));
    }
  }
  dataFile.close();

  if (fails) {SerialUSB.print("Failures: ");SerialUSB.println(fails); }
   else {SerialUSB.println("Success!"); }
  }







void readFromSD(){
  
  uint16_t i = 0;
  uint8_t byteData;
  File dataFile = SD.open("EEPROM.txt");
 
if(dataFile) {
    SerialUSB.println(F("successfully opened EEPROM.txt"));  }
  else
  {
    SerialUSB.println(F("error opening EEPROM.txt"));
    return ;
  } 

 
  while (i<MEM_SIZE && dataFile.available()){
   
       byteData=dataFile.read();
       writeEEPROM(EEPROM_I2C_ADDRESS,i,byteData);
       i++;
         
    // For debugging/info only
    if((i % KB_VAL == 0) && (i > 1))
    {
      unsigned long total = (unsigned long) (i / KB_VAL);
      SerialUSB.print(F("Wrote "));
      SerialUSB.print(total);
      SerialUSB.println(F(" Kb"));
    }
  }
  dataFile.close();
  }






uint8_t readAddress( uint16_t address)
{
  uint8_t rData = 0xFF;
  
  Wire.beginTransmission(EEPROM_I2C_ADDRESS);
  
  Wire.write((uint16_t)(address >> 8));   // MSB
  Wire.write((uint16_t)(address & 0xFF)); // LSB
  Wire.endTransmission();  

  Wire.requestFrom(EEPROM_I2C_ADDRESS, 1);  

  rData =  Wire.read();

  return rData;
}


void writeEEPROM(uint16_t deviceaddress, uint16_t eeaddress, uint8_t data ) 
{
  
  
  Wire.beginTransmission(deviceaddress);
  Wire.write((uint16_t)(eeaddress >> 8));   // MSB
  Wire.write((uint16_t)(eeaddress & 0xFF)); // LSB
  Wire.write(data);
  Wire.endTransmission();
 
  delay(2);
}
 



bool initSd()
{
  SerialUSB.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output
  // or the SD library functions will not work.
  pinMode(14, OUTPUT);
  pinMode(9, OUTPUT);

  if (!SD.begin(SPI_HALF_SPEED,14)) 
  {
    SerialUSB.println(F("initialization failed!"));
    return false;
  }
  SerialUSB.println(F("initialization done."));
  return true;
  
}

Other than being horribly inefficient to do it byte by byte, I don't seen any issues other than you are not checking the return value of Wire.endtransmission() which will indicate success/failure.
You can also replace your readAddress() function with a different form of requestFrom()

uint8_t readAddress( uint16_t address)
{
  Wire.requestFrom(EEPROM_I2C_ADDRESS, 1, address, 2);
  return Wire.read();
}

Note: error checking omitted. I would suggest checking the return values of endTransmission() and reqestFrom() just to verify things are working as intended.

What model Arduino are you using? I tried to compile your sketch for an UNO and "SerialUSB" is not defined.

Compiling for Leonardo I get an error because you are passing a uint16_t to Wire.beginTransmission() and the compiler can't figure out if you mean 'uint8_t' or 'int'.

/Users/john/Documents/Arduino/sketch_may19a/sketch_may19a.ino: In function 'void writeEEPROM(uint16_t, uint16_t, uint8_t)':
sketch_may19a:206:39: error: call of overloaded 'beginTransmission(uint16_t&)' is ambiguous
   Wire.beginTransmission(deviceaddress);
                                       ^
In file included from /Users/john/Documents/Arduino/sketch_may19a/sketch_may19a.ino:1:0:
/Users/john/Library/Arduino15/packages/arduino/hardware/avr/1.8.3/libraries/Wire/src/Wire.h:61:10: note: candidate: void TwoWire::beginTransmission(uint8_t)
     void beginTransmission(uint8_t);
          ^~~~~~~~~~~~~~~~~
/Users/john/Library/Arduino15/packages/arduino/hardware/avr/1.8.3/libraries/Wire/src/Wire.h:62:10: note: candidate: void TwoWire::beginTransmission(int)
     void beginTransmission(int);
          ^~~~~~~~~~~~~~~~~
exit status 1
call of overloaded 'beginTransmission(uint16_t&)' is ambiguous

Hi,
I am using arduino zero. For AVR based arduinos you need to replace SerialUSB with Serial.

Is there a mistake here:

Wire.requestFrom(EEPROM_I2C_ADDRESS, 1, address, 2);

There seems to be an extra parameter based on:
Wire.requestFrom(address, quantity, stop)

No, is was supposed to be the version that passes all 5 parameters, but I left off the last one - sorry. You need to use this one to pass a 16 bit memory address

uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop)

Hmm.. still couldnt get it done.

It says
no matching function for call to 'arduino::TwoWire::requestFrom(int, int, uint16_t&, int, int)'

You have to supply the final parameter

Wire.requestFrom(EEPROM_I2C_ADDRESS, 1, address, 2, true);

i see..
will try it!

It still complains about it..

no matching function for call to 'arduino::TwoWire::requestFrom(const uint8_t&, int, uint16_t&, int, bool)'

May be this is a different library that takes all these parameters?

address is of type 'uint16_t' but needs to be cast to uint32_t. Your parameters needs to match up with what the function is expecting. That is how C++ matches function calls to multiple function definitions (aka signatures)

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.