I can't accessing data registers of the AD7151 through I2C

Hey everyone, I am using the AD7151(Data Sheet) to get the capacitance data from a capacitance pressure sensor, But AD7151 just don't working, I can't get response from Serial Monitor.

I'm using 5V arduino nano as my master and my slave is 3V3 device, so Level Shift also include. here are my circuit and code.

#include <Wire.h>

#define AD7150_I2C_ADDRESS 0x48 //AD7150 adress

#define AD7150_REG_STATUS 0x00
#define AD7150_REG_CH1_DATA_HIGH 0x01
#define AD7150_REG_CH1_DATA_LOW 0x02
#define AD7150_REG_CH1_AVERAGE_HIGH 0x05
#define AD7150_REG_CH1_AVERAGE_LOW 0x06
#define AD7150_REG_CH1_SENSITIVITY 0x09
#define AD7150_REG_CH1_TIMEOUT 0x0A
#define AD7150_REG_CH1_SETUP 0x0B
#define AD7150_REG_CONFIGURATION 0x0F
#define AD7150_REG_POWER_DOWN_TIMER 0x10
#define AD7150_REG_CH1_CAPDAC 0x11
#define AD7150_REG_SERIAL_NUMBER_3 0x13
#define AD7150_REG_SERIAL_NUMBER_2 0x14
#define AD7150_REG_SERIAL_NUMBER_1 0x15
#define AD7150_REG_SERIAL_NUMBER_0 0x16
#define AD7150_REG_CHIP_ID 0x17

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

Wire.beginTransmission(AD7150_I2C_ADDRESS);
Wire.write(AD7150_REG_CH1_SETUP); //Move pointer to the register address
Wire.write(203); //Setup features for range bx11001011
Wire.endTransmission();
delay(4);

Wire.beginTransmission(AD7150_I2C_ADDRESS);
Wire.write(AD7150_REG_CONFIGURATION); //Move pointer to the register address
Wire.write(49); //Configuration of the threshold mode bx00110001
Wire.endTransmission();
delay(4);

}

void loop() {
//Get capacitance data

Wire.beginTransmission(AD7150_I2C_ADDRESS); // "Hey, AD7150 @ 0x48! Message for you"
Wire.write(AD7150_REG_CH1_DATA_HIGH); // "move your register pointer to get DATA_HIGH
Wire.endTransmission(); // "Thanks, goodbye..."
Wire.requestFrom(AD7150_I2C_ADDRESS,1); // "Hey AD7150 send me your data with 1 byte"
byte ch1H = Wire.read();

Wire.beginTransmission(AD7150_I2C_ADDRESS); // "Hey, AD7150 @ 0x48! Message for you"
Wire.write(AD7150_REG_CH1_DATA_LOW); // "move your register pointer to get DATA_LOW
Wire.endTransmission(); // "Thanks, goodbye..."
Wire.requestFrom(AD7150_I2C_ADDRESS,1);
byte ch1L = Wire.read();

unsigned int ch1 = ch1H*256 + ch1L; //Concatanates the two bytes into one 16 bit word

float Cap1 = (ch1-12288)*4.0/40944.0; // Converts the digital value into capacitance, formula from datasheet.

//print the data on serial monitor
Serial.print("Ch1=");
Serial.print(ch1, BIN);
Serial.print(" Ch1=");
Serial.print(ch1);
Serial.print(" C1=");
Serial.println(Cap1,2);

delay(700);

}

If you would have posted your codes with code tags (</>), the sketch would appear as follows:

#include <Wire.h>

#define AD7150_I2C_ADDRESS  0x48 //AD7150 adress

#define AD7150_REG_STATUS   0x00
#define AD7150_REG_CH1_DATA_HIGH             0x01
#define AD7150_REG_CH1_DATA_LOW              0x02
#define AD7150_REG_CH1_AVERAGE_HIGH       0x05
#define AD7150_REG_CH1_AVERAGE_LOW        0x06
#define AD7150_REG_CH1_SENSITIVITY            0x09
#define AD7150_REG_CH1_TIMEOUT                 0x0A
#define AD7150_REG_CH1_SETUP                     0x0B
#define AD7150_REG_CONFIGURATION              0x0F
#define AD7150_REG_POWER_DOWN_TIMER      0x10
#define AD7150_REG_CH1_CAPDAC                   0x11
#define AD7150_REG_SERIAL_NUMBER_3          0x13
#define AD7150_REG_SERIAL_NUMBER_2          0x14
#define AD7150_REG_SERIAL_NUMBER_1          0x15
#define AD7150_REG_SERIAL_NUMBER_0          0x16
#define AD7150_REG_CHIP_ID                          0x17

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

  Wire.beginTransmission(AD7150_I2C_ADDRESS);
  Wire.write(AD7150_REG_CH1_SETUP);  //Move pointer to the register address
  Wire.write(203);                                                  //Setup features for range bx11001011
  byte busStatus = Wire.endTransmission();
  if(busStatus !=0)
  {
    Serial.println("I2C Communication problem....!");
    while(1);      //wait for ever
  }
  Serial.println("Slave is present...!");
  delay(4);

  Wire.beginTransmission(AD7150_I2C_ADDRESS);
  Wire.write(AD7150_REG_CONFIGURATION);  //Move pointer to the register address
  Wire.write(49);                                                //Configuration of the threshold mode bx00110001
  Wire.endTransmission();
  delay(4);

}

void loop() 
{
  Wire.beginTransmission(AD7150_I2C_ADDRESS);   // "Hey, AD7150 @ 0x48! Message for you"
  Wire.write(AD7150_REG_CH1_DATA_HIGH);     // "move your register pointer to get DATA_HIGH
  Wire.endTransmission();                                     // "Thanks, goodbye..."
  
  Wire.requestFrom(AD7150_I2C_ADDRESS, 2);   // "Hey AD7150 send me your data with 1 byte"
  byte ch1H = Wire.read();
  byte ch1L = Wire.read();
  int ch1 = (int)ch1H<<8 | (int) ch1L;

 // Wire.beginTransmission(AD7150_I2C_ADDRESS);     // "Hey, AD7150 @ 0x48! Message for you"
 // Wire.write(AD7150_REG_CH1_DATA_LOW);      // "move your register pointer to get DATA_LOW
 // Wire.endTransmission();                                         // "Thanks, goodbye..."
 // Wire.requestFrom(AD7150_I2C_ADDRESS, 1);
//  byte ch1L = Wire.read();

 // unsigned int ch1 = ch1H * 256 + ch1L;   //Concatanates the two bytes into one 16 bit word

  float Cap1 = (ch1 - 12288) * 4.0 / 40944.0; // Converts the digital value into capacitance, formula from datasheet.

  //print the data on serial monitor
  Serial.print("Ch1=");
  Serial.print(ch1, BIN);
  Serial.print(" Ch1=");
  Serial.print(ch1);
  Serial.print(" C1=");
  Serial.println(Cap1, 2);
  
  delay(700);
}

BTW: I have not done any major change in your codes except:
I have added 2/3 lines to see that the NANO has detected the sensor.

Some codes optimization with regards to reading data (CH1_DATA_HIGH and CH1_DATA_LOW).

It work! very grateful, but it doesn't work everytime, sometime it take a very long time to wait it respond, is there anything else need to optimization ?

l00ger:
It work! very grateful, but it doesn't work everytime, sometime it take a very long time to wait it respond, is there anything else need to optimization ?

What Arduino are you using? Are you getting the message 0 for busStatus? Are getting reasonable value for your Ch1H, Ch1L, and C1? What is the response time of your sensor? 700 ms -- tome looks too short?

Q:What Arduino are you using? A:Arduino nano

Q:Are you getting the message 0 for busStatus? A:Yes! but most of the time the Serial Monitor show nothing

Q:Are getting reasonable value for your Ch1H, Ch1L, and C1? A:Yes! at the beginning I using arduino to receive data, it all successful, but when I restart the arduino in second or more run, nothing respond....

Q:What is the response time of your sensor? A:my capacitance pressure sensor response time depending on human touch, and I haven't touch it yet, so it a fix capacitance.

@OP

You may bring the following changes/adjustments in your setup and sketch to see if there happens any improvements.

1. Terminate the I2C Bus to 3.3V by external 2.2k/4.7k pull-up resistors.

2. You should read the sensor value once the conversion is complete. As you have selected the continuous conversion mode, you should continuously poll the RDY/-bit of the Status Register to detect the end of conversion and then read the value of the data registers. RDY/-bit is a part of Status Register; where, the read value of 0x52 of Status Register indicates 'end of conversion'.

3. Please, upload the following revised codes and report the performance of the sketch.

#include <Wire.h>

#define AD7150_I2C_ADDRESS  0x48               //AD7150 adress
#define AD7150_REG_STATUS   0x00
#define AD7150_REG_CH1_DATA_HIGH  0x01
#define AD7150_REG_CH1_DATA_LOW  0x02
#define AD7150_REG_CH1_SETUP  0x0B
#define AD7150_REG_CONFIGURATION  0x0F

byte myArray[] = {49, 0, 0, 0, 203};    //SETUP Reg, x, x, x, CONFIG REg

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

  Wire.beginTransmission(AD7150_I2C_ADDRESS);
  Wire.write(AD7150_REG_CH1_SETUP);          //Move pointer to the SETUP register address
  Wire.write(myArray, sizeof(myArray));           //see global arry declaration
  byte busStatus = Wire.endTransmission();
  if(busStatus !=0)
  {
    Serial.println("I2C Communication problem....!");
    while(1);      //wait for ever
  }
  Serial.println("Slave is present...!");
  delay(4);
}

void loop() 
{
   Wire.beginTransmission(AD7150_I2C_ADDRESS);   // "Hey, AD7150 @ 0x48! Message for you"
   Wire.write(AD7150_REG_STATUS);     //pointing Status Register
   Wire.endTransmission();   

  do
  {          
      Wire.requestFrom(AD7150_I2C_ADDRESS, 3); //if conversion complete, we can read data bytes also
  }
  while(Wire.read() != 0x52);     //at busy--Wire.read() = Status Register 0x53; else Wire.read() = 0x52                           
  int ch1 = (int)Wire.read() <<8 | (int) Wire.read();

  float Cap1 = (ch1 - 12288) * 4.0 / 40944.0; //Converts digital value into capacitance, formula from datasheet.

  //print the data on serial monitor
  Serial.print("Ch1="); Serial.print(ch1, BIN);
  Serial.print(" Ch1="); Serial.print(ch1, DEC);
  Serial.print(" C1="); Serial.println(Cap1, 2);
  
  delay(700);
}

I try your code, but this time it only show "Slave is present...!" , nothing more.

My level shift should have 10k pull-up resistors, according to it design i'm not allow to adding another resistors. here is the circuit of the level shift.

l00ger:
I try your code, but this time it only show "Slave is present...!" , nothing more.

1. You said that the codes of Post#1 had been working intermittently. That means that those codes could not be taken as working codes. In that code you did not include the following loping lines to check the 'end-of-conversion'.

do
  {          
      Wire.requestFrom(AD7150_I2C_ADDRESS, 3); //if conversion complete, we can read data bytes also
  }
  while(Wire.read() != 0x52);     //at busy--Wire.read() = Status Register 0x53; else Wire.read() = 0x52

2. Codes of Post#5 are more formal and accurate (correct also?) than the codes of Post#1, which contains the code lines to check the 'end-of-conversion' before reading data registers. From your Post#6, I draw this logical decision that the MCU can not detect that the sensor has finished conversion. According to data sheet, the Status Register will contain a value of 0x52 at the 'end of conversion' event; as a result, RDY/-bit will assume Logic-low state which will revert to inactive state when user performs read operations on the data registers.

3. Please, check (invitations are also placed to other members of the Forum) my codes of Post#5 against data sheets for any possible logical errors. I am also scrutinizing my codes critically against the data sheets. I have no sensor to test these codes.

4. In the meantime, try the following codes (slightly modified version of the codes of Post#5)

#include <Wire.h>

#define AD7150_I2C_ADDRESS  0x48               //AD7150 adress
#define AD7150_REG_STATUS   0x00
#define AD7150_REG_CH1_DATA_HIGH  0x01
#define AD7150_REG_CH1_DATA_LOW  0x02
#define AD7150_REG_CH1_SETUP  0x0B
#define AD7150_REG_CONFIGURATION  0x0F

byte myArray[] = {49, 0, 0, 0, 203};    //SETUP Reg, x, x, x, CONFIG REg

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

  Wire.beginTransmission(AD7150_I2C_ADDRESS);
  Wire.write(AD7150_REG_CH1_SETUP);          //Move pointer to the SETUP register address
  Wire.write(myArray, sizeof(myArray));           //see global arry declaration
  byte busStatus = Wire.endTransmission();
  if(busStatus !=0)
  {
    Serial.println("I2C Communication problem....!");
    while(1);      //wait for ever
  }
  Serial.println("Slave is present...!");
  delay(4);
}

void loop() 
{
   Wire.beginTransmission(AD7150_I2C_ADDRESS);   // "Hey, AD7150 @ 0x48! Message for you"
   Wire.write(AD7150_REG_STATUS);     //pointing Status Register
   Wire.endTransmission();   

  do
  {          
      Wire.requestFrom(AD7150_I2C_ADDRESS, 1); //if conversion complete, we can read data bytes also
  }
  while(Wire.read() != 0x52);     //at busy--Wire.read() = Status Register 0x53; else Wire.read() = 0x52                           
  
   Wire.beginTransmission(AD7150_I2C_ADDRESS);   // "Hey, AD7150 @ 0x48! Message for you"
   Wire.write(AD7150_REG_CH1_DATA_HIGH);     //pointing DATA_H Register
   Wire.endTransmission();   
  
   Wire.requestFrom(AD7150_I2C_ADDRESS, 2); 

   int ch1 = (int)Wire.read() <<8 | (int) Wire.read();

  float Cap1 = (ch1 - 12288) * 4.0 / 40944.0; //Converts digital value into capacitance, formula from datasheet.

  //print the data on serial monitor
  Serial.print("Ch1="); Serial.print(ch1, BIN);
  Serial.print(" Ch1="); Serial.print(ch1, DEC);
  Serial.print(" C1="); Serial.println(Cap1, 2);
  
  delay(700);
}

5. If the codes of Step-4 are not working, try in 'single conversion' mode of the sensor for which you have to change the content of the relevant register.

BTW: You have already pull-ups with the I2C Bus.

It working!!! 'i'm very appreciate you help me all the way, this time it show the data every time. I replace another AD7151, so probable is the hardware issue. But it only show me two number below,

Slave is present...!
Ch1=101001000000000 Ch1=20992 C1=0.85
Ch1=101001100000000 Ch1=21248 C1=0.88
Ch1=101001000000000 Ch1=20992 C1=0.85
Ch1=101001000000000 Ch1=20992 C1=0.85
Ch1=101001000000000 Ch1=20992 C1=0.85
Ch1=101001000000000 Ch1=20992 C1=0.85
Ch1=101001100000000 Ch1=21248 C1=0.88
Ch1=101001000000000 Ch1=20992 C1=0.85
Ch1=101001000000000 Ch1=20992 C1=0.85
Ch1=101001000000000 Ch1=20992 C1=0.85
Ch1=101001000000000 Ch1=20992 C1=0.85

I'm using 6pF fix capacitance this time, probable is any else register need to modify ?

l00ger:
But it only show me two number below,

Because, you asked to print the value of only one channel in BIN, DEC, and float.

Can you upload the sketch of Post#5 and check that you are getting the same output as of Post#8.

Good! Enjoy your time and project.

Post#5 can't work, it stop at

do
{
Wire.requestFrom(AD7150_I2C_ADDRESS, 3); //if conversion complete, we can read data bytes also
}
while(Wire.read() != 0x52); //at busy--Wire.read() = Status Register 0x53; else Wire.read() = 0x52

Also Post#7 code has the same problem now...
So i add a "delay(4);" after "Wire.endTransmission();" , after that it Improve a lot, my finally code is below

#include <Wire.h>

#define AD7150_I2C_ADDRESS 0x48 //AD7150 adress
#define AD7150_REG_STATUS 0x00
#define AD7150_REG_CH1_DATA_HIGH 0x01
#define AD7150_REG_CH1_DATA_LOW x02
#define AD7150_REG_CH1_SETUP 0x0B
#define AD7150_REG_CONFIGURATION 0x0F

byte myArray[] = {219, 0, 0, 0, 49, 0, 255}; //SETUP Reg, x, x, x, CONFIG REg

void setup()
{
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(AD7150_I2C_ADDRESS);
Wire.write(AD7150_REG_CH1_SETUP); //Move pointer to the SETUP register address
Wire.write(myArray, sizeof(myArray)); //see global arry declaration
byte busStatus = Wire.endTransmission();
delay(4);
if(busStatus !=0)
{
Serial.println("I2C Communication problem....!");
while(1); //wait for ever
}

}

void loop()
{
Wire.beginTransmission(AD7150_I2C_ADDRESS); // "Hey, AD7150 @ 0x48! Message for you"
Wire.write(AD7150_REG_STATUS); //pointing Status Register
Wire.endTransmission();
delay(4);
do
{
Wire.requestFrom(AD7150_I2C_ADDRESS, 1); //if conversion complete, we can read data bytes also
}
while(Wire.read() != 0x52); //at busy--Wire.read() = Status Register 0x53; else Wire.read() = 0x52
Wire.beginTransmission(AD7150_I2C_ADDRESS); // "Hey, AD7150 @ 0x48! Message for you"
Wire.write(AD7150_REG_CH1_DATA_HIGH); //pointing DATA_H Register
Wire.endTransmission();
delay(4);
Wire.requestFrom(AD7150_I2C_ADDRESS, 2);
int ch1 = (int)Wire.read() <<8 | (int) Wire.read();
float Cap1 = (ch1 - 12288) * 4.0 / 40944.0; //Converts digital value into capacitance, formula from datasheet.
//print the data on serial monitor
Serial.print("Ch1="); Serial.print(ch1, BIN);
Serial.print(" Ch1="); Serial.print(ch1, DEC);
Serial.print(" C1="); Serial.println(Cap1, 4);
delay(700);
}

And i also has a question, now i'm 2pF TO 3pF Variable capacitance as my Cin, but no matter capacitance value changed, C1 value stay still, is that any other registers setting wrong ?

ch1H =1010011 ch1L =10011101Ch1=101001110011101 Ch1=21405 C1=0.8907
ch1H =1010011 ch1L =10111001Ch1=101001110111001 Ch1=21433 C1=0.8934
ch1H =1010011 ch1L =10011001 Ch1=101001110011001 Ch1=21401 C1=0.8903
ch1H =1010010 ch1L =10011001 Ch1=101001010011001 Ch1=21145 C1=0.8653
ch1H =1010011 ch1L =10001010 Ch1=101001110001010 Ch1=21386 C1=0.8888
ch1H =1010011 ch1L =10001010 Ch1=101001110001010 Ch1=21386 C1=0.8888
ch1H =1010011 ch1L =10001010 Ch1=101001110001010 Ch1=21386 C1=0.8888
ch1H =1010011 ch1L =1100010 Ch1=101001101100010 Ch1=21346 C1=0.8849
ch1H =1010010 ch1L =1100010 Ch1=101001001100010 Ch1=21090 C1=0.8599
ch1H =1010011 ch1L =1001111 Ch1=101001101001111 Ch1=21327 C1=0.8831
ch1H =1010011 ch1L =1100111 Ch1=101001101100111 Ch1=21351 C1=0.8854

1. Please, use code tage (</>) to post your codes online in this post/reply page. To do so, follow these steps:
(1) Open your sketch in the IDE and make a copy of it by pressing 'Ctrl+A and then Ctrl+C'.
(2) Open the post/reply page.
(3) Click on the symbol (</>) in the tool bar of the post page. You will get: [ code ] and [/code ].
(4) Place the cursor in the middle of [ code ] and [/ code ] and then press Ctrl+V in the Keyboard.
(5) Your code will appear like this:

#include <Wire.h>

#define AD7150_I2C_ADDRESS 0x48               //AD7150 adress
#define AD7150_REG_STATUS 0x00

2. Your project requires trouble shooting and debugging based on SSS (Small Start Strategy) approach.
(1) Take out all jumpers between UNO and sensor. Put back the jumpers one-by-one after continuity check by AVM/DVM.

(2) Upload a sketch just to read the serial number of the sensor. Test both sensors (you have at least two sensors!).

(3) Connect a capacitor (10 pF to 14 pF) across EXC and CIN pins of the sensor. Upload sketch of Post#7 and check that the output changes as the capacitor value changes.
cin.png

cin.png