|
|
View previous topic :: View next topic |
Author |
Message |
ac34856
Joined: 14 Dec 2009 Posts: 33 Location: Wales
|
AD7705 not reading full 16 bits ? |
Posted: Fri Mar 12, 2010 11:28 am |
|
|
I'm back to the AD7705 which has been the only glitch with my design.
The following code reads back 22547 at 2.45V with a 2.5V reference in
unipolar mode and somewhere near 23100 at 2.49V. I seem to be missing the MSB but I cant find why ?
Anyone know what the problem is ? .. other than me.. !?
Code: |
#include <18F4620.h>
#device PASS_STRINGS=IN_RAM
#device *= 16;
#fuses HS, NOPROTECT, BROWNOUT, PUT, NOLVP, NODEBUG, MCLR
//#fuses NOWDT
#fuses WDT, WDT512 // 1024 etc. See 18F4620.h for details...
#use DELAY(CLOCK=40MHz, RESTART_WDT) // Modified so it restarts WDT./
#use RS232(BAUD=115200, XMIT=PIN_C6, RCV=PIN_C7, ERRORS, STREAM=USB, RESTART_WDT, BITS=8, PARITY=N, STOP=1)
#use RS232(BAUD=19200 , XMIT=PIN_C0, RCV=PIN_C1, ERRORS, STREAM=USB1, RESTART_WDT, BITS=8, PARITY=N, STOP=1)
#use SPI(MASTER, DO=PIN_C5, DI=PIN_C4, CLK=PIN_C3, MSB_FIRST, MODE=0, BITS=16, STREAM=SPI)
#use I2C(MASTER, SDA=PIN_A2, SCL=PIN_A3, FORCE_SW)
#include <string.h>
#include <stdlib.h>
#include <float.h>
#define VERBOSE 1
#define SILENT 0
#define ERASE 1
#define NO_ERASE 0
#define SETUP_PRESENT 0x62
#define FIFO_SIZE 12
#define WDT_LED PIN_D0
#define ADC_RESET PIN_D1
#define ADC_DRDY PIN_D2
#define EEPROM_CS PIN_D3
#define DS106_CS PIN_D4
#define AD7705_CS PIN_D5
#define AD7243_CS PIN_D6
//
// Pin D7 Space for MAX186 Chip Sel
#define RS232_TXD PIN_C0
#define CCP1_IN PIN_C1
#define CPP2_IN PIN_C2
#define ADC_CLK PIN_C3
#define ADC_DI PIN_C4
#define ADC_D0 PIN_C5
#define TXD PIN_C6
#define RXD PIN_C7
//
// PINS A2 and A3 are for I2C...
// AD7705 Calibration Mode Settings
//
#define ADC_NORMAL 0x00
#define ADC_SELF 0x40
#define ADC_ZERO_SCALE 0x80
#define ADC_FULL_SCALE 0xC0
// AD7705 Gain Settings
#define ADC_GAIN_1 0x00
#define ADC_GAIN_2 0x08
#define ADC_GAIN_4 0x10
#define ADC_GAIN_8 0x18
#define ADC_GAIN_16 0x20
#define ADC_GAIN_32 0x28
#define ADC_GAIN_64 0x30
#define ADC_GAIN_128 0x38
// AD7705 Polar Operations
#define ADC_BIPOLAR 0x04
#define ADC_UNIPOLAR 0x00
#define ADC_CORRECT 0x04
// AD7705 Update rates
#define ADC_50 0x04
#define ADC_60 0x05
#define ADC_250 0x06
#define ADC_500 0x07
typedef unsigned char BOOL ;
typedef unsigned char UINT8 ;
typedef unsigned int16 UINT16;
typedef unsigned int32 UINT32;
UINT16 read_adc_value(int1);
void write_adc_byte(BYTE data);
void setup_ad7705(BYTE, BYTE, BYTE, BYTE, BYTE, BYTE);
//***************************************************************************
void init_ad7705(int1 type)
{
output_low(ADC_RESET);
output_high(ADC_CLK);
output_high(AD7705_CS);
output_high(ADC_RESET);
fprintf(USB, "\r\n");
delay_ms(1000); fprintf(USB, "\r...Initialising AD7705 ADC : (3 Seconds)");
delay_ms(1000); fprintf(USB, "\r...Initialising AD7705 ADC : (2 Seconds)");
delay_ms(1000); fprintf(USB, "\r...Initialising AD7705 ADC : (1 Second) ");
if (type) // Used for calibration.
{ read_adc_value(0);
setup_ad7705(ADC_NORMAL, ADC_GAIN_1, 0x4, ADC_50, 0x2, 0x0); delay_ms(100);
setup_ad7705(ADC_ZERO_SCALE, ADC_GAIN_1, 0x4, ADC_50, 0x2, 0x1); delay_ms(100);
setup_ad7705(ADC_NORMAL, ADC_GAIN_1, 0x4, ADC_50, 0x0, 0x0); delay_ms(100);
fprintf(USB, "\r\n\n ");
read_adc_value(1);
setup_ad7705(ADC_NORMAL, ADC_GAIN_1, 0x4, ADC_50, 0x2, 0x0); delay_ms(100);
setup_ad7705(ADC_ZERO_SCALE, ADC_GAIN_1, 0x4, ADC_50, 0x2, 0x1); delay_ms(100);
setup_ad7705(ADC_NORMAL, ADC_GAIN_1, 0x4, ADC_50, 0x0, 0x0); delay_ms(100);
read_adc_value(1);
} // setup_wdt(WDT_ON);
}
//***************************************************************************
void setup_ad7705(BYTE calmode, BYTE gainsetting, BYTE operation, BYTE rate, BYTE fsync, BYTE buffered)
{ write_adc_byte(0x20); // Communications register
write_adc_byte(rate);
write_adc_byte(0x10); // Access setup register.
write_adc_byte(calmode|gainsetting|operation|fsync|buffered);
}
//***************************************************************************
// DESCRIPTION: Converts string pointed to by s to a float
// RETURN: Result of the conversion
// ALGORITHM: None
//***************************************************************************
// And now the functions for the ADC AD7705
void write_adc_byte(BYTE data)
{ BYTE i;
output_low(AD7705_CS);
for (i=1; i<=8;++i)
{ output_low(ADC_CLK);
output_bit(ADC_DI, shift_left(&data,1,0));
output_high(ADC_CLK);
} output_high(AD7705_CS);
}
//***************************************************************************
long int read_adc_word()
{ BYTE i;
long data;
output_low(AD7705_CS);
delay_us(20);
for (i=1;i<=16;++i) { output_low(ADC_CLK);
output_high(ADC_CLK);
shift_left(&data,2, input(ADC_D0));
} output_high(AD7705_CS);
return(data);
}
//***************************************************************************
UINT16 read_adc_value(int1 ch)
{
long long retries=0;
UINT16 value;
while (input(ADC_DRDY))
{ restart_wdt();
delay_us(100); // &&&&&&&& This used to be 100 uS.
if (retries++ > 0xfff)
{ // fprintf(USB, "\r\n ADC Timed Out !");
break;
}
};
if (ch) write_adc_byte(0x39);
else write_adc_byte(0x38);
if (retries >= 0xfff) return(0xffff);
value = read_adc_word();
return(value);
}
void main(void)
{
UINT16 adc;
init_ad7705(1);
while(1)
{
restart_wdt();
adc=read_adc_value(1);
if (adc == 0xffff) init_ad7705(0);
fprintf(USB, "\r\n ADC Value : %Lu", adc);
delay_ms(500);
}
} |
|
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Fri Mar 12, 2010 11:47 am |
|
|
You don't need to start a new thread every time you have something
different with the AD7705. Every time you add to the existing thread it
will move to the top. _________________ Google and Forum Search are some of your best tools!!!! |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri Mar 12, 2010 12:07 pm |
|
|
In bipolar mode, the full scale ouput range is 0x8000..0x7fff. so you dont' miss a MSB with an output in the range of 22000.
Furthermore it seems to me, that you you are performing a system zero calibration without providing zero input signal. |
|
|
ac34856
Joined: 14 Dec 2009 Posts: 33 Location: Wales
|
|
Posted: Sat Mar 13, 2010 6:19 am |
|
|
Apology for posting a similar thread.. running to a deadline I'm afraid and didnt think to check.
I changed the mode between BIPOLAR and UNIPOLAR but didnt get
anywhere incidentally .. but it appears I left it in BIPOLAR mode when
I posted the code.
I dont think that is the problem.. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Mar 14, 2010 3:38 am |
|
|
Quote: | I dont think that is the problem.. |
Clearly you won't get the expected output in bipolar mode. In so far it is a problem. The output coding in bipolar
mode is offset binary rather than two's complement, by the way. As I mentioned, your calibration scheme seems to
me dubious as well. Yes, I think, there are other problems too.
But I'm basically convinced, that you are able to figure it out. Many programmers have been using the various
ADI and other manufacturers ADC chips before and succeeded at last. Happy developing. |
|
|
ac34856
Joined: 14 Dec 2009 Posts: 33 Location: Wales
|
|
Posted: Sun Mar 14, 2010 7:53 am |
|
|
Well I see your point if it were working in bipolar mode but alas it isnt
working in offset binary format so I think the issue with the mode is that the mode command definitions must have an error - which were pointed out in other posts on this.
Will stick with it ... its amazing isnt it how stressful these things can become when working to a deadline and then how quickly they are forgotten about !
I guess we are in this game cos we must like it. |
|
|
ac34856
Joined: 14 Dec 2009 Posts: 33 Location: Wales
|
|
Posted: Sun Mar 14, 2010 7:55 am |
|
|
Postscript:
I believe that the AD7705 internally disconnects the input when it does
a zero calibration so assuming this is correct it shouldnt matter whats going on with the input pins so long as they are below 2.5V |
|
|
mindstorm88
Joined: 06 Dec 2006 Posts: 102 Location: Montreal , Canada
|
|
Posted: Sun Mar 14, 2010 8:32 am |
|
|
In Self-Calibration it is internally shorted, but for Zero-Scale System Calibration and Full-Scale System Calibration you must put proper signal at the inputs !!! Read datasheet carefully (page 18)!! |
|
|
ac34856
Joined: 14 Dec 2009 Posts: 33 Location: Wales
|
|
Posted: Sun Mar 14, 2010 10:42 am |
|
|
Well it sounds like I need to get reading again.
thanks |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Mar 14, 2010 12:05 pm |
|
|
Quote: | it sounds like I need to get reading again |
Yes. System zero calibration exactly means what the name says: A system (overall) calibration in contrast
to an internal self calibration. The latter does, what you apparently intended. |
|
|
ac34856
Joined: 14 Dec 2009 Posts: 33 Location: Wales
|
Fixed .. well sort of |
Posted: Wed Mar 24, 2010 1:25 pm |
|
|
Just in case anyone wondered what the outcome was, .. simple .. as I couldnt get it to read above 30,000 just multiply the output by 2 and add or subtract 1 periodically ..
Cheating yes but noone will ever know .. and I get to do something else ! |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|