Go Down

Topic: I2C EEPROM with I2C Clock Module (Read 2807 times) previous topic - next topic

nncs20

I'm having some trouble using the I2C EEPROM 24LC256 chip. I found some tutorials and some test code and it seems like it is wired correctly and responding with those tests. But now when I use my code (which is based off of when I was just using internal EEPROM), it gets jibberish when I go into the 'review' mode to look at previous readings (the final product is more or less a glucose reader that can store readings along with a time stamp and then eventually transfer over Xbee). Also on the I2C line is a Dallas Semiconductor RTC. The RTC has an address of 0x68 and the EEPROM has an address of 0x50 since I have all the analog pins wired to ground. Any ideas of what is going wrong in my code? Am I separating my int's into bytes correctly?

Thanks!


Code: [Select]
#include <LiquidCrystal.h>
#include <Wire.h>
#include <EEPROM.h>
#include <XBee.h>
#define DS1307_I2C_ADDRESS 0x68
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 10, 9);

//41

//Global Variables
volatile int curDay = 0;
volatile int curMon = 0;
volatile int curYear = 0;
volatile int curHour = 0;
volatile int curMin = 0;
volatile int curSec = 0;
volatile int curWkday = 0;
volatile float curReading = 0;
volatile float readOne = 0;
volatile float readTwo = 0;
volatile float readThree = 0;
volatile float readFour = 0;
volatile float readFive = 0;
volatile float readSix = 0;
volatile float curVoltage = 0;
volatile int curActVal = 0;
volatile int curState = 1;
volatile int okState = 0;
volatile int dispUpdate = 0;
volatile int eeCount = 0;
volatile int toGet = 1;
uint8_t payload[18] = {"12;34;56;78;9012;111"};

//States
#define GETREADING 1
#define REVIEW 2
//#define CLOCK 3
#define TRANSFER 3
#define CLEAR 4
#define TOTALSTATES 4
#define EEPROMADDR 0x50


//Pin assignments
volatile int advButtonPin = 2;
volatile int okButtonPin = 3;
volatile int sensorPin = 3; //this is analog
//volatile int triggerPin = 3; //this is analog

XBee xbee = XBee();

void setup(){
  //clear EEPROM
 
  pinMode(advButtonPin, INPUT);
  pinMode(okButtonPin, INPUT);
  pinMode(A3, INPUT);
 
  analogReference(DEFAULT);
  attachInterrupt(1, advanceAction, FALLING);
  attachInterrupt(0, okAction, FALLING);
 
  Wire.begin();
  Serial.begin(9600);
  lcd.begin(16,2);
  lcd.print("Glucose Reader");
  delay(2000);
  lcd.clear();
  lcd.print("Select a");
  lcd.setCursor(0,1);
  lcd.print("Function");
 
  eeCount = EEPROMReadInt(0);
 
}

void loop(){
  if(dispUpdate){
    lcd.clear();
   
    if(curState == GETREADING){
      lcd.print("Take Reading.");
      lcd.setCursor(0,1);
      lcd.print("Press OK Button");
    }else if(curState == REVIEW){
      lcd.print("Review Readings.");
      lcd.setCursor(0,1);
      lcd.print("Press OK Button");
    //}else if(curState == CLOCK){
      //getDateDs1307();
      //displayReadings();
    }else if(curState == TRANSFER){
      lcd.print("Transfer Readings.");
      lcd.setCursor(0,1);
      lcd.print("Press OK Button");
    }else if(curState == CLEAR){
      lcd.print("Clear Memory");
      lcd.setCursor(0,1);
      lcd.print("Press OK Button");
    }
    dispUpdate = 0;
  }
  if(okState == 1 && curState == REVIEW){
    reviewReadings();
    okState = 0;
  }
  if(okState == 1 && curState == GETREADING){
    doReading();
    okState = 0;
  }
  if(okState == 1 && curState == TRANSFER){
    transmitData();
    okState = 0;
  }
  if(okState == 1 && curState == CLEAR){
    clearReadings();
    okState = 0;
  }
}

void advanceAction(){
  curState++;
  if(curState > TOTALSTATES){
    curState = 1;
  }
  dispUpdate = 1;
}

void okAction(){
  okState = 1;
}

void doReading(){
  lcd.clear();
  lcd.print("Waiting...");
  lcd.setCursor(0,1);
  //lcd.print(analogRead(A3), DEC);
  //delay(1000);
  while(analogRead(A3) < 20);
  lcd.clear();
  lcd.print("Taking Reading...");
  delay(4999);
  readOne = analogRead(A3);
  readTwo = analogRead(A3);
  readThree = analogRead(A3);
  readFour = analogRead(A3);
  readFive = analogRead(A3);
  readSix = analogRead(A3);
  curReading = (readOne+readTwo+readThree+readFour+readFive+readSix)/6;
  curVoltage = (curReading/1025)*5;
  curActVal = (int)((curVoltage/0.009)-32.75);
  lcd.clear();
  //lcd.print("Reading: ");
  //lcd.print(curReading, DEC);
  //lcd.setCursor(0,1);
  lcd.print("Glucose: ");
  lcd.print(curActVal, DEC);
  getDateDs1307();
  writeEeprom();
}

void clearReadings(){
  for(int i=0; i<2048; i++){
    writeEEPROM(i,0);
  }
  eeCount = 0;
  lcd.clear();
  lcd.print("Readings Cleared!");
}

void transmitData(){
  lcd.clear();
  lcd.print("Transferring");
  lcd.setCursor(0,1);
  lcd.print("Readings...");

  xbee.begin(9600);
  for(int i=1; i<=eeCount; i++){
    toGet = i;
    readEeprom();
    payload[0] = highByte(curActVal);
    payload[1] = lowByte(curActVal);
    payload[2] = ';';
    payload[3] = highByte(curMon);
    payload[4] = lowByte(curMon);
    payload[5] = ';';
    payload[6] = highByte(curDay);
    payload[7] = lowByte(curDay);
    payload[8] = ';';
    payload[9] = highByte(curYear);
    payload[10] = lowByte(curYear);
    payload[11] = ';';
    payload[12] = highByte(curHour);
    payload[13] = lowByte(curHour);
    payload[14] = ';';
    payload[15] = highByte(curMin);
    payload[16] = lowByte(curMin);
    payload[17] = '$';
    Tx16Request zbTx = Tx16Request(0x1234, payload, sizeof(payload));
    xbee.send(zbTx);
  }
  delay(2000);
  lcd.clear();
  lcd.print("Data Transmitted");
}

void writeEeprom(){
  eeCount++;
  int curSpot = ((eeCount-1)*12)+2;
  EEPROMWriteInt(curSpot, curMon);
  curSpot = curSpot+2;
  EEPROMWriteInt(curSpot, curDay);
  curSpot = curSpot+2;
  EEPROMWriteInt(curSpot, curYear);
  curSpot = curSpot+2;
  EEPROMWriteInt(curSpot, curHour);
  curSpot = curSpot+2;
  EEPROMWriteInt(curSpot, curMin);
  curSpot = curSpot+2;
  EEPROMWriteInt(curSpot, curActVal);
  EEPROMWriteInt(0, eeCount);
}

void reviewReadings(){
  if(toGet<=eeCount){
    readEeprom();
    displayReadings();
    toGet++;
  }else{
    lcd.clear();
    lcd.print("No readings!");
    toGet = 1;
  }
}

void readEeprom(){
  int curSpot = ((toGet-1)*12)+2;
  curMon = EEPROMReadInt(curSpot);
  curSpot = curSpot+2;
  curDay = EEPROMReadInt(curSpot);
  curSpot = curSpot+2;
  curYear = EEPROMReadInt(curSpot);
  curSpot = curSpot+2;
  curHour = EEPROMReadInt(curSpot);
  curSpot = curSpot+2;
  curMin = EEPROMReadInt(curSpot);
  curSpot = curSpot+2;
  curActVal = EEPROMReadInt(curSpot);
 
}

//This function will write a 2 byte integer to the eeprom at the specified address and address + 1
void EEPROMWriteInt(int p_address, int p_value)
{
byte theLowByte = ((p_value >> 0) & 0xFF);
byte theHighByte = ((p_value >> 8) & 0xFF);

writeEEPROM(p_address, theLowByte);
writeEEPROM(p_address + 1, theHighByte);
}

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
int EEPROMReadInt(int p_address)
{
byte theLowByte = readEEPROM(p_address);
byte theHighByte = readEEPROM(p_address + 1);

return ((theLowByte << 0) & 0xFF) + ((theHighByte << 8) & 0xFF00);
}

void writeEEPROM(int eeaddress, byte data ) {
  //Wire.begin(EEPROMADDR);
  Wire.beginTransmission(EEPROMADDR);
  Wire.send((int)(eeaddress >> 8));   // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.send(data);
  Wire.endTransmission();
}

byte readEEPROM(unsigned int eeaddress ) {
  ///Wire.begin(EEPROMADDR);
  byte rdata = 0xFF;
  Wire.beginTransmission(EEPROMADDR);
  Wire.send((int)(eeaddress >> 8));   // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(EEPROMADDR,1);
  if (Wire.available()) rdata = Wire.receive();
  return rdata;
}

void displayReadings(){
    lcd.clear(); // clear LCD screen
    lcd.setCursor(0,0);
    lcd.print(curHour, DEC);
    lcd.print(":");
    if (curMin<10){
      lcd.print("0");
    }
    lcd.print(curMin, DEC);
    lcd.print(" R:");
    lcd.print(curActVal, DEC);

    lcd.setCursor(0,1);
    lcd.print(curMon, DEC);
    lcd.print("/");
    lcd.print(curDay, DEC);
    lcd.print("/20");
    lcd.print(curYear, DEC);
}

int decToBcd(int val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
int bcdToDec(int val)
{
  return ( (val/16*10) + (val%16) );
}
// Gets the date and time from the ds1307
void getDateDs1307(){
  // Reset the register pointer
  //Wire.begin(DS1307_I2C_ADDRESS);
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
  // A few of these need masks because certain bits are control bits
  curSec = bcdToDec(Wire.receive() & 0x7f);
  curMin = bcdToDec(Wire.receive());
  curHour = bcdToDec(Wire.receive() & 0x3f); // Need to change this if 12 hour am/pm
  curWkday = bcdToDec(Wire.receive());
  curDay = bcdToDec(Wire.receive());
  curMon = bcdToDec(Wire.receive());
  curYear = bcdToDec(Wire.receive());
}


liuzengqiang

All analog pin to ground or all EEPROM address pin to ground?

Plus, I don't think you had any delay between sequential write in your writeEEPROMinteger. The spec sheet may require up to 4ms delay between sequential write requests. you can get around it by doing bulk write, like organizing all data, time stamp and readings, then do a bulk write, just keep writing (within 64byte boundary) until you're done.

I suspect all you got was FF on MSB and current value on MSB if you read back, right?
Serial LCD keypad panel,phi_prompt user interface library,SDI-12 USB Adapter

nncs20

Thanks for the input. I added a 4ms delay between writes but I still seem to be having trouble. It seems like the first integer I write to keep track of quantity of records in the EEPROM is right but the data isn't reading correctly. Also, I did meanthat all the EEPROM address pins are hooked to ground currently. What if I used something like the following functions with the same data format  create in transmitData()?

Code: [Select]
void i2c_eeprom_write_page(unsigned int eeaddresspage, byte* data, byte length ) {
  Wire.beginTransmission(EEPROMADDR);
  Wire.send((int)(eeaddresspage >> 8)); // MSB
  Wire.send((int)(eeaddresspage & 0xFF)); // LSB
  byte c;
  for ( c = 0; c < length; c++)
    Wire.send(data[c]);
  Wire.endTransmission();
}

void i2c_eeprom_read_buffer(unsigned int eeaddress, byte *buffer, int length ) {
  Wire.beginTransmission(EEPROMADDR);
  Wire.send((int)(eeaddress >> 8)); // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,length);
  int c = 0;
  for ( c = 0; c < length; c++ )
    if (Wire.available()) buffer[c] = Wire.receive();
}

robtillaart

Wrote a lib a while ago for 24LC256 - http://arduino.cc/playground/Main/LibraryForI2CEEPROM - It can write blocks over 64byte boundaries

Might help,
rob
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

nickgammon

I wrote to and read from that chip here:

http://www.gammon.com.au/forum/?id=10896

My code looks fairly similar to yours. However I added a "read check" after the write, which kept polling the device (as the spec suggests) until it indicates it has finished writing, by not ignoring you.

Maybe try my sketch just to confirm you get back a response. Then check the differences between yours and mine.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

nickgammon

Also, you are writing in multiples of 12 bytes. This doesn't divide equally into the page size of 64, so from time to time it will wrap and corrupt data earlier in the page. It would probably be safer to write in multiples of 16. Of course, bearing in mind your use of the first 2 bytes for the counter. So maybe start on the second page. Or have more sophisticated memory address management.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

nncs20

Got it working! Thanks all for the help! Turns out like Nick said, was having problems with page sizes so I changed everything to be in address groups of 16 bytes and also used Rob's library which works great so thanks for that as well!

Kyle

floresta

How about posting your working code?

Don

nncs20

Sure here are the main parts I changed, and this is all code using Rob's library now.
Code: [Select]

void clearReadings(){
  ee.writeBlock(0,0,500);
  eeCount = 0;
  lcd.clear();
  lcd.print("Readings Cleared!");
}

void writeEeBlock(){
    eeCount++;
    int curSpot = ((eeCount)*16);
    eePayload[0] = highByte(curActVal);
    eePayload[1] = lowByte(curActVal);
    eePayload[2] = highByte(curMon);
    eePayload[3] = lowByte(curMon);
    eePayload[4] = highByte(curDay);
    eePayload[5] = lowByte(curDay);
    eePayload[6] = highByte(curYear);
    eePayload[7] = lowByte(curYear);
    eePayload[8] = highByte(curHour);
    eePayload[9] = lowByte(curHour);
    eePayload[10] = highByte(curMin);
    eePayload[11] = lowByte(curMin);
    ee.writeBlock(curSpot, (uint8_t*)&eePayload, 12);
    ee.writeBlock(0,(uint8_t*)&eeCount,1);
}

//void writeEeprom(){
//  eeCount++;
//  int curSpot = ((eeCount-1)*12)+2;
// EEPROMWriteInt(curSpot, curMon);
//  curSpot = curSpot+2;
//  EEPROMWriteInt(curSpot, curDay);
//  curSpot = curSpot+2;
//  EEPROMWriteInt(curSpot, curYear);
//  curSpot = curSpot+2;
//  EEPROMWriteInt(curSpot, curHour);
//  curSpot = curSpot+2;
//  EEPROMWriteInt(curSpot, curMin);
//  curSpot = curSpot+2;
//  EEPROMWriteInt(curSpot, curActVal);
//  EEPROMWriteInt(0, eeCount);
//}

void reviewReadings(){
  if(toGet<=eeCount){
    readEeprom();
    displayReadings();
    toGet++;
  }else{
    lcd.clear();
    lcd.print("No readings!");
    toGet = 1;
  }
}

void readEeprom(){
  int curSpot = ((toGet)*16);
  ee.readBlock(curSpot, (uint8_t*)&eePayload, 12);
  curActVal = (eePayload[0]<<8)+eePayload[1];
  curMon = (eePayload[2]<<8)+eePayload[3];
  curDay = (eePayload[4]<<8)+eePayload[5];
  curYear = (eePayload[6]<<8)+eePayload[7];
  curHour = (eePayload[8]<<8)+eePayload[9];
  curMin = (eePayload[10]<<8)+eePayload[11];
//  curMon = ee.readByte(curSpot);
//  curSpot = curSpot+2;
//  curDay = ee.readByte(curSpot);
//  curSpot = curSpot+2;
//  curYear = ee.readByte(curSpot);
//  curSpot = curSpot+2;
//  curHour = ee.readByte(curSpot);
//  curSpot = curSpot+2;
//  curMin = ee.readByte(curSpot);
//  curSpot = curSpot+2;
//  curActVal = ee.readByte(curSpot);
 
}

//This function will write a 2 byte integer to the eeprom at the specified address and address + 1
//void EEPROMWriteInt(int p_address, int p_value)
// {
// byte theLowByte = ((p_value >> 0) & 0xFF);
// byte theHighByte = ((p_value >> 8) & 0xFF);

// writeEEPROM(p_address, theLowByte);
// writeEEPROM(p_address + 1, theHighByte);
//}

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
int EEPROMReadInt(int p_address)
{
byte theLowByte = ee.readByte(p_address);
byte theHighByte = ee.readByte(p_address + 1);

return ((theLowByte << 0) & 0xFF) + ((theHighByte << 8) & 0xFF00);
}


Go Up