I2C - Accessing data registers of the AD7150 capacitance to digital converter

Hello. I am using the AD7150 (here datasheet) to get the capacitance values of a parallel plate capacitor sensor that consists of 2 capacitors. I am using both channels, each one for each parallel plate capacitor.

The datasheet has the formula to convert the digital value into capacitance:
C(pf)=(data-12288)*Input_range/40944 ; where I am using 4pf as Input_range.

After getting access to the registers, the capacitance values make no sense, and I am not sure if I did something wrong when accessing the registers o when using the different type of variables (float, int, unsigned int...etc).

The serial monitor shows me (see picture attached) that for a digital value of 23708 I get 1.00 pF, but for a value of 30875 I get 0.00pF, which does not makes sense. When I do the math with a calculator I get 1.11pF and 1.81pF respectively. Plus I couldn´t get the computations with at leats 2 decimals, it keeps showing ".00".

Hope I am clear enogh. Thanks in advance. I am attaching the code,

#include <Wire.h>
int chip_addr = 0x48; //AD7150 adress
#define ch1_dataH_addr 0x01 //Address to point the Data High of Ch1
#define ch1_dataL_addr 0x02 //Address to point the Data Low of Ch1
#define ch2_dataH_addr 0x03 //Address to point the Data High of Ch2
#define ch2_dataL_addr 0x04 //Address to point the Data Low of Ch2
#define ch1_SetupR_addr 0x0B //Setup (range) register address for Ch1
#define ch2_SetupR_addr 0x0E //Setup (range) register address for Ch2
#define ConfigR_addr 0x0F //Configuration register (operation mode -threshold-) 
#define Ch1_ThHR_addr 0x09 //Ch1 Threshold High Register
#define Ch1_ThLR_addr 0x0A //Ch1 Threshold Low Register
#define Ch2_ThHR_addr 0x0C //Ch2 Threshold High Register
#define Ch2_ThLR_addr 0x0D //Ch2 Threshold Low Register



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

void rconfig1()
{
  Wire.beginTransmission(chip_addr);
  Wire.write(ch1_SetupR_addr); //Move pointer to the register address
  Wire.write(203); //Setup features for range (bx11001011)
  Wire.endTransmission();
}

void rconfig2()
{
  Wire.beginTransmission(chip_addr);
  Wire.write(ch2_SetupR_addr); //Move pointer to the register address
  Wire.write(203); //Setup features for range (bx11001011)
  Wire.endTransmission();
}

void rconfig3()
{
  Wire.beginTransmission(chip_addr);
  Wire.write(ConfigR_addr); //Move pointer to the register address
  Wire.write(185); //Configuration of the threshold mode bx10111001
  Wire.endTransmission(); 
}


void loop() {
  //Get capacitance data
  // move the register pointer back to the second register
  Wire.beginTransmission(chip_addr); // "Hey, AD7150 @ 0x48! Message for you"
  Wire.write(1); // "move your register pointer back to 01h"
  Wire.endTransmission(); // "Thanks, goodbye..."
  // now get the data from the AD7150
  Wire.requestFrom(chip_addr, 4); // "Hey, CN75 @ 0x48 - please send me the contents of your first two registers"
  while(Wire.available())    // slave may send less than requested
  { 
  byte ch1H = Wire.read(); // first received byte stored here
  byte ch1L = Wire.read(); // second received byte stored here
  byte ch2H = Wire.read(); // third received byte stored here
  byte ch2L = Wire.read(); // fourth received byte stored here

  unsigned int ch1 = ch1H*256 + ch1L; //Concatanates the two bytes into one 16 bit word for capacitor 1.
  unsigned int ch2 = ch1H*256 + ch1L; //Concatanates the two bytes into one 16 bit word for capacitor 2.
     
  float Cap1 = (ch1-12288)*4/40944; // Converts the digital value into capacitance, formula from datasheet. 
  float Cap2 = (ch2-12288)*4/40944;
//print the data on serial monitor, data that was gotten from the registers that store capacitance values
  Serial.print("Ch1="); 
  Serial.print(ch1, BIN);
  Serial.print(" Ch1="); 
  Serial.print(ch1);
  Serial.print(" C1="); 
  Serial.print(Cap1,2);
  Serial.print("   Ch2="); 
  Serial.print(ch2, BIN);
  Serial.print(" Ch2=");
  Serial.print(ch2); 
  Serial.print(" C2="); 
  Serial.println(Cap2,2); 
   
  }
  delay(700);
}

serial_monitor.PNG

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

Numerical constants default to integers. To tell the compiler to handle the calculation as floats, write them as follows

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

In your case the 4.0 is required to keep the numerator from overflowing an int as well as creating the float. 40944 doesn't actually require the .0, once the compiler figures out the numerator, but I'm in the habit of adding the trailing .0 it whenever it might be required.

You could also avoid the overflow in the numerator by using 4L or 4UL to and then use 40944.0 to create the float. Its a matter of style and clarity.

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

Thanks so much! That resolved my problem about the overflow. Now I get the capacitance values with two decimals after the unit.

But now, the chip is detecting a change in capacitance and coming back to the original value. When the capacitor sensor is empty (air as dielectric) the serial monitor is showing capacitance equals to 0.81pF, but then when I put my hand closer it shows 1.71pF, for 1 second, and comes back to show 0.81pF. The same happens when a change the dielectricc inside for corn.

Any idea how to set the threshold in this case? What I need is the capacitance reading at any time, not just when there is a change.

Hi,

I read your post and it was exactly what I needed but now I am getting the same issue as you did.
It only reads a change in the capacitor once, then it goes back to the previous value.

Did you manage to solve it?

If so, how did you do it?

Thank you very much!!