Author Topic: Programming an external ADC(AD7921)  (Read 5213 times)

0 Members and 1 Guest are viewing this topic.

Offline brendanTopic starter

  • Contributor
  • Posts: 15
Programming an external ADC(AD7921)
« on: February 11, 2015, 12:23:32 pm »
Hey ,

I am programming an SPI communication between my AD7921 and the microcontroller Arduino DUE.
the Datasheet of my ADC is :http://www.analog.com/static/imported-files/data_sheets/AD7911_7921.pdf

here is the Programm i wrote for both channels. but there is a mistake, that i cant see:


#include <SPI.h>

int cs = 4;

void setup(){
  pinMode(cs, OUTPUT);                   

  digitalWrite(cs, HIGH);                 
  SPI.begin();                             
  SPI.setDataMode(SPI_MODE3);             
  SPI.setClockDivider(cs,21);             
  SPI.setBitOrder(MSBFIRST);             
  Serial.begin(9600);
}

void loop()
{
  int adcWert0 = readAdc(0);
  int adcWert1 = readAdc(1);
  delay(1000);
 }

 int readAdc(int channel)
 {
   byte adcPrimaryByteMask=00101111;
   byte adcPrimaryRegister=channel<<5;
   digitalWrite(cs, LOW);
   byte adcPrimarybyte = SPI.transfer(adcPrimaryRegister);   
   byte adcSecondarybyte = SPI.transfer(0x00);               
   digitalWrite(cs, HIGH);
   adcPrimarybyte &= adcPrimaryByteMask;
   adcPrimarybyte = adcPrimarybyte << 8;
   int adcValue = adcPrimarybyte|adcSecondarybyte;
   return adcValue;
 }
in Attachements you can see  the result of the conversion. it is working only for channel 0.

please i Need you help.

 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3240
  • Country: gb
Re: Programming an external ADC(AD7921)
« Reply #1 on: February 11, 2015, 03:16:13 pm »
I can see quite a few mistakes here:

Code: [Select]
int readAdc(int channel)
 {
   byte adcPrimaryByteMask=00101111;

You can not specify a binary value like this, I'm surprised the compiler didn't give a warning about the value being loaded into adcPrimaryByteMask (you did check the compiler warnings didn't you?).  Specify it as a hex value,  adcPrimaryByteMask=0x2F;  However in this case there's little point loading a literal into a local variable since you never modify it and it's used only once in the function.

Code: [Select]
   byte adcPrimaryRegister=channel<<5;
   digitalWrite(cs, LOW);
   byte adcPrimarybyte = SPI.transfer(adcPrimaryRegister);   
   byte adcSecondarybyte = SPI.transfer(0x00);               
   digitalWrite(cs, HIGH);
   adcPrimarybyte &= adcPrimaryByteMask;
   adcPrimarybyte = adcPrimarybyte << 8;

You are left shifting an 8 bit value by 8 bits, and then assigning the result to an 8 bit variable.  What do you think the result is going to be?

Since your 8 bit value will be integer promoted, you can simply do this:

Code: [Select]
return ((adcPrimarybyte & 0x2F) << 8) | adcSecondarybyte;

Another issue is I suspect you haven't read the datasheet properly.  The outgoing 16 bit word that holds the channel address bit specifies the channel for the NEXT conversion, not the current one.  This means that in your loop() that adcWert0 will hold the value for channel 1 and adcWert1 will hold the value for channel 0.
 

Offline brendanTopic starter

  • Contributor
  • Posts: 15
Re: Programming an external ADC(AD7921)
« Reply #2 on: February 11, 2015, 04:09:02 pm »
Hey mikerj,
 
Thank you very much for your Help. I changed all the mistakes that you mentioned, but i still have a Problem. I just want to be sure that my Programm is ok with the descriptions of the datasheet. could you please check my (void Setup) and tell mee if my Programm is ok?

Thank you for your Help.
 

Offline diyaudio

  • Frequent Contributor
  • **
  • !
  • Posts: 683
  • Country: za
Re: Programming an external ADC(AD7921)
« Reply #3 on: February 11, 2015, 07:31:15 pm »
Hey ,

I am programming an SPI communication between my AD7921 and the microcontroller Arduino DUE.
the Datasheet of my ADC is :http://www.analog.com/static/imported-files/data_sheets/AD7911_7921.pdf

here is the Programm i wrote for both channels. but there is a mistake, that i cant see:


#include <SPI.h>

int cs = 4;

void setup(){
  pinMode(cs, OUTPUT);                   

  digitalWrite(cs, HIGH);                 
  SPI.begin();                             
  SPI.setDataMode(SPI_MODE3);             
  SPI.setClockDivider(cs,21);             
  SPI.setBitOrder(MSBFIRST);             
  Serial.begin(9600);
}

void loop()
{
  int adcWert0 = readAdc(0);
  int adcWert1 = readAdc(1);
  delay(1000);
 }

 int readAdc(int channel)
 {
   byte adcPrimaryByteMask=00101111;
   byte adcPrimaryRegister=channel<<5;
   digitalWrite(cs, LOW);
   byte adcPrimarybyte = SPI.transfer(adcPrimaryRegister);   
   byte adcSecondarybyte = SPI.transfer(0x00);               
   digitalWrite(cs, HIGH);
   adcPrimarybyte &= adcPrimaryByteMask;
   adcPrimarybyte = adcPrimarybyte << 8;
   int adcValue = adcPrimarybyte|adcSecondarybyte;
   return adcValue;
 }
in Attachements you can see  the result of the conversion. it is working only for channel 0.

please i Need you help.

The problem is you haven't really read the datasheet thoroughly. I recently started working with Analogue Devices ADC`s and looking at that datasheet their data frames are all the same.

Are you  using 16 SCLK cycles during each frame transaction. ?

 
 
The following users thanked this post: lorenrus

Offline brendanTopic starter

  • Contributor
  • Posts: 15
Re: Programming an external ADC(AD7921)
« Reply #4 on: February 11, 2015, 07:35:42 pm »
I think yes. You can check it on the Attachment i posted.
 

Offline AndreasF

  • Frequent Contributor
  • **
  • Posts: 251
  • Country: gb
    • mind-dump.net
Re: Programming an external ADC(AD7921)
« Reply #5 on: February 11, 2015, 07:50:41 pm »
I think yes. You can check it on the Attachment i posted.

But there is a pause between the first set of 8 and the second set, which may upset the ADC, since this ADC appears to use the SPI clock to drive the conversion.
my random ramblings mind-dump.net
 

Offline brendanTopic starter

  • Contributor
  • Posts: 15
Re: Programming an external ADC(AD7921)
« Reply #6 on: February 11, 2015, 08:43:40 pm »
Yes i also saw it. But i dont know why i get this pause. I didnt include it in my Program.may bee it is a standard of arduino due.
 

Offline AndreasF

  • Frequent Contributor
  • **
  • Posts: 251
  • Country: gb
    • mind-dump.net
Re: Programming an external ADC(AD7921)
« Reply #7 on: February 11, 2015, 09:30:17 pm »
I highly doubt it's a problem with the chip on the Due itself, but rather one of those limitations that come with using a provided library instead of working directly with the hardware. The delay likely comes from the fact that a) there is some time between calling SPI.transfer() and the actual begin of the transmission of the data, and b) there is some delay between the time the actual SPI transfer has finished and the time the SP.transfer() method returns to the calling function.

There seems to be a different call to SPI.transfer() that allows you to transfer more than one byte at a time (at least in the most recent version of the Arduino libraries for the Due), but it doesn't seem to be mentioned on their website. Seems fairly straight forward to use though (but maybe not for a beginner).

Code: [Select]
void SPIClass::transfer(byte _pin, void *_buf, size_t _count, SPITransferMode _mode)
my random ramblings mind-dump.net
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Programming an external ADC(AD7921)
« Reply #8 on: February 11, 2015, 09:36:29 pm »
you may not have sufficient timing between the first and 2nd conversion - the datasheet must have some spec on that. I would insert some delays there to try it out.

Or the 2nd channel is indeed grounded.
================================
https://dannyelectronics.wordpress.com/
 

Offline brendanTopic starter

  • Contributor
  • Posts: 15
Re: Programming an external ADC(AD7921)
« Reply #9 on: February 11, 2015, 10:05:26 pm »
Ok thank you for your advices. I will try to insert a delay tomorow and see what will happen.
sorry again if i disturbed you, i am a beginner with spi and arduino.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Programming an external ADC(AD7921)
« Reply #10 on: February 11, 2015, 10:58:05 pm »
Alternatively, you can simply read ch1 first and then ch0.

================================
https://dannyelectronics.wordpress.com/
 

Offline neslekkim

  • Super Contributor
  • ***
  • Posts: 1305
  • Country: no
Re: Programming an external ADC(AD7921)
« Reply #11 on: February 12, 2015, 10:23:01 am »
Why do you want to use this ADC?, since the DUE already have 12bit adc?
 

Offline brendanTopic starter

  • Contributor
  • Posts: 15
Re: Programming an external ADC(AD7921)
« Reply #12 on: February 12, 2015, 10:33:42 am »
I have to use an external ADC, because it is part of my project. i didnt have the choice.
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3240
  • Country: gb
Re: Programming an external ADC(AD7921)
« Reply #13 on: February 12, 2015, 06:05:54 pm »
you may not have sufficient timing between the first and 2nd conversion - the datasheet must have some spec on that. I would insert some delays there to try it out.

Or the 2nd channel is indeed grounded.

Minimum 30ns, so I doubt that's the problem.

OP, can you post the current version of the code you are using?
 

Offline DesertTechie

  • Newbie
  • Posts: 1
Re: Programming an external ADC(AD7921)
« Reply #14 on: February 13, 2015, 12:40:40 am »
byte adcPrimaryByteMask=00101111;

should be defined this way if you want to use binary:

byte adcPrimaryByteMask=0b00101111;

or in hex:

byte adcPrimaryByteMask=0x2F;
 

Offline AndreasF

  • Frequent Contributor
  • **
  • Posts: 251
  • Country: gb
    • mind-dump.net
Re: Programming an external ADC(AD7921)
« Reply #15 on: February 13, 2015, 12:09:22 pm »
I would think that sure  adcPrimaryByteMask should be 0x0F since bit 5 of the first MSbyte is only a reflection of the converted channel and is not really part of the conversion result. I doub't that solves your original problem though.

Also, please put any code in the correct code markup - the # symbol in the post editor so it looks nicer:

Code: [Select]
#include <SPI.h>

int cs = 4;

void setup(){
  pinMode(cs, OUTPUT);                     
  digitalWrite(cs, HIGH);                 
  SPI.begin();                             
  SPI.setDataMode(SPI_MODE3);             
  SPI.setClockDivider(cs,21);             
  SPI.setBitOrder(MSBFIRST);               
  Serial.begin(9600);
}

void loop()
{
  int adcWert0;
  int adcWert1;
 
  adcWert1 = readAdc(1);
  adcWert0 = readAdc(0);
  delay(1000);
}
 
...
 }

Edit :wtf:  Whoa - I made this reply in response to the post of the OT directly below mine.
« Last Edit: February 13, 2015, 12:19:00 pm by AndreasF »
my random ramblings mind-dump.net
 

Offline brendanTopic starter

  • Contributor
  • Posts: 15
Re: Programming an external ADC(AD7921)
« Reply #16 on: February 13, 2015, 12:13:43 pm »
hier is my actual code. i also changed the adc(i took a new), but i still have a Problem. may be in the program.

#include <SPI.h>

int cs = 4;

void setup(){
  pinMode(cs, OUTPUT);                     
  digitalWrite(cs, HIGH);                 
  SPI.begin();                             
  SPI.setDataMode(SPI_MODE3);             
  SPI.setClockDivider(cs,21);             
  SPI.setBitOrder(MSBFIRST);               
  Serial.begin(9600);
}

void loop()
{
  int adcWert0;
  int adcWert1;
 
  adcWert1 = readAdc(1);
  adcWert0 = readAdc(0);
  delay(1000);
}
 
 int readAdc(int channel)
 {
   int adcValue;
   byte adcPrimaryByteMask;
   byte adcPrimaryRegister;
   int adcPrimarybyte;
   byte adcSecondarybyte;
   
   adcPrimaryByteMask=0x2F;
   adcPrimaryRegister=channel<<5;
   
   digitalWrite(cs, LOW);
   adcPrimarybyte = SPI.transfer(adcPrimaryRegister); 
   adcSecondarybyte = SPI.transfer(0x00);
   digitalWrite(cs, HIGH); 
   adcPrimarybyte &= adcPrimaryByteMask;
   adcValue = (adcPrimarybyte <<8 )|adcSecondarybyte;
   return adcValue;   
 }

i just want to be sure that this code is correct. if yes, i will check my platine again.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf