I2C - Arduino Uno to AD7153. All registers reading "83"

All,

I have an AD7152 capacitance to digital converter that I am trying to read using an arduino UNO and I am having some problems getting it to work. I am sure its a simple fix but I can not find it.

Here is what I have have so far.

(1) The data sheet can be found here:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD7152_7153.pdf.

(2) I have 1k pull up resistors pulling the SDA and SCL lines up to 3.3 volts, coming from the Arduino.

(3) I ran the I2C search script that seems to float around everywhere, and I got an address of 0x48.

(4) I run the following code that I have written. I am no expert so I assume the problem is in my code.

#include <Wire.h>

// Austin Downey I2C

// I ran the search code and found a I2C device at address 0x48 


// define the address of the I2C cap-digital chip

#define ADDRESS 0x48


// setup, open serial, begin wire, and print test.

void setup(){
  
   Serial.begin(9600);
  
  Wire.begin();
  
  delay(20);
  
  Serial.println ("test");
  
}



void loop(){
  
  // open transmission to the address found before.
  Wire.beginTransmission(ADDRESS);
  
  // ask to read the registor 
  Wire.write(0);
  
  // close transmission
  Wire.endTransmission();
  delay(500);
  
  //read 1 byte from the address 
  Wire.requestFrom(ADDRESS, 1);
  
  //wait till wire.available returns a zero
  while(Wire.available() == 0);
  
  // print the read value. 
  int c = Wire.read();  
  Serial.println(c);
  delay(1000);
  
  
}

It does not matter what register I ask to read, the serial port always returns “83”. Does this number mean some sort of error? How can I read the data stored in the registers?

Please let me know if there is anything else I can provide.

Thanks in advance for the help.

Austin.

All,

I’m still working on the code. I don’t have it working but I tried to add a few wire.write functions to read 3 registers in a row. I now get (83,-1,-1). I have copied the code again to be helpful.

#include <Wire.h>

// Austin Downey I2C

// I ran the search code and found a I2C device at address 0x48 


// define the address of the I2C cap-digital chip

#define ADDRESS 0x48


// setup, open serial, begin wire, and print test.

void setup(){
  
   Serial.begin(9600);
  
  Wire.begin();
  
  delay(20);
  
  Serial.println ("test");
  
}



void loop(){
  
  int c1,c2,c3;
  
  // open transmission to the address found before.
  Wire.beginTransmission(ADDRESS);
  
  // ask to read the registor 
  Wire.write(0x00);
  Wire.write(0x01);
  Wire.write(0x02);
  
  // close transmission
  Wire.endTransmission();
  delay(500);
  
  //read 1 byte from the address 
  Wire.requestFrom(ADDRESS, 1);
  
  //wait till wire.available returns a zero
  while(Wire.available() == 0);
  
  // print the read value. 
  c1 = Wire.read();  
  c2 = Wire.read();  
  c3 = Wire.read();  
  
  
  Serial.println(c1);
  Serial.println(c2);
  Serial.println(c3);
  delay(1000);
  
  
}

Please explain what you have. We would to know more, almost as if we are looking over your shoulder.

Do you use the bare AD7152 chip ? or a module with a few extra components ? If you have used a i2c scanner sketch, please tell us which one. Use this one http://playground.arduino.cc/Main/I2cScanner or this one http://gammon.com.au/forum/?id=10896&reply=6#reply6 Let it run for a while to see if that is stable.

Have you accidently connected the chip to 5V, then it might be broken.

Don't use 1k pullup resistors. They can be 4k7 or 10k, but not 1k. You can even remove every pullup resistor, the internal pullup resistors of the Arduino Uno of 50k will probably enough (for testing).

This line can be removed : while(Wire.available() == 0) ; I know many others do that, but that is not how the Wire library should be used.

In the second sketch, you request 1 byte, and you read 3. The extra bytes will be -1 because the AD7152 did not send them.

A value of 0x83, is that the status register ? Would that mean the chip is in power-down mode ?

Koepel,

Thanks for the advice I will try answer all your questions.

  1. I am using a bare AD7152 chip on a breakout board. (if needed I can host a image on my website)
  2. I am using the I2C scanner that can be found at http://playground.arduino.cc/Main/I2cScanner
  3. The results are stable.
  4. Yes, I did. (I ordered a new chip today in case this is the problem). I figured it was OK as I am still able to pick it up using the I2C scanner.
  5. I used the 1k pull up resistor that is what the data sheet called for. (I sure can play around with this).
  6. I can remove the code line (Wire.available() == 0). It seems every one is using some sort of wait function so I figured I needed one.

  7. The value of 0x83 does not seem to line up with anything for the registers. I checked in binary also. I am not sure about a power down state.

OK, maybe a new chip will fix my problems, but I still think my code is wrong. Here is why.

Looking at page 11 of the data sheet (see below) it states that "The start byte address is Address 0x90 for a write and Address 0x91 for a read." What does this mean? My slave address is 0X48, is this something I need to use in the code?

I don't see where it ask for a read byte, only a read bit.

Looking at page 12 It looks like my read sequence has 2 start bits, am I right? Should I issue two Wire.begin() commands?

The data sheet can be found here http://www.analog.com/media/en/technical-documentation/data-sheets/AD7152_7153.pdf

Thanks again for all your help. I think I am converging on a working solution.

I promise if I get this working to update this thread.

OK, I have a few questions I would like to ask.

  1. What else is on the breakout board ? smd components ? resistors ? capacitors ?

  2. A lot of times a 3.3V chip is accidently connected to 5V on this forum. Many do still work after that, but even if they work, perhaps something is damaged inside.

  3. Don't use the 1k. Maybe the sensor can handle it, but it is outside the specifications of the Arduino. Use 4k7 or 10k. The maximum source current for the I2C is 3mA. Trust me, remove the 1k.

  4. No, not everyone. Only people that don't know the Wire library use some kind of waiting. When the Wire.requestFrom() returns, the complete I2C transaction has finished.

  5. I read in the datasheet that the status register should be 0x03. And you have 0x83. That would make sense if the power down bit is also '1'.

Don't worry about start bits, or 0x90 / 0x91 / 0x48. The Arduino i2c_scanner finds the sensor at 0x48, then it is 0x48. Explanation: The chips uses normal I2C. So does the Arduino. Therefor the start and stop conditions will work. It is not a start "bit". It is a start condition that uses a combination of SDA and SCL. The I2C address is a byte and the lowest bit indicates read or write. However, the Arduino uses the 7 upper bits shifted one bit to the right. So the Arduino uses 0x48, and during the I2C transaction, the read/write bit is added. That means that 0x90 and 0x91 and 0x48 are all the same thing.

Remove the 1k pullup resistor.

Next step is to make your sketch work. I have not read the datasheet, maybe it needs a certain start sequence to the registers, maybe there is already code on Github. Can you search for code ?

Koepel,

Thanks again. I will host a picture of my setup on my website and post it here tonight.

Thanks for explaining the 0x90 / 0x91 / 0x48 difference. That makes perfect sense as their binary counterparts are 10010000 / 10010001 / 1001000. That is really cool.

As for code I have not been able to find any. I have found a topic on stackoverflow where someone seems to have an AD7152 hooked up to an Arduino and I have posted the link below.

The data sheet states that the read sequence is:

Start bit - Slave ADDR - Sub ADDR - Acknowledge by slave - Start bit - Data - Acknowledge by master ........

Maybe my problem is in the two start sequences, I will have to look into this more, I will be back tonight with an update.

MATLAB - Arduino - AD7152 http://stackoverflow.com/questions/32128586/matlab-serial-fscanf-reading-long-int-from-arduino

Do you have the "AD7152 Evaluation Board" (EVAL-AD7152EBZ) from Analog ? That board has 2k2 pullup resistor for SDA and SCL. You should not add any more pullup to that.

This is the manufacturer's page : http://www.analog.com/en/products/analog-to-digital-converters/integrated-special-purpose-converters/capacitive-to-digital-and-touch-screen-controllers/ad7152.html#product-overview

Writing : The Master write the register-pointer and after that one data byte to the registers or multiple bytes because the register-pointer is auto-incremented. Reading : According to the datasheet a repeated start it needed after the register-pointer is set. The Master can read one byte or multiple bytes.

To make things terribly and absolutely unnecessary confusing, they call the "register-pointer" also a "subaddress". Forget about that. It's just normal I2C like any other. Only the repeated start is needed.

The next example are more like pseudo-code, but you get the idea. Writing:

  Wire.beginTransmission(0x48);          // The Slave address
  Wire.write (register pointer);             // AD7152 register pointer to start
  Wire.write (first data byte);
  Wire.write (second data byte);
  ...
  Wire.endTransmission();

Reading:

  Wire.beginTransmission(0x48);          // The Slave address
  Wire.write (register pointer);             // AD7152 register pointer to start
  Wire.endTransmission(false);             // false, this is the repeated start ! !

  int n = Wire.requestFrom(0x48, 4);   // read 4 bytes
  if ( n == 4)
  {
    // success, we got the 4 bytes that we requested.
    // Use four Wire.read() or just one Wire.readBytes.
    byte buffer[10];
    Wire.readBytes( buffer, n);
  }
  else
  {
    // something happened, we requested 4 bytes, but didn't get 4 bytes.
  }

There is already an undocumented function in the Wire library, that sets the register-pointer and does a Wire.requestFrom. https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/libraries/Wire/Wire.cpp Look for the base function of TwoWire::requestFrom

I can't find code for it. Are you sure you can write that yourself. The chips needs some kind of calibrating. I don't understand the linux driver very well http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/staging/iio/cdc/ad7152.c

Koepel,

Again, Thank you for all your help.

I “think” I have it working. It seems that I am able to read some data. The data is perfectly stable so I know it has some problems but I hope this is just a setup thing.

  1. Here are pictures of my setup.

http://adowney2.public.iastate.edu/projects/AD7152/AD7152.html

  1. Here is the code that I am using to talk to the chip. (Thanks for helping me with the code)
#include <Wire.h>

// Austin Downey I2C
// I ran the search code and found a I2C device at address 0x48 
// define the address of the I2C cap-digital chip
#define ADDRESS 0x48
// setup, open serial, begin wire, and print test.
void setup(){
  Serial.begin(9600);
  Wire.begin();
  delay(20);
  Serial.println ("test");
}

void loop(){
  
  int c1,c2,c3,c4;
    
  // writing to the 7152
  // open transmission to the address found before.
  Wire.beginTransmission(0x48);
  // ask to read the registor 
  Wire.write(0x0F);
  // write the data 00010001 to address 0x0F.  This is the CONFIGURATION REGISTER and I think I am telling the chip to run Ch 1 in Continuous conversion mode. 
  Wire.write(0x11);
  //I belive I only need to send one byte
  
  //Wire.write(0x00);
  //Wire.write(0x00);
  // close transmission
  Wire.endTransmission();
  delay(500);
  
  // reading from the AD7152
  Wire.beginTransmission(0x48);            // The Slave address
  //  Wire.write(register pointer);            // AD7152 register pointer to start
    Wire.write(0x01);                       // Set the AD7152 to the subaddress 0x01.  I think this should auto increment so I will read 0x01 through 0x04
  Wire.endTransmission(false);             // false, this is the repeated start ! !

  int n = Wire.requestFrom(0x48, 4);   // read 4 bytes
  if ( n == 4)
  {
    // success, we got the 4 bytes that we requested.
    // Use four Wire.read() or just one Wire.readBytes.
    c1 = Wire.read();
    c2 = Wire.read();
    c3 = Wire.read();
    c4 = Wire.read();
  }
  else
  {
    // something happened, we requested 4 bytes, but didn't get 4 bytes.
  }
  
  Serial.println(c1);
  Serial.println(c2);
  Serial.println(c3);
  Serial.println(c4);
  Serial.println ("break");
  
}
  1. This is what I am reading on the serial port with a 1pF capacitor.

217
144
0
0
break

This translate to 01101100101001 or 6953 (note the last four binary digits of 144 are left off again)

  1. This is what I am reading on the serial port with no capacitor hooked up.

148
208
0
0
break

This translate to 01001010001101 or 4749 (note the last four binary digits of 208 are left off)

A problem still arises when I try to read the status register at 0x00. In now get 82, or 01010010. Can an unused bit be high or low? If I have a 1 in bit 2, does this matter as that bit place is only used on the AD7152? (I have the 7153)

You will notice that I took out your buffer content from the code. I tried unsuccessfully to make this work. I will have to explore this concept a little bit more in the future.

As for your last two comments, I am unsure of what you where trying to convey. I will have to come back to these later.

When I get this working for real I will be back with a full write-up / tutorial. Something to help the next girl of guy.

That is indeed a breakout board, just a bare breakout board.

Reading and writing the registers of the chip is good in your sketch. You don't have to use the buffer, using Wire.read() is perfectly fine.

O no, you used the word 'subaddress' in the sketch ;)

0x11 to register 0x0F : channel 1 continues mode. Okay. Read register 0x01, 0x02, 0x03, 0x04 : channel 1 and 2. Okay.

Status register: It is possible that the unused /RDY2 is a '1'. It is also possible that in continuous mode the /RDY1 is a '0'. No problem with that. However, that PWDN bit is weird. It should be '0'.

Let's make an unsigned integer of the data registers. word : https://www.arduino.cc/en/Reference/WordCast

unsigned int channel1 = word (c1, c2);    // c1 = high byte, c2 = low byte.
unsigned int channel2 = word (c3, c4);

Serial.print("channel1 = ");
Serial.println(channel1);
Serial.print("channel2 = ");
Serial.println(channel2);

Forget about that undocumented function. It is a Wire.requestFrom() that has setting the register pointer included. That means that Wire.beginTransmission, Wire.write(register pointer), Wire.endTransmission are included in the Wire.requestFrom() function.

That chip was soldered by hand. I even build a setup so I could mount my USB mirocsocpe on my CNC machine just to check it. :) :) :) :) :)

Subaddress should of been pointer. :confused:

I need to shift the last word from a 8 byte word to a 4 byte word before I combine them, or maybe just combine them and subtract a constant. I will have to work on that in the future.

my next task is to get the chip to measure capacitance. These values should change when I touch the capacitor, but they don't. I think I need to tell the chip what setup I am using.

I will post back with results.

Thanks again, Austin.