This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

sd 16 not get accurate result

Other Parts Discussed in Thread: MSP430F4270, XTR116

i am useing msp430f4270 controller.in it i attech channel 2 a opamp amplifier to amplify voltage.i use sd16 channel 2 to meassure milivolts . i use calibration technique for nullify offset effect and linear equation for converting counts to milivolts. here i attech my code and snap of schematic.

here is my code

#include <msp430.h>


//#define Num_of_Results 50

/* Arrays to store SD16_A conversion results */
/* NOTE: arrays need to be global to */
/* prevent removal by compiler */
#define a 0x80
#define b 0x40
#define c 0x20
#define d 0x10
#define e 0x08
#define f 0x04
#define g 0x02
#define h 0x01
unsigned char common[4],n;
int i=0,mode=0,display,number1,test,y1,offset,dif;
int PW[4],digit=3,done=0,value[4],tp,amb_offset,ambient,cal_amb;
char list_mode,pass=0,zero1=0,cal1=0,cpass1=0;
unsigned char gain=1,dp=0,val_u1,y=0,val_k1,flag;
unsigned int val[4],x1=0,x2=0,crt;
double temp=0;
char blink=0;
unsigned int packed=0,dp_val=0,inp=0,gain_val;
unsigned int hex=0xFFFF,results,oldresult;
int zero_val,span_val,outlow_val,outhi_val,packed11=0,offset_val,temp_amb;
unsigned int calz_tc,cals_tc,clol_val,cloh_val,calz_rtd,cals_rtd,calz_mv,cals_mv,z1,s1;
unsigned int pass_val,input_val,old_val=0,pinput_val,oinput_val,input21;
long int input,sample1;
long int input2;
unsigned int results12[8];
long double val_a,val_b,k2;
volatile unsigned int refresh;
//long int avg[5];

void keyscan(void);
void delay(int i);
void adc(void);
void hex2bcd(void);
void number(void);
const char char_gen[] =
{ // definitions for digits
g,//a+b+c+d+e+f, // Displays "0"
a+d+e+f+g,//b+c, // Displays "1"
c+f,//a+b+d+e+g, // Displays "2"
f+e,//a+b+c+d+g, // Displays "3"
a+d+e,//b+c+f+g, // Displays "4"
b+e,//a+c+d+f+g, // Displays "5"
b,//a+c+d+e+f+g, // Displays "6"
d+e+f+g,//a+b+c, // Displays "7"
0,//a+b+c+d+e+f+g, // Displays "8"
e//a+b+c+d+f+g // Displays "9"
};


void main(void)
{
volatile unsigned int i; // Use volatile to prevent removal
// by compiler optimization

WDTCTL = WDTPW + WDTHOLD; // Stop WDT
FLL_CTL0 |= XCAP14PF; // Configure load caps
for (i = 0; i < 10000; i++); // Delay for 32 kHz crystal to
P2DIR = 0XFF; //port initialization
P5DIR = 0X1E;
P2SEL = 0X00;
P5SEL = 0X00;
P6SEL = 0X0F;
P1SEL = 0xFF; // stabilize
CCTL0 |= CCIE; // CCR0 interrupt enabled
CCR0 = 300;
TACTL = TASSEL_2 + MC_2+ID_3;

_BIS_SR(GIE);

SD16CTL = SD16REFON + SD16SSEL0 ;
for (i = 0; i < 0x3000; i++);
SD16AE = SD16AE6+ SD16AE7;
SD16CCTL0 |= SD16UNI;
SD16INCTL0 = SD16INCH_2 + SD16INTDLY_0+SD16GAIN_2;
SD16CCTL0 |= SD16SC;

_EINT();

while(1)
{
if(flag)
adc();



}
}

void keyscan(void)
{
int key1=0xFF;
P6DIR = 0X0F;
P6SEL = 0X0F;
key1 = P6IN;
key1 = key1 & 0xF0;
key1 = key1 >> 4;

switch(key1)
{
case 0xE: //Mode key
delay(500);
key1 = P6IN;
key1 = key1 & 0xF0;
key1 = key1 >> 4;
if(key1==0xE)
{
delay(500);
while(key1==0xE)
{
key1 = P6IN;
key1 = key1 & 0xF0;
key1 = key1 >> 4;
}
calz_mv=input;
}
break;

case 0xD: // Enter key
delay(500);
key1 = P6IN;
key1 = key1 & 0xF0;
key1 = key1 >> 4;
if(key1==0xD)
{

while(key1==0xD)
{
key1 = P6IN;
key1 = key1 & 0xF0;
key1 = key1 >> 4;
}
cals_mv=input;
}


break;
}




}

void adc(void)
{
unsigned int i,sample=0;

kk: sample=0;

val_a=0;
val_b=0; // Use volatile to prevent removal
flag=0;
sample1=0;
input=0;
y1=0;
k2=0;


adc1: while ((SD16CCTL0 & SD16IFG)==0); // Poll interrupt flag
results = SD16MEM0;

results12[0]=results;

for(i=0;i<8;i++)
{
val_a=val_a+(results12[i]/8);

}

input=val_a;

keyscan();

val_a=cals_mv-calz_mv;
val_b=input-calz_mv;
val_b=24000*val_b;
val_a=val_b/val_a;
val_a=1000+val_a;
input=val_a;
input=input+offset_val;


if(input<=9999)
{
dp_val=3;
}
if(input>9999)
{
input=input/10;
dp_val=2;
}


hex2bcd();
number();
for(i=7;i>0;i--)
{
results12[i]=results12[i-1];
}



}
void delay(int i)
{
while(i!=0)
{
i--;
}
}

void hex2bcd(void)
{
unsigned int dummy;
temp=input;
if(temp<0)
{
hex=input*(-1);
}
else
{
hex=input;
}
if( (mode==0 && input > 0x270F) || (cal1==1 || cal1==2) )
{
dummy=hex/0x2710;
hex=hex%0x2710;
dummy = dummy<<12;
input=dummy;

dummy=hex/0x3E8;
hex=hex%0x3E8;
dummy = dummy<<8;
input=input + dummy;

dummy=hex/0x64;
hex=hex%0x64;
dummy = dummy<<4;
input = input + dummy;

dummy=hex/0xA;
hex=hex%0xA;
dummy = dummy<<0;
input = input + dummy;
}


else
{
dummy=hex/0x3E8;
hex=hex%0x3E8;
dummy = dummy<<12;
input=dummy;

dummy=hex/0x64;
hex=hex%0x64;
dummy = dummy<<8;
input = input + dummy;

dummy=hex/0xA;
hex=hex%0xA;
dummy = dummy<<4;
input = input + dummy;

dummy=hex;
input = input + dummy;
}
if(temp<0)
{
input=input*(-1);
}
}

void number(void)
{
unsigned int j;
//hex2bcd();

if(input>=0)
{
j= input & 0x000F; // Last character fatch
common[3] = char_gen[j];

j= input & 0x00F0; // Last character fatch
j= j>>4;
common[2] = char_gen[j];

j= input & 0x0F00; // Last character fatch
j= j>>8;
common[1] = char_gen[j];

j= input & 0xF000; // Last character fatch
j= j>>12;
common[0] = char_gen[j];
}
if(input<0)
{
input=input*(-1);

j= input & 0x000F; // Last character fatch
common[3] = char_gen[j];

j= input & 0x00F0; // Last character fatch
j= j>>4;
common[2] = char_gen[j];

j= input & 0x0F00; // Last character fatch
j= j>>8;
common[1] = char_gen[j];

common[0]=g;
}

}

// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
int j;

refresh++;
if(refresh==600)
{
flag=1;
refresh=0;
}

if(display!=3 && display > 3)
{
display=0;
}

P5OUT = 0XFF;
switch(display)
{
case 0:
j=0; // Last character fatch
if(dp_val==3)
{
P2OUT = common[j];
}
else
{
P2OUT = common[j]+h;
}
P5OUT = 0X10;
display++;


break;

case 1:
j=1; // 3rd character fatch
if(dp_val==2)
{
P2OUT = common[j];
}
else
{
P2OUT = common[j]+h;
}
P5OUT = 0X08;
display++;


break;

case 2:
j=2; // 2nd character fatch
if(dp_val==1)
{
P2OUT = common[j];
}
else
{
P2OUT = common[j]+h;
}
P5OUT = 0X04;
display++;


break;
case 3:
j=3; // Last character fatch
if(dp_val==0)
{
P2OUT = common[j];
}
else
{
P2OUT = common[j]+h;
}
P5OUT = 0X02;
display++;


break;
}
CCR0 += 250;


}

i attech 100nf capactior to vref pin and giving voltage useing presice yokogava calibration source

problem is that when i calculate milivolts from counts not get reliable results.

i calibrate for zer0=1milivolts

                      span=25milivolts;

as you can see from code.

i does this practice because i want to display temperature from thermocouple milivolts.

i spent 2-3 days and gone through various posts but unable to solve my problem........ please help me i am tired from this sd16 because its counts is so fluctuing so i have to implement running average methode

here i not attech r24 and shorted -tca to agand

now i am giving 5.260mv and reading on my led display is 5.217mv

  • You are mixing Analogue ground with Digital ground, R18 & C11 are on the same ground as the Op-Amp and is probably your digital ground too.

    Why you are using a separate Op-Amp to amplify and not the build-in PGA which gives up to 0.286uV/bit (Unipolair)?

    And if an Op-Amp then I would recommend the ‘Two Op-Amp Differential Amplifier’.

    The SD16 Negative Input must be connected directly and separate from other GND signals to the sensor GND (or via the Op-Amp).

  • thank you so much for reply.....................

    i mix analog and digital ground only at one point near xtr116 ic i have used in my ckt.i also want to generate 4-20 transmitter so i used xtr116 ic and for that i mix both ground near its iret pin otherwise both ground is different in ckt they mix only at junction

    second thing is it really affect that i connect A2- to nearby analog ground because on back side there is large solid copper poring area ? in my pcb A2- is directily connected to backside copper pouring.

    can you explain why you prefer 2 stage differential amplifier i mean how its help me to resolve my problem?

  • I’m not so good in analogue explanations, but I’ll try;

    Both +/- inputs of the SD should directly be connected to the sensor, these connections should carry only the current from the sensor and no other. If you need to ground the sensor (in most cases) then ground it close as possible at the sensor side (at board terminal is Ok), directly or via a small resistor.

    An analogue copper-poor is dangerous. It can pick-up easily noise from your digital connections at the opposite side of the board.

    An Op-Amp has a little input offset voltage, in a single configuration you are missing this. An Op-Amp can take a lot of current, if its GND is connected in/at your – input line you get a DC offset in your connection and also a lot of noise. A Differential Op-Amp compensates the input offset and isolates the +/- signals from Vcc or GND.

  • Leo Bosch said:

    Both +/- inputs of the SD should directly be connected to the sensor, these connections should carry only the current from the sensor and no other. If you need to ground the sensor (in most cases) then ground it close as possible at the sensor side (at board terminal is Ok), directly or via a small resistor.

    This illustrates the idea quite well: http://en.wikipedia.org/wiki/Four-terminal_sensing

    Key of all this is excerpt from particular wiki article: "The accuracy of the technique comes from the fact that almost no current flows in the sense wires, so the voltage drop V=RI is extremely low."

  • Thanks, this is a good explanation of one of the problems.

    Another is, when the connection wires are not identical a small voltage difference as result of the thermocouple effect can occur.

  • here is cro waveform between A2+and A2- channel. i give 2mv input and gain of opamp stage is 11 .

    volts/div is 10mv

    now below wave form is between agand provided to A2- channel and another ground on pcb

    setting volts/div 2mv

  • This kind of measurements are quite difficult. You need a scoop with high sample rate, very good probes and the knowledge how to do. But anyhow you see a lot of noise at AGND approx 2mV and a lot of spikes >30mV, and that’s only the visual part.

    Your Op-Amp has a gain of 11, your PGA 2, in total 22. This mains a resolution of 0.416uV/bit and a full-scale of 27.27mV.

    My recommendation: Lift SD-A2- from PCB and connect directly to Sensor- and from here a wire to MCU-AVss, remove C6 & C11. And try what’s happening.

**Attention** This is a public forum