Go Down

Topic: Data ADC 16bit Unreliable Where Is Wrong? (Read 1 time) previous topic - next topic

oneitusatu

ive already made my arduino uno to read data adc 16 bit from max1416
http://datasheets.maxim-ic.com/en/ds/MAX1415-MAX1416.pdf
pin configuration


my code
Code: [Select]
#include "SPI.h"

int ss=10;
unsigned int adcValue;
byte highByte;
byte lowByte;

void setup(){
  pinMode(ss, OUTPUT);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  Serial.begin(9600);
}
void loop()
{
  //series of commandbit   
  digitalWrite(ss,LOW);
  SPI.transfer(0x20);//command for comm reg to select ch1 and write to clock register
  SPI.transfer(0xA5);//command for clock reg to set 2,4576Mhz                                 
  SPI.transfer(0x10);//command for comm reg to write setup register                         
  SPI.transfer(0x44);//command for setup reg to self calibration,unipolar,unbuffered,   
 
 

  while(1)
  {
      char DataNotReady = 0x80;
      while(DataNotReady) // wait for end of conversion
      {
          SPI.transfer(0x08);//command for comm reg to read  (dec   8)
          DataNotReady =SPI.transfer(0x00); // Read comm register
  DataNotReady &= 0x80;
      }
     
     
      SPI.transfer(0x38);//command for the comm to read data register for channel 1
     
  //read 16bit of data ADC
      highByte = SPI.transfer(0x00);
      lowByte = SPI.transfer(0x00);
     
      adcValue = highByte << 8;
      adcValue = adcValue | lowByte;
     
      digitalWrite(ss,HIGH);
      Serial.print("analog value =");
      Serial.println(adcValue, DEC);
      Serial.print('\n');
      delay(1000);
  }
}


my problems is the reading of adc seems random and giving the floating number,
here is the reading when i connect ain+ to 5volt with reference 5volt,and i use 5volt pin in arduino

Quote

analog value =0

analog value =32896

analog value =0

analog value =32896

analog value =128

analog value =32896

analog value =0

analog value =32896


and these is the result when i connect the ain+ to GND

Quote
analog value =0

analog value =65471

analog value =16383

analog value =1926

analog value =7

analog value =34811

analog value =48591

analog value =4095


according to datasheet we have to read data when data is ready,it is acknowledged by pin 12,or MSB bit in communication register,so value 1 for data not ready,and 0 for data ready
but when i try to debug there,the data are never ready,it keep giving 1

i aware that the adc 16 bit have to be design well with separate analog and digital ground and etc to get precise value.but my point is i just want to developing at first level,like get values 65536 when measuring 5 volt (vref=5volt) and get zero when measuring 0 volt

where is exactly my problem?anyone?

Grumpy_Mike

Can you post a schematic of how you have wired it up.

oneitusatu

here is my schematic,


i think the problems is in this code,
Code: [Select]
while(1)
  {
      char DataNotReady = 0x80;
      while(DataNotReady) // wait for end of conversion
      {
          SPI.transfer(0x08);//command for comm reg to read  (dec   8)
          DataNotReady =SPI.transfer(0x00); // Read comm register
  DataNotReady &= 0x80;
      }
     
     
      SPI.transfer(0x38);//command for the comm to read data register for channel 1
     
  //read 16bit of data ADC
      highByte = SPI.transfer(0x00);
      lowByte = SPI.transfer(0x00);
     
      adcValue = highByte << 8;
      adcValue = adcValue | lowByte;
     
      digitalWrite(ss,HIGH);


am i doing the reading of register correctly?because from the data output we see 32896 which is in binary 1000000010000000.
we know that 10000000 is the state of data has not been ready to read in communication register.
my objective is to read the data in data register and id already set the communication register to read data register with command SPI.transfer(0x38);
but why the reading still in communication register?
sory i havent experience using the spi.h library before,

Grumpy_Mike

Well you are only powering it with 3.3V but you are giving it 5V signals and setting the reference to 5V. At best this does not do it any good, at worst has damaged it.
You should also have a 0.1uF capacitor from power to ground.
You have put the ~CE pin to pin 13 but you are not driving it with the software. This needs to be driven low just before you send it clock & data pulses and then high just after. Otherwise it will not work.

oneitusatu

#4
May 10, 2012, 02:06 am Last Edit: May 10, 2012, 02:33 am by oneitusatu Reason: 1
what do you mean ~CE?Chip Enable?if you mean that i connect it in pin 10 and id already driving it low and high then giving the data in the middle of it,
but if you are reffering to pin 13 its sclk pin,does it already handle with library spi.h?afaik in spi.h library in arduino uno already handle pin 11 = mosi ; 12= miso ; 13 =sclk;
And btw,what is exactly the purpose of putting capacitor there?

oke nice hints,ill try that tonight after work

Grumpy_Mike

Quote
what do you mean ~CE?Chip Enable?i

Using the ~ ( tilda ) in front of a pin name is another way of writing a bar on top of the pin name so ~CE means CE bar. The bar on a pin name is used to indicate that pin is active low. That is the pin does what it name says with a logic zero. Therefore the chip is enabled when a logic zero is placed on the pin.
Quote
if you mean that i connect it in pin 10 and id already driving it low and high then giving the data in the middle of it,

You must drive it low just before you send it data and you must put it back high just after. If you do not then the chip will not work correctly. This MUST be done before and after every transfer, you are not doing this. You asked where you are going wrong and I am telling you.

Quote
And btw,what is exactly the purpose of putting capacitor there?

http://www.thebox.myzen.co.uk/Tutorial/De-coupling.html

jwatte

My guess is the output is actually signed, rather than unsigned. Thus, if you change the declaration of adcValue to "int" instead of "unsigned int," it may give you better readings.
Also, if the difference is almost entirely in the upper half rather than the lower half, it's totally possible that the data transfer is little-endian, when you're currently assuming it's big-endian. If that's the case, swap which byte you assign to the upper half of the value, and which you assign to the lower half.

oneitusatu

thx you Grumpy_Mike & jwatte  :)

id already try the Grumpy_mike advice n its still giving no reading =(,,
and btw i think it doesnt need to drop cs low and high in every time we write and read the spi,
in link :
http://www.ccsinfo.com/forum/viewtopic.php?t=46768
http://www.ccsinfo.com/forum/viewtopic.php?t=47085
his code works fine without generating cs low and high every spi transfer,

and for jwatte
i use the unsigned for datatype because in this device i am setting it to unipolar mode,according to datasheet we get value up to 65536,so its unsigned

ive revised my code,
what ive improved here,
1) wait for value drdy to 0 before drop the cs in reading state

2) give cs high & low in every phase write & read
3) give a reset state when initialization
4) using hardware pooling in while loops

Code: [Select]
#include "SPI.h"

int ss=10;
int drdy=9;
int reset=8;
unsigned int adcValue;
byte highByte;
byte lowByte;

void setup(){
  pinMode(ss, OUTPUT);
  pinMode(drdy,INPUT);
  pinMode(reset, OUTPUT);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  Serial.begin(9600);
  digitalWrite(reset,LOW);
  digitalWrite(ss,LOW);
  delay(100);
  digitalWrite(reset,HIGH);
  digitalWrite(ss,HIGH);
}

void DataNotReady()
{
    int ready=digitalRead(drdy);
    while(ready)
    {
        delayMicroseconds(1);
        ready=digitalRead(drdy);
    }
}

void SeriesCommandBit()
  {
  digitalWrite(ss,LOW);
  SPI.transfer(0x20);//command for comm reg to select ch1 and write to clock register ( dec     32)
  SPI.transfer(0xA5);//command for clock reg to set 2,4576Mhz                                  ( dec    165)
  SPI.transfer(0x10);//command for comm reg to write setup register                          (dec      16)
  SPI.transfer(0x44);//command for setup reg to self calibration,unipolar,unbuffered,     (dec      68)
  digitalWrite(ss,HIGH);
  }

void loop()
{
SeriesCommandBit();   
digitalWrite(ss,LOW);
SPI.transfer(0x38);
delayMicroseconds(1);
digitalWrite(ss,HIGH);
DataNotReady();
digitalWrite(ss,LOW);
highByte = SPI.transfer(0x00);
lowByte = SPI.transfer(0x00);
adcValue = highByte << 8;
adcValue = adcValue | lowByte;
digitalWrite(ss,HIGH);
Serial.print("analog value =");
Serial.println(adcValue, DEC);
Serial.print('\n');
delay(1000);
}


ive already debuged it in drdy value,in it always giving 1,so it means the data never ready
please any advise for my situation  :D

Go Up