I2C Register

Hi

I am programming a I2C to read ADC input but I am having some problems accessing the internal registers in sequence. Can anyone offer some insights?

Thank you.

ADC: LTC2497 Datasheet and Product Info | Analog Devices

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

#define ADCAddr 0x14         //Address of I2C
#define ADCChan 0xB0         //Channel of IC

int data, data2;


void setup() {
  Wire.begin();

  //Start I2C Communication
  Wire.beginTransmission(ADCAddr);
  Wire.write(1);
  Wire.endTransmission(true);
   
  Serial.begin(9600);
  Serial.println("Welcome to BMS");
} 


void loop() {
  Wire.beginTransmission(ADCAddr);
  Wire.write(ADCChan);
  
  Wire.requestFrom(ADCAddr, 3);      //Request data from the I2C Address and # of byte, max 3

  while(Wire.available()) {
    data = Wire.read();              //Request data from the IC 
    data2 = Wire.read();             //Subsequent internal register address
    Serial.println(data);
    Serial.println(data2);
  }
}

Please post a link to the datasheet for the ADC device from which you are trying to read.

...R

Hi Robin2

Apologies…here is the link…
https://www.analog.com/en/products/ltc2497.html

I have had a quick look at the LTC2497 datasheet. I was hoping it might have some code examples, but it doesn't.

I am having some problems accessing the internal registers in sequence

Can you explain further what you are trying to do, what results you are getting and what you want to happen that is different?

That may help to focus on a particular part of the datasheet, but I won't be surprised if I can't help.

...R

Have you been to the Analog Devices website and looked at the page for the LTC2497. The web page is here.

Part way down the page there is a section called "Tools and Simulation" where it talks about their Arduino clone board called Linduino. Just below that, there is a section called "Code Files". There is an example there called "LTC2497 - DC1012AB Linduino.INO" which you can download.

It's obviously targeted at their Linduino board but that uses a ATMega328 processor. The code may give you an insight into how to get your chip working. You may even be able to run their application directly on your Arduino board.

markd833:
Part way down the page there is a section called "Tools and Simulation" where it talks about their Arduino clone board called Linduino.

Interesting. I saw the word "Linduino" but it never occurred to me that it had anything to do with an Arduino so I just skated past it.

...R

Robin2:
I have had a quick look at the LTC2497 datasheet. I was hoping it might have some code examples, but it doesn't.

Can you explain further what you are trying to do, what results you are getting and what you want to happen that is different?

That may help to focus on a particular part of the datasheet, but I won't be surprised if I can't help.

...R

I am building a ADC converter. The ADC contains 16 channels which translates into 16 different registers. I needed to read the different registers in sequence to extract the data into arduino for processing.

So far I only managed to read single register and the problem comes when I try to read the second register. It seems, arduino is not requesting for data from the second register / I am unable to send the second register address to arduino for it to request data from the ADC. It will only return the value of the first register.

markd833:
Have you been to the Analog Devices website and looked at the page for the LTC2497. The web page is here.

Part way down the page there is a section called “Tools and Simulation” where it talks about their Arduino clone board called Linduino. Just below that, there is a section called “Code Files”. There is an example there called “LTC2497 - DC1012AB Linduino.INO” which you can download.

It’s obviously targeted at their Linduino board but that uses a ATMega328 processor. The code may give you an insight into how to get your chip working. You may even be able to run their application directly on your Arduino board.

markd833:
Have you been to the Analog Devices website and looked at the page for the LTC2497. The web page is here.

Part way down the page there is a section called “Tools and Simulation” where it talks about their Arduino clone board called Linduino. Just below that, there is a section called “Code Files”. There is an example there called “LTC2497 - DC1012AB Linduino.INO” which you can download.

It’s obviously targeted at their Linduino board but that uses a ATMega328 processor. The code may give you an insight into how to get your chip working. You may even be able to run their application directly on your Arduino board.

Hi markd833

You are right…I went to check their linduino code and verified the sequence with their applications engineer, they do require to “update” the new register address before it will read from it. Here is my question, I tried to “update” the register address after every cycle of conversion but it does not work. Did I missed any thing in the increment?

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

#define ADCAddr 0x14         //Address of I2C
byte ADCChan = 0xB0;         //Channel of IC

int data;


void setup() {
  Wire.begin();

  //Start I2C Communication
  Wire.beginTransmission(ADCAddr);
  Wire.write(1);
  Wire.endTransmission(true);
   
  Serial.begin(9600);
  Serial.println("Welcome to BMS");
} 


void loop() {
  Wire.beginTransmission(ADCAddr);
  Wire.write(ADCChan);
  
  Wire.requestFrom(ADCAddr, 3);      //Request data from the I2C Address and # of byte, max 3

  while(Wire.available()) {
    data = Wire.read();              //Request data from the IC 
    Serial.println(data);
  }
  ADCChan += 1;                       //Increment ADC register address
}

In your main loop, I don't see a wire.endTransmission() call.

It looks like your device doesn't auto increment the ADC channel after a read, which probably makes sense. I think what the App Eng was saying is that you need to explicitly tell the ADC which channel to start a conversion on. From a quick look at the data sheet it looks like you can perform continuous reads of the same ADC channel without re-writing the address.

Edit: I forgot to add, that I think figure 6 in the datasheet is the sequence you need to create in order to start a conversion and read the result.

markd833:
In your main loop, I don't see a wire.endTransmission() call.

It looks like your device doesn't auto increment the ADC channel after a read, which probably makes sense. I think what the App Eng was saying is that you need to explicitly tell the ADC which channel to start a conversion on. From a quick look at the data sheet it looks like you can perform continuous reads of the same ADC channel without re-writing the address.

Edit: I forgot to add, that I think figure 6 in the datasheet is the sequence you need to create in order to start a conversion and read the result.

markd833:
In your main loop, I don't see a wire.endTransmission() call.

It looks like your device doesn't auto increment the ADC channel after a read, which probably makes sense. I think what the App Eng was saying is that you need to explicitly tell the ADC which channel to start a conversion on. From a quick look at the data sheet it looks like you can perform continuous reads of the same ADC channel without re-writing the address.

Edit: I forgot to add, that I think figure 6 in the datasheet is the sequence you need to create in order to start a conversion and read the result.

Hi markd833

Yup, it is able to perform the conversion continuously now. I tried to update the "register" and it works on my serial monitor. I am only unable to get the ADC to ACK the "updated" register.

Do you happen to see any error in my code?

Thank you.

Ok, this is a complete guess as I don’t have an LTC2497 to test it on but maybe something like this will work:

#include <Wire.h>

#define ADCAddr 0x14         // I2C Address of LTC2497

// codes for single ended ADC channels 0,1,2 & 3
uint8_t adcChannel[4] = { B10110000, B10111000, B10110001, B10111001 };

// codes for differential ADC channels 0,1,2 & 3
//uint8_t adcChannel[4] = { B10100000, B10100001, B10100010, B10100011 };

void setup()
{
  Wire.begin();
  Serial.begin(9600);
}

void loop()
{
  for (adcChan = 0; adcChan < 4; adcChan++)
  {
    Serial.print( adcChann );
    Serial.print( ":" );

    // start a conversion on channel "adcChan"
    Wire.beginTransmission(ADCAddr);
    Wire.write(adcChannel[adcChan]);
    Wire.endTransmission();

    // slight delay for the conversion to complete
    // you might need to tweak the delay
    delay(10);

    // request 3 bytes from the ADC
    Wire.requestFrom(ADCAddr, 3);
    while (Wire.available()) {
      data = Wire.read();
      Serial.print(data, HEX);
    }
    Serial.println("");
  }
  // wait a second
  delay(1000);
}

Hopefully this will work for you.

markd833:
Ok, this is a complete guess as I don’t have an LTC2497 to test it on but maybe something like this will work:

#include <Wire.h>

#define ADCAddr 0x14        // I2C Address of LTC2497

// codes for single ended ADC channels 0,1,2 & 3
uint8_t adcChannel[4] = { B10110000, B10111000, B10110001, B10111001 };

// codes for differential ADC channels 0,1,2 & 3
//uint8_t adcChannel[4] = { B10100000, B10100001, B10100010, B10100011 };

void setup()
{
  Wire.begin();
  Serial.begin(9600);
}

void loop()
{
  for (adcChan = 0; adcChan < 4; adcChan++)
  {
    Serial.print( adcChann );
    Serial.print( “:” );

// start a conversion on channel “adcChan”
    Wire.beginTransmission(ADCAddr);
    Wire.write(adcChannel[adcChan]);
    Wire.endTransmission();

// slight delay for the conversion to complete
    // you might need to tweak the delay
    delay(10);

// request 3 bytes from the ADC
    Wire.requestFrom(ADCAddr, 3);
    while (Wire.available()) {
      data = Wire.read();
      Serial.print(data, HEX);
    }
    Serial.println("");
  }
  // wait a second
  delay(1000);
}




Hopefully this will work for you.

Hi markd833

Thanks so much for your help…the ADC is still reading back the same register…I guess I have to approach the APP Eng again to debug this…really appreciate all your help! Stay Safe! :slight_smile:

There’s one more thing you can try if you haven’t tried it already.

If you go to the Analog Devices website here, they talk about their Linduino board. Scroll down the page to the section titled “Setup”. Grab the Linduino sketchbook - it’s a zip file.

Once you have downloaded it, click on the link in the first line in the “Setup” section where it says DC2026 Demo Manual. That’s a PDF document that tells you how to install the Linduino sketchbook. If you follow those instructions and then restart your Arduino IDE, then you should be able to go to:

File->Sketchbook->Part Number->2000->2400->2497 and load the DC1012A_B sketch.

I followed the instructions and the sketch compiles for my Arduino UNO board without any errors.

Their Linduino board is basically an Arduino UNO board with a specially configured connector so that they can plug in lots of their demo boards to let users evaluate them.

As long as you wire up your LTC2497 correctly, then the demo code should run. A quick look at the demo code and it looks like it may complain about not being able to read from an EEPROM but seems to continue anyway.

You can only read one channel at a time but then you will have a baseline for talking to their engineer using their code.

markd833:
There's one more thing you can try if you haven't tried it already.

If you go to the Analog Devices website here, they talk about their Linduino board. Scroll down the page to the section titled "Setup". Grab the Linduino sketchbook - it's a zip file.

Once you have downloaded it, click on the link in the first line in the "Setup" section where it says DC2026 Demo Manual. That's a PDF document that tells you how to install the Linduino sketchbook. If you follow those instructions and then restart your Arduino IDE, then you should be able to go to:

File->Sketchbook->Part Number->2000->2400->2497 and load the DC1012A_B sketch.

I followed the instructions and the sketch compiles for my Arduino UNO board without any errors.

Their Linduino board is basically an Arduino UNO board with a specially configured connector so that they can plug in lots of their demo boards to let users evaluate them.

As long as you wire up your LTC2497 correctly, then the demo code should run. A quick look at the demo code and it looks like it may complain about not being able to read from an EEPROM but seems to continue anyway.

You can only read one channel at a time but then you will have a baseline for talking to their engineer using their code.

Hi markd833

I tried your recommendation but I cant seem to compile the file. I edited some of the lines because it is not Arduino compatible but I still have errors because there are some functions I cant find which is needed for compiling, "'LTC2497_read' was not declared in this scope"...did you have such issues?

No, I followed the instructions in the document and it compiled straight away without a single error. I tried it with a standard Arduino UNO as the board type.

I temporarily altered the location of my sketches as per the document. I wonder if that has anything to do with the errors you are getting.

markd833:
Ok, this is a complete guess as I don’t have an LTC2497 to test it on but maybe something like this will work:

#include <Wire.h>

#define ADCAddr 0x14        // I2C Address of LTC2497

// codes for single ended ADC channels 0,1,2 & 3
uint8_t adcChannel[4] = { B10110000, B10111000, B10110001, B10111001 };

// codes for differential ADC channels 0,1,2 & 3
//uint8_t adcChannel[4] = { B10100000, B10100001, B10100010, B10100011 };

void setup()
{
  Wire.begin();
  Serial.begin(9600);
}

void loop()
{
  for (adcChan = 0; adcChan < 4; adcChan++)
  {
    Serial.print( adcChann );
    Serial.print( “:” );

// start a conversion on channel “adcChan”
    Wire.beginTransmission(ADCAddr);
    Wire.write(adcChannel[adcChan]);
    Wire.endTransmission();

// slight delay for the conversion to complete
    // you might need to tweak the delay
    delay(10);

// request 3 bytes from the ADC
    Wire.requestFrom(ADCAddr, 3);
    while (Wire.available()) {
      data = Wire.read();
      Serial.print(data, HEX);
    }
    Serial.println("");
  }
  // wait a second
  delay(1000);
}




Hopefully this will work for you.

Hi markd833

I managed to resolve the issue…it was very close to the code you posted…Post them here so everyone can learn…

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

#define ADCAddr 0x14         //Address of I2C

uint32_t data;
int dataBits;
int dataBits2;
uint8_t adcChannel[8] = { 0xB0, 0xB8, 0xB1, 0xB9, 
                          0xB2, 0xBA, 0xB3, 0xBB };

void setup() {
  Wire.begin();
  
  Wire.beginTransmission(ADCAddr);
  Wire.write(0);
  Wire.write(adcChannel[0]);
  Wire.endTransmission();

  Serial.begin(9600);
  Serial.println("Welcome to BMS");
} 


void loop() { 
  for (int x = 0; x < 8; x++) {
    delay(170);
    
    Serial.print(adcChannel[x], HEX);
    Serial.println(":");

    Wire.beginTransmission(ADCAddr);
    Wire.write(adcChannel[x]);
    Wire.endTransmission();

    delay(170);

    Wire.requestFrom(ADCAddr, 3);

    while(Wire.available()) {
      data = Wire.read();
      Serial.println(data, BIN);
    }
    Serial.println();
  } 
  // wait a second
  delay(1000);
}

Glad you got it working and thanks for sharing the answer.