Arduino reads AD7780 24bit ADC

Hi guys,
I'm trying for a while now to read out an AD7780 24bit ADC over the SPI.
Because the AD7780 has no "normal" SPI interface (no chip-select) I'm trying to hardcode the readout.

First of all, the Datasheet of the AD7780 is here:
http://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&uact=8&ved=0CDQQFjAB&url=http%3A%2F%2Fwww.analog.com%2Fstatic%2Fimported-files%2Fdata_sheets%2FAD7780.pdf&ei=ESBlU76tI8mvO7KsgfgH&usg=AFQjCNEl08EyIVuPFzWakHQfVjZRG2j2aA&bvm=bv.65788261,d.ZWU

The description of the Serial Interface is on Page 13.

The Data sent from AD7780 is 32bit long. There are 8bits for status and an other 24 for the value.
The Data in general is sent as MSBfirst of I read it correct.
If I'm right, the status byte is sent first. otherwhise you can't detect the RDY bit first.

#include <SPI.h>
#define AD7780_PWDOWN 28	// Reset/ Power down pin -> High is on
#define AD7780_GAIN 28		// Gain on/ off LOW = GAIN = 128/ HIGH = GAIN = 1
#define AD7780_SCK 7		// Clock
#define AD7780_MISO 6		// MISO
#define AD7780_MOSI 5		// MOSI

void setup()
{

	Serial1.begin(9600);
	Serial1.println("Start...");
	pinMode(30, OUTPUT);
	digitalWrite(30, HIGH);    // AD7080 Power einschalten
	
	pinMode(AD7780_PWDOWN, OUTPUT);
	digitalWrite(AD7780_PWDOWN, LOW);    // AD7080 ausschalten
	
	Serial1.println("AD7780 ist eingeschaltet");
}

void loop()
{
Serial1.println("read data");
	delay(1000);

digitalWrite(AD7780_SCK, HIGH);			// Clock high
delay(100);

digitalWrite(AD7780_PWDOWN, HIGH);    // AD7080 Turn on	

	while(digitalRead(AD7780_MISO)==HIGH);	// Wait until AD7780 sets RDY LOW
	Serial1.println("MISO Low");
int a = 0;

for(int i=0; i< 32; i++)
{
	a = digitalRead(AD7780_MISO);
	Serial1.print(a);
	digitalWrite(AD7780_SCK, LOW);
	delay(100);
	digitalWrite(AD7780_SCK, HIGH);
}
Serial1.println("");
digitalWrite(AD7780_PWDOWN, LOW);    // AD7080 Turn off	
}

My Problem now is I can't find any error in this reading, but it tells me values like random. Can you detect any error? Or do you know a better way of reading values from the AD7780 or equivalent?

Thank you verry much!

but it tells me values like random.

can you post a sample of the output?

I don't think you are reading the bits correctly. Figure 3 in the datasheet shows that the chip starts to present the next bit when you set the clock low. The datasheet shows that the worst case settling time is 80ns, so giving it a delay of 100ms is way more than it needs :slight_smile: Figure 3 also shows that you should read the bit when you set the clock high.
Try this for loop instead of what you have:

  for(int i=0; i< 32; i++)
  {
    digitalWrite(AD7780_SCK, LOW);
    delayMicroseconds(10);
    digitalWrite(AD7780_SCK, HIGH);
    a = digitalRead(AD7780_MISO);
    Serial1.print(a);
    delayMicroseconds(10);
  }

Both delays are still longer than needed and, in particular, the second one may be unnecessary because I'm pretty sure a digitalRead takes several microseconds.

Pete

Hi guys,
thank you very much for your fast replies!

@robtillaart:
the output of "my" code looks like this:

Opening port
Port open
Start...
AD7780 ist eingeschaltet
read data
Start...
AD7780 ist eingeschaltet
read data
MISO Low
00001111100111110011111111111000
read data
MISO Low
00001111110011111111111111111111
read data
MISO Low
00001111111111111111111111111111
read data
MISO Low
00001111111111111111111111111111
read data
MISO Low
01111111111111001111111111111111
read data
MISO Low
01111111111111111111111111111111
read data
MISO Low
01111111111111111111111111111111
read data
MISO Low
00111111111111111111111111111111
read data
Port closed

sometimes it reads 011111111111111111..... and sometimes there are bits like narrow: 010101010100011.....
but they are all starting with a zero.

@el_supremo:
Your comment sounds good. I tested it, but it gives me just 000...

Here is the output of a few sample reads:

Opening port
Port open
Start...
AD7780 ist eingeschaltet
read data
Start...
AD7780 ist eingeschaltet
read data
MISO Low
00000000000000000000000000000000
read data
MISO Low
00000000000000000000000000000000
read data
MISO Low
00000000000000000000000000000000
read data
MISO Low
00000000000000000000000000000000
read data
MISO Low
00000000000000000000000000000000
read data
Port closed

It seems to go in the right direction, but there must still be a mistake in because in case of a correct reading the PAT0 bit of the status byte should be 1. So the result can't be correct.

Thank you very much so far!

Hi,
now it looks better. I'm only able to check the status byte due to my unfinished hardware, but the status byte reacts on different settings, so i guess it's right.

What was wrong?
First: I haven't set my ports correctly (output ports as output and input ports as inputs).
Second: @el_supremo your change of delay and rising/ falling clock was correct - may thanks!

So this is a simple code which can read the AD7780 and prints the result including the status byte (24bit result + 8bit status):

#define AD7780_VCC 30		// Give AD7780 5V or not
#define AD7780_PWDOWN 28	// Reset/ Power down pin -> High is on
#define AD7780_FILTER 18
#define AD7780_GAIN 19		// Gain on/ off LOW = GAIN = 128/ HIGH = GAIN = 1
#define AD7780_SCK 7		// Clock
#define AD7780_MISO 6		// MISO
#define AD7780_MOSI 5		// MOSI

void setup()
{
	Serial1.begin(9600);
	Serial1.println("Start...");
	pinMode(AD7780_VCC, OUTPUT);
	pinMode(AD7780_PWDOWN, OUTPUT);
	pinMode(AD7780_SCK, OUTPUT);	// SCK is output
	pinMode(AD7780_FILTER, OUTPUT);
	pinMode(AD7780_GAIN, OUTPUT);
	pinMode(AD7780_MISO, INPUT);	// MISO ist read
	digitalWrite(AD7780_VCC, HIGH);			// AD7080 VCC on
	digitalWrite(AD7780_PWDOWN, LOW);		// AD7080 in Standby
	digitalWrite(AD7780_FILTER, HIGH);
	digitalWrite(AD7780_GAIN, LOW);
	Serial1.println("AD7780 initialisation finnished");
}

void loop()
{
Serial1.println("Start reading data");
	delay(100);

digitalWrite(AD7780_SCK, HIGH);				// Clock high from Arduino
delay(100);

digitalWrite(AD7780_PWDOWN, HIGH);			// AD7080 Turn on	

	while(digitalRead(AD7780_MISO)==HIGH);	// Wait until AD7780 sets RDY LOW
	Serial1.println("MISO turned low Measuring is finnished, and we get the result");
int a = 0;

 for(int i=0; i< 32; i++)
 {
	 digitalWrite(AD7780_SCK, LOW);
	 delayMicroseconds(10);
	 digitalWrite(AD7780_SCK, HIGH);
	 a = digitalRead(AD7780_MISO);
	 Serial1.print(a);
	 delayMicroseconds(10);
 }

Serial1.println("");
digitalWrite(AD7780_PWDOWN, LOW);    // AD7080 Turn off	
}

One more question:
Is there an easy way of extracting the fist 24-result-bits into a single number and the 8-status-bits into an other single number?

Thanky you!

Try changing the for loop to this:

  uint32_t adc_read = 0;
  for(int i=0; i< 32; i++)
  {
    digitalWrite(AD7780_SCK, LOW);
    delayMicroseconds(10);
    digitalWrite(AD7780_SCK, HIGH);
    if(a = digitalRead(AD7780_MISO)) {
      adc_read |= 1;
    }
    adc_read <<= 1;
    delayMicroseconds(10);
  }
// If the status byte is sent first use this
  uint8_t stat;
  stat = adc_read >> 24;
  adc_read &= 0xffffff;
// If the ADC reading is sent first use this
  uint8_t stat;
  stat = adc_read & 0xff;
  adc_read >>= 8;

The datasheet doesn't really say whether the status byte is sent before or after the ADC reading so I've added code for both possibilities. Pick whichever one is correct.

Pete