AD7730

I got a project from university to build a weight scale. I use AD7730 as load cell amplifier. It uses SPI for communication. There's no slave select pin on 7730 but there's a chip select pin.
I stuck at the SPI communication point because there's only one SPI function is available. (SPI.transfer()). It transfers one byte over the SPI bus, both sending and receiving.
But it is required to read the registers of the 7730 without sending any data to 7730.
Can someone help me to read values of AD7730? :frowning:

The datasheet for the AD7730 specifically says on the top right of page 12 that you must write to the Communications register to read any of the other registers. Page 21 gives a nice flowchart showing you how to read data from the IC. Pages 13-20 explain how data is structured within each of the registers.

I'm willing to bet your professor wants you to set up a stream from the sensor. If you look on page 21, it shows that there are two ways of reading data. The first way is called polling, where you write to the Communications register each time you want to read data from a register. The second way is called streaming, where you write to the Communications register only once and tell it to continuously send data from a register until you send it a stop command. Like I said, I bet your professor wants you to set up streaming, which requires only one write to the IC to start a continuous output of data from the IC.

Use pages 21 and 13-20 of the datasheet to figure out what you must write over SPI to start and read the data stream.

Thanks a lot for your help. But the thing I want is to read MISO stream from Arduino.
As an example, SPI.transfer(0xff); sends 255 to the slave. But I want to know how to read data from slave. :slight_smile:

byte dataRead = SPI.transfer(0xFF);

This will read one byte from slave. The 0xFF can be anything, in this case.

According to the Arduino SPI reference page, SPI.transfer() both sends and receives data. When called, SPI.transfer(val) returns a byte read from the slave (Make sure you have the SS/Chip Select line low or the AD7730 will not send anything). Although you are using SPI.transfer(val) to read a byte, you must still specify a byte to send. According to page 13 of the AD7730 datasheet, the communication register will ignore any commands that have the WEN bit (first bit) set to 1. So in this case, we will us 0xFF (255) as the byte to send, as it will set all bits to 1 and the byte will be ignored by the communication register. Does that make sense?

As an example, here is a function for reading a single byte:

byte readbyte()
{
    digitalWrite(SSPin, LOW);  // Enable AD7730 SPI communication.
    byte output = SPI.transfer(0xFF);  // Send 0xFF (0b11111111) as it will be ignored by Communication register.
    digitalWrite(SSPin, HIGH); // Disable AD7730 SPI communication.

    return output;
}

Does that help?

Oh that's tricky! :open_mouth:
Thanks a lot pcdangio and Hackscribble!

No problem! And HackScribble, quit helping other people and help solve my Ground Loops Galore thread!!! :stuck_out_tongue:

I tried to read and write AD7730. But Ended up with unexpected results.
-RDY pin never goes to LOW state.
-I cannot read what I wrote to the MODE register. (Tried removing while loop. Capture of serial monitor is attached here.)

I really need a help here. =(
Is there anyone who has succeeded with AD7730?

#define RESET 5
#define RDY 6
#define CS 7

#include <SPI.h>

byte result;
long time;

void setup() {
  pinMode(10 ,OUTPUT);
  digitalWrite(10,HIGH);
  
  Serial.begin(9600);
  
  pinMode(RDY , INPUT);
  pinMode(MISO , INPUT);
  pinMode(RESET , OUTPUT);
  pinMode(MOSI , OUTPUT);
  pinMode(CS , OUTPUT);
  
  digitalWrite(RESET,LOW);
  delay(100);
  digitalWrite(RESET,HIGH);
  
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST); //
  SPI.setClockDivider(SPI_CLOCK_DIV16);
  
  time = millis();
  
  digitalWrite(CS,LOW);
  delayMicroseconds(10);
  
  digitalWrite(10,LOW);
  
  //I tried adding a delay of 10 micro secs
  SPI.transfer(0x02);//Write to Mode register
  delayMicroseconds(10);
  SPI.transfer(0x31);//Continuous conversion, 24bits, unipolar 
  delayMicroseconds(10);
  SPI.transfer(0x80);//0mV -10mV range + AIN1 register 0
  delayMicroseconds(10);
  
  digitalWrite(10,HIGH);
  
  /*while(digitalRead(RDY)== HIGH) {//Wait until ready pin becomes LOW
    if(millis() - time > 1000){
      Serial.println("Not ready");
      time = millis();
    }
  }*/
  digitalWrite(CS,HIGH);
}

void loop(){  
  digitalWrite(CS,LOW);
  
  SPI.transfer(0x12);//Single read mode register 16 bits
  
  SPI.transfer(0xff);//Read first 8 bits
  Serial.println(SPDR);
  
  SPI.transfer(0xff);//Read second 8 bits
  Serial.println(SPDR);
  
  digitalWrite(CS,HIGH);
  delay(1000);
}

Serial Monitor.PNG

Looks like you have made some progress!

First thing that I noticed is that you have two pins assigned to do the chip/slave select for the SPI communication, when you only need one. I see you define and raise/lower both pin 10 and pin 7 (CS as you labeled it) when you are doing the SPI communications. What do you have connected to pins 7 and 10 on your Arduino? You should have the AD7730 CS pin connected to pin 10 on your Arduino, and pin 10 should be the only pin you raise/lower when using SPI.

The second problem you have is that you need to raise CS after you write each byte. The reason your mode is not changing is because you are shifting new data in before the mode byte is even read by the AD7730. SPI.transfer(A) only shifts the bits of value "A" into the AD7730's 8-bit register. You need to raise CS to tell the AD7730 to "latch" (aka read) the data that is currently in the register. If you do not raise CS and call another SPI.transfer(B), the "A" data will be replaced by "B" data without being read. Does that make sense?

Any time you write to your AD7730, this is what it should look like:

// Set CS to LOW so that the AD7730 will accept data that is transferred.
digitalWrite(CS, LOW);  // CS = pin 10 on Arduino, connected to CS pin on AD7730.

// Transfer 8 bits into the AD7730 register.
SPI.transfer(0x02);

// Set CS to HIGH so that the AD7730 knows to latch/read the 8 bits you just transferred to it.
digitalWrite(CS, HIGH);

Thank you! I tried that as well. The reason I used 10 (SS) pin because I thought CS should be always LOW until all the data is transferred.
Now I changed the code to following. But still sometimes the IC is always not ready. Sometimes RDY becomes LOW when I reset Arduino and after that I get the values in MODE register but they are not the values I wrote. And also those values are changing!!
I feel like the 7730 is malfunctioning..... :~

#define RESET 5
#define RDY 6

#include <SPI.h>

byte result;
long time;

void setup() {  
  Serial.begin(9600);
  
  pinMode(RDY , INPUT);
  pinMode(MISO , INPUT);
  pinMode(RESET , OUTPUT);
  pinMode(MOSI , OUTPUT);
  
  digitalWrite(RESET,LOW);
  delay(100);
  digitalWrite(RESET,HIGH);
  
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST); //
  SPI.setClockDivider(SPI_CLOCK_DIV16);
  
  time = millis();
  
  digitalWrite(SS,LOW);
  SPI.transfer(0x02);//Write to Mode register
  digitalWrite(SS,HIGH);
  
  delayMicroseconds(10);
  digitalWrite(SS,LOW);
  SPI.transfer(0x31);//Continuous conversion, 24bits, unipolar 
  digitalWrite(SS,HIGH);
  
  delayMicroseconds(10);
  digitalWrite(SS,LOW);
  SPI.transfer(0x80);//0mV -10mV range + AIN1 register 0
  digitalWrite(SS,HIGH);
  
  while(digitalRead(RDY)== HIGH) {//Wait until ready pin becomes LOW
    if(millis() - time > 1000){
      Serial.println("Not ready");
      time = millis();
    }
  }
}

void loop(){  
  digitalWrite(SS,LOW);  
  SPI.transfer(0x12);//Single read mode register 16 bits
  digitalWrite(SS,HIGH);
  delayMicroseconds(100);
  
  digitalWrite(SS,LOW);  
  SPI.transfer(0xff);//Read first 8 bits
  digitalWrite(SS,HIGH);  
  Serial.println(SPDR);
  delayMicroseconds(100);
  
  digitalWrite(SS,LOW);  
  SPI.transfer(0xff);//Read second 8 bits
  digitalWrite(SS,HIGH);  
  Serial.println(SPDR);
  
  delay(1000);
}

Serial Monitor.PNG

Ahh, this one is my bad. I didn't look at the data sheet closely enough.

The AD7730 has different sized registers for different functions of the chip. Here's how it works:

Any time you want to access a register, you need to first send something to the Communications register, which is 8bits. You did that just fine with the SS:LOW, SPI.transfer(0x02), SS:HIGH. This tells the chip that the next bits you send are for writing to the Mode register. The Mode register is actually 16 bits wide. So what you would do here is:

digitalWrite(SS, LOW);  // Tell chip to listen for bits.
SPI.transfer(0x31);  // Sends in first 8 bits into 16 bit register.
SPI.transfer(0x80); // Sends in second 8 bits into 16 bit register.
digitalWrite(SS, HIGH); // Tell chip's Mode register to latch/read the 16 bits of data that are in there right now.

So because the Mode register is 16 bits wide, you transfer all 16bits into it first before making SS go high and telling the chip to latch/read the register. Does that make sense?

You should do the same thing for reading the Mode register, call two SPI.transfer()'s before raising SS.

When reading/writing each register, you should check its size in the datasheet and set up your SS HIGH/LOW and SPI.transfer() calls accordingly. For example, the Filter register is 24bits wide, so you'd need to call SPI.transfer() 3 times before making SS go high.

kasunFdo, view this video AD7730 with Arduino - YouTube
Maybe, it help to your problem.

I figured out that the problem was in clock polarity. POL pin should be in HIGH state.
I corrected that problem and I was able to configure registers on 7730 successfully.

Following is my code.

#define RESET 5
#define RDY 6

#include <SPI.h>

const byte WRITE_MODE = 0x02;//Write to MODE register
const byte READ_MODE = 0x12;//Read MODE register
const byte INT_ZERO_CALIB = 0x91; //tare intern + 24bits +unipolar (MSB of MODE)
const byte INIT_CONT_CONV = 0x31;//continuous conversion, 24bits, unipolar (MSB of MODE)
const byte SET_CHANNEL = 0x80; //0mV -10mV range + AIN1 register 0 (LSB of MODE)

const byte WRITE_FILTER = 0x03;//Write to Filter register
const byte READ_FILTER = 0x13;//Read Filter register
const byte SET_CHOP = 0x10;//Set CHOP mode
const byte CLEAR_AC = 0xdf;//Set CHOP mode

const byte READ_DAC = 0x14;//
const byte WRITE_DAC = 0x04;//
const byte BITWISE_DAC = 0x3f;//
const byte READ_DATA_REG = 0x21;//

byte result1;
byte result2;
byte result3;
long time;

void setup() {  
  Serial.begin(9600);
  
  pinMode(RDY , INPUT);
  pinMode(MISO , INPUT);
  pinMode(RESET , OUTPUT);
  
  SPI.begin();
  SPI.setDataMode(SPI_MODE3);
  SPI.setBitOrder(MSBFIRST); //
  SPI.setClockDivider(SPI_CLOCK_DIV16);
  
  time = millis();
  reset();
  initialize();
}

void loop(){
  while(digitalRead(RDY) != LOW) {
    /*if(millis()-time >1000){
      readModeReg();
      time = millis();
    }*/
  }
  
  digitalWrite(SS,LOW);
  result1 = SPI.transfer(0xff);//Read first 8 bits
  result2 = SPI.transfer(0xff);//Read next 8 bits
  result3 = SPI.transfer(0xff);//Read last 8 bits
  digitalWrite(SS,HIGH);
  
  Serial.println("Data reg");
  Serial.print("1: ");
  Serial.println(result1);
  Serial.print("2: ");
  Serial.println(result2);
  Serial.print("3: ");
  Serial.println(result3);
  Serial.println();
}

void readModeReg(){
  digitalWrite(SS,LOW);  
  SPI.transfer(READ_MODE);//Single read mode register 16 bits
  digitalWrite(SS,HIGH);
  
  digitalWrite(SS,LOW);  
  result1 = SPI.transfer(0xff);//Read first 8 bits
  Serial.println(SPDR, HEX);
  //Serial.println(SPDR);
  
  result2 = SPI.transfer(0xff);//Read second 8 bits
  Serial.println(SPDR, HEX);
  digitalWrite(SS,HIGH);
  //Serial.println(SPDR);
}

void initialize(){
  digitalWrite(SS,LOW);
  SPI.transfer(WRITE_MODE);
  digitalWrite(SS,HIGH);
  
  digitalWrite(SS,LOW);
  SPI.transfer(0x91);
  SPI.transfer(SET_CHANNEL);
  digitalWrite(SS,HIGH);
  while(digitalRead(RDY) != LOW) {}
  Serial.println("Mode set");
  //delay(1000);
  //readModeReg();
//-------------------------------------  
  digitalWrite(SS,LOW);
  SPI.transfer(READ_FILTER);
  digitalWrite(SS,HIGH);
  
  digitalWrite(SS,LOW);
  result1 = SPI.transfer(0xff);
  result2 = SPI.transfer(0xff);
  result3 = SPI.transfer(0xff);
  digitalWrite(SS,HIGH);
  
  result3 = result3 & CLEAR_AC;
  result3 = result3 | SET_CHOP;
  
  digitalWrite(SS,LOW);
  SPI.transfer(WRITE_FILTER);
  digitalWrite(SS,HIGH);
  
  digitalWrite(SS,LOW);
  SPI.transfer(result1);
  SPI.transfer(result2);
  SPI.transfer(result3);
  digitalWrite(SS,HIGH);
  Serial.println("Filter set");
  //delay(1000);
  //readModeReg();
//-------------------------------------
  digitalWrite(SS,LOW);
  SPI.transfer(READ_DAC);
  digitalWrite(SS,HIGH);
  
  digitalWrite(SS,LOW);
  result1 = SPI.transfer(0xff);
  digitalWrite(SS,HIGH);
  
  result1 = result1 & BITWISE_DAC;
  
  digitalWrite(SS,LOW);
  SPI.transfer(WRITE_DAC);
  digitalWrite(SS,HIGH);
  
  digitalWrite(SS,LOW);
  SPI.transfer(result1);
  digitalWrite(SS,HIGH);
  Serial.println("DAC set");
  //readModeReg();
//-------------------------------------
  Serial.println("Continuous conv. setting");
  digitalWrite(SS,LOW);
  SPI.transfer(WRITE_MODE);
  digitalWrite(SS,HIGH);
  
  digitalWrite(SS,LOW);
  SPI.transfer(INIT_CONT_CONV);
  SPI.transfer(SET_CHANNEL);
  digitalWrite(SS,HIGH);
  while(digitalRead(RDY) != LOW) {}
  Serial.println("Continuous conv. started");
  //delay(1000);
  readModeReg();
//-------------------------------------
  digitalWrite(SS,LOW);
  SPI.transfer(READ_DATA_REG);
  digitalWrite(SS,HIGH);
  Serial.println("Reading started");
}

void reset(){
  digitalWrite(RESET,LOW);
  delay(100);
  digitalWrite(RESET,HIGH);
}

Now I ran into another issue. The IC gives output only twice. I have attached the capture of the serial monitor.
I have printed back the register values to check whether something has gone wrong but all is good.
Dear friends, can you help me?

Capture.PNG

Hello all.
@kasunFdo Please check your pin13 ( SCK )
I am trying to do the same think using ad7730, I wrote a code, tried your too but without any success. The RDY signal goes low but I read only zeros, then I checked pin13 ( SCK ) but no frequency appears. I think this is the problem. I simulate the code but the SCK ( PIN13) is always HIGH. If someone can help with the SPI library I will be happy.
I use the spi library from the site.

Hi bob4i!

I checked with a logic analyzer as well. Clock is present. I can read values from all other registers but the DATA register.
I have attached the captures from logic analyzer as well.

Yes the clock is fine, I attached the oscillator to wrong pin. Please check what value do you read from status register. After 2 reads RDY does not go LOW.
I tried to start continues mode then read and then stop it and start again, RDY always goes low but I read only zeros.
SYNC and POL are tied HIGH, I use 4.1925Mhz ,
I tried so many times without any success. When I tried to read the status register after reset the result was something 10001, that makes me think something is wrong with the code.
I will try more tricks tomorrow.

#include <SPI.h>

#define RESET 5
#define RDY 6
//#define MOSI 11
//#define MISO 12
//#define SCK 13
//#define SS 10

  



byte byte1;
byte byte2;
byte byte3;
byte byte_total;
long time;


void setup()
{
  
  pinMode(RDY, INPUT);
 pinMode(RESET, OUTPUT);
pinMode(SCK,OUTPUT);
   digitalWrite(SS, HIGH);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3);
  SPI.setClockDivider(SPI_CLOCK_DIV16);
 Serial.begin(115200);

  Serial.println("Reset ADC ...");
  digitalWrite(RESET,HIGH);
  delay(500);
  digitalWrite(RESET,LOW);
  delay(500);
  digitalWrite(RESET,HIGH);
  delay(500);
  Serial.println("Set up AD7730");
  digitalWrite(SS,LOW);
  SPI.transfer(0x03);
  digitalWrite(SS,HIGH);
//  delay(100);
  digitalWrite(SS,LOW);
  SPI.transfer(0x800010);
  digitalWrite(SS,HIGH);
//  delay(100);
  Serial.println("Set DAC register settings");
  digitalWrite(SS,LOW);
  SPI.transfer(0x04);
  digitalWrite(SS,HIGH);
//  delay(100);
  digitalWrite(SS,LOW);
  SPI.transfer(0x23);
  digitalWrite(SS,HIGH);
  //delay(100);
Serial.println("Channel 1 Internal full scale calibration");
digitalWrite(SS,LOW);
SPI.transfer(0x02);
digitalWrite(SS,HIGH);
//delay(100);
digitalWrite(SS,LOW);
SPI.transfer(0xA190);
 digitalWrite(SS,HIGH);
 digitalWrite(SS,LOW);
SPI.transfer(0x02);
digitalWrite(SS,HIGH);
while(digitalRead(RDY) !=LOW) { Serial.println("calibration wait RDY"); delay(500); }
Serial.println("calibration done");
 digitalWrite(SS,LOW);
 SPI.transfer(0x02);
 digitalWrite(SS,HIGH);
 //delay(100);
 digitalWrite(SS,LOW);
  SPI.transfer(0x9180);
  digitalWrite(SS,HIGH);
   digitalWrite(SS,LOW);
 SPI.transfer(0x02);
 digitalWrite(SS,HIGH);
 delay(100);
 while(digitalRead(RDY) !=LOW) { Serial.println("wait for RDY signal to goes LOW IN VOID SETUP2"); delay(500); }
 
}
  
  
 void loop() {
  digitalWrite(SS,LOW);
  SPI.transfer(0x02);
  digitalWrite(SS,HIGH);
//  delay(100);
  digitalWrite(SS,LOW);
  SPI.transfer(0x2180); //continuous read from channel 1
  digitalWrite(SS,HIGH);
//  delay(100);
  digitalWrite(SS,LOW);
  SPI.transfer(0x21);
  digitalWrite(SS,HIGH);
//  delay(100);
while(digitalRead(RDY) !=LOW){ Serial.println("NOT RDY IN VOID LOOP");}
//delay(500);} 
// SPI.transfer(0x30); //end continous mode
/// delay(1000);

  
// SPI.transfer(0x30); //end continous mode
//delay(1000); 
 delay(100);
  digitalWrite(SS,LOW);
  byte1 = SPI.transfer(0xff);
  byte2 = SPI.transfer(0xff);
  byte3 = SPI.transfer(0xff);
  digitalWrite(SS,HIGH);
 byte_total=byte1<<16;  
 byte2=byte2<<8;   byte_total=  byte_total|byte2|byte3;  
 byte_total=(byte_total*2)+byte_total;  
      
 SPI.transfer(0x30); //end continous mode

  Serial.print(byte1,BIN);
  Serial.print(" ");
  Serial.print(byte2,BIN);
  Serial.print(" ");
  Serial.print(byte3,BIN);
  Serial.print(" ");
  Serial.print(byte_total, DEC);
  Serial.print("\n");
  //delay(1000);
  
}
  SPI.transfer(0x800010);

You can't send three bytes with one call to transfer().

Make separate calls like this (assumes most significant byte goes first - check your datasheet).

 SPI.transfer(0x80);
 SPI.transfer(0x00);
 SPI.transfer(0x10);

I red the registers and they are same like in datasheet, wrote different once and red them and they are correct, in datasheet DATA REGISTER result is 000000 Hex and I red 000000 HEX I think have to do some calibration and settings for correct work but do not know what exactly to do.

Finished the code and the pcb but the noise is too much, settings: 24bit data output chope mode on, fast mode off, 50hz rejection, AC excistation ON, I loose about 10 bits, please give me some advice to reduce the noise.
Thank you.

Hello, I am trying a new board with AD9175 but I cannot open PCB file form analog device evaluation board CN0155. If someone can open the PCB please tell me.