EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Glitches with ADC12 internal temperature sensor

Started by John Pitney October 6, 2012
Hi all,

I'm trying out the internal temperature sensor on an MSP430F449 with the
ADC12. Most of the samples I get are within a few counts of the median,
but some, maybe less than 10%, are 15 counts off, usually low. The MSP430
is on an Olimex development board, which seems to have all the recommended
power and reference capacitors. I suspect I'm doing something wrong in my
code, so I'd appreciate any pointers on where I'm going wrong.

//*****************************************************************************
// Olimex MSP430F449-STK
//*****************************************************************************
// Compiled with msp430-gcc-4.5.3 -Os -mmcu=msp430f449
// Example output (note 0x06AF and 0x06B5)
// 06C7 06C6 06C6 06C7 06C6 06C6 06C5 06C6
// 06C6 06C6 06C6 06C6 06C6 06AF 06C7 06C6
// 06C5 06C6 06B5 06C6 06C6 06C8 06C6 06C6
// 06C6 06C6 06C8 06C6 06C6 06C8 06C6 06C5

#include
#include
#include

#define N_RESULTS 8
static uint16_t ADCresult[N_RESULTS];

void tx(char c);
size_t tx_string(char * Buf, size_t Bufsize);
void itoa16(uint16_t x, char *s);

void main(void)
{
volatile int i;
char s;
WDTCTL = WDT_ADLY_250; // 250ms interval timer
FLL_CTL0 |= XCAP18PF; // Configure load caps
IE1 |= WDTIE; // Enable WDT interrupt
P4SEL |= 0x01 | 0x02; // P4.0,1 = USART1 TXD/RXD
ME2 |= UTXE1 + URXE1; // Enable USART1 TXD/RXD
U1CTL |= CHAR; // 8-bit character
U1TCTL |= SSEL1; // UCLK = SMCLK
U1BR0 = 0x6D; // 1MHz 9600
U1BR1 = 0x00; // 1MHz 9600
U1MCTL = 0x03; // modulation
U1CTL &= ~SWRST; // Initialize USART state
machine
IE2 |= URXIE1; // Enable USART1 RX interrupt
P4DIR |= 0x01; // P4.0 output direction
ADC12CTL0 = ADC12ON+REFON+REF2_5V+MSC+SHT0_10;
ADC12CTL1 = SHP+CONSEQ_1+ADC12DIV_7;
ADC12MCTL0 = INCH_10+SREF_1;
ADC12MCTL1 = INCH_10+SREF_1;
ADC12MCTL2 = INCH_10+SREF_1;
ADC12MCTL3 = INCH_10+SREF_1;
ADC12MCTL4 = INCH_10+SREF_1;
ADC12MCTL5 = INCH_10+SREF_1;
ADC12MCTL6 = INCH_10+SREF_1;
ADC12MCTL7 = INCH_10+SREF_1+EOS;
ADC12IE = 1 << 7;
ADC12CTL0 |= ENC;
for(;;) {
char buf[5];
ADC12CTL0 = ADC12ON+REFON+REF2_5V+MSC+SHT0_10;
ADC12CTL1 = SHP+CONSEQ_1;
ADC12CTL0 |= ENC;
for(i=0; i < 0x7200; i++) {
} // no-op delay for reference stabilization
ADC12CTL0 |= ADC12SC; // start conversion
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
// ADC12CTL0 &= !ADC12ON; // commented out, but problem
remains
s = ' ';
for(i = 0; i < N_RESULTS; i++) {
itoa16(ADCresult[i], buf);
tx_string(buf, 4);
tx(s);
}
s = '\n';
tx(s);
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
}
}

// Watchdog Timer interrupt service routine
__attribute__((interrupt(WDT_VECTOR)))
void watchdog_timer(void)
{
_BIC_SR_IRQ(LPM0_bits); // Back to active mode
}

__attribute__((interrupt(ADC12_VECTOR)))
void ADC12ISR(void) {
ADCresult[0] = ADC12MEM0;
ADCresult[1] = ADC12MEM1;
ADCresult[2] = ADC12MEM2;
ADCresult[3] = ADC12MEM3;
ADCresult[4] = ADC12MEM4;
ADCresult[5] = ADC12MEM5;
ADCresult[6] = ADC12MEM6;
ADCresult[7] = ADC12MEM7;
_BIC_SR_IRQ(LPM0_bits); // Back to active mode
}

Thanks,
John


Beginning Microcontrollers with the MSP430

Just wonder if the internal reference voltage was connected to a pin with external capacitor to AVss.

--- In m..., John Pitney wrote:
>
> Hi all,
>
> I'm trying out the internal temperature sensor on an MSP430F449 with the
> ADC12. Most of the samples I get are within a few counts of the median,
> but some, maybe less than 10%, are 15 counts off, usually low. The MSP430
> is on an Olimex development board, which seems to have all the recommended
> power and reference capacitors. I suspect I'm doing something wrong in my
> code, so I'd appreciate any pointers on where I'm going wrong.
>
> //*****************************************************************************
> // Olimex MSP430F449-STK
> //*****************************************************************************
> // Compiled with msp430-gcc-4.5.3 -Os -mmcu=msp430f449
> // Example output (note 0x06AF and 0x06B5)
> // 06C7 06C6 06C6 06C7 06C6 06C6 06C5 06C6
> // 06C6 06C6 06C6 06C6 06C6 06AF 06C7 06C6
> // 06C5 06C6 06B5 06C6 06C6 06C8 06C6 06C6
> // 06C6 06C6 06C8 06C6 06C6 06C8 06C6 06C5
>
> #include
> #include
> #include #define N_RESULTS 8
> static uint16_t ADCresult[N_RESULTS];
>
> void tx(char c);
> size_t tx_string(char * Buf, size_t Bufsize);
> void itoa16(uint16_t x, char *s);
>
> void main(void)
> {
> volatile int i;
> char s;
> WDTCTL = WDT_ADLY_250; // 250ms interval timer
> FLL_CTL0 |= XCAP18PF; // Configure load caps
> IE1 |= WDTIE; // Enable WDT interrupt
> P4SEL |= 0x01 | 0x02; // P4.0,1 = USART1 TXD/RXD
> ME2 |= UTXE1 + URXE1; // Enable USART1 TXD/RXD
> U1CTL |= CHAR; // 8-bit character
> U1TCTL |= SSEL1; // UCLK = SMCLK
> U1BR0 = 0x6D; // 1MHz 9600
> U1BR1 = 0x00; // 1MHz 9600
> U1MCTL = 0x03; // modulation
> U1CTL &= ~SWRST; // Initialize USART state
> machine
> IE2 |= URXIE1; // Enable USART1 RX interrupt
> P4DIR |= 0x01; // P4.0 output direction
> ADC12CTL0 = ADC12ON+REFON+REF2_5V+MSC+SHT0_10;
> ADC12CTL1 = SHP+CONSEQ_1+ADC12DIV_7;
> ADC12MCTL0 = INCH_10+SREF_1;
> ADC12MCTL1 = INCH_10+SREF_1;
> ADC12MCTL2 = INCH_10+SREF_1;
> ADC12MCTL3 = INCH_10+SREF_1;
> ADC12MCTL4 = INCH_10+SREF_1;
> ADC12MCTL5 = INCH_10+SREF_1;
> ADC12MCTL6 = INCH_10+SREF_1;
> ADC12MCTL7 = INCH_10+SREF_1+EOS;
> ADC12IE = 1 << 7;
> ADC12CTL0 |= ENC;
> for(;;) {
> char buf[5];
> ADC12CTL0 = ADC12ON+REFON+REF2_5V+MSC+SHT0_10;
> ADC12CTL1 = SHP+CONSEQ_1;
> ADC12CTL0 |= ENC;
> for(i=0; i < 0x7200; i++) {
> } // no-op delay for reference stabilization
> ADC12CTL0 |= ADC12SC; // start conversion
> _BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
> // ADC12CTL0 &= !ADC12ON; // commented out, but problem
> remains
> s = ' ';
> for(i = 0; i < N_RESULTS; i++) {
> itoa16(ADCresult[i], buf);
> tx_string(buf, 4);
> tx(s);
> }
> s = '\n';
> tx(s);
> _BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
> }
> }
>
> // Watchdog Timer interrupt service routine
> __attribute__((interrupt(WDT_VECTOR)))
> void watchdog_timer(void)
> {
> _BIC_SR_IRQ(LPM0_bits); // Back to active mode
> }
>
> __attribute__((interrupt(ADC12_VECTOR)))
> void ADC12ISR(void) {
> ADCresult[0] = ADC12MEM0;
> ADCresult[1] = ADC12MEM1;
> ADCresult[2] = ADC12MEM2;
> ADCresult[3] = ADC12MEM3;
> ADCresult[4] = ADC12MEM4;
> ADCresult[5] = ADC12MEM5;
> ADCresult[6] = ADC12MEM6;
> ADCresult[7] = ADC12MEM7;
> _BIC_SR_IRQ(LPM0_bits); // Back to active mode
> }
>
> Thanks,
> John
>
>

On Sat, Oct 6, 2012 at 10:07 PM, old_cow_yellow wrote:

> Just wonder if the internal reference voltage was connected to a pin with
> external capacitor to AVss.
>

Olimex seems to have followed TI's recommendations here, and they have 10uF
and 100nF capacitors connected to the VRef+ pin. I see 2.515V on the
positive terminal of the 10uF capacitor, and to the extent I can see with
my scope, it looks clean.

I just tried running my temperature sensor test program with the JTAG
debugger disconnected, just to see if that was causing the glitches, and
the behavior was unchanged.

Best regards,
John


Have you looked at the errata sheet?
http://www.ti.com/lit/er/slaz016d/slaz016d.pdf
There are a number of issues with the ADC12, perhaps one of them is the cause?

bob

--- In m..., John Pitney wrote:
>
> On Sat, Oct 6, 2012 at 10:07 PM, old_cow_yellow wrote:
>
> > Just wonder if the internal reference voltage was connected to a pin with
> > external capacitor to AVss.
> > Olimex seems to have followed TI's recommendations here, and they have 10uF
> and 100nF capacitors connected to the VRef+ pin. I see 2.515V on the
> positive terminal of the 10uF capacitor, and to the extent I can see with
> my scope, it looks clean.
>
> I just tried running my temperature sensor test program with the JTAG
> debugger disconnected, just to see if that was causing the glitches, and
> the behavior was unchanged.
>
> Best regards,
> John
>
>

Did you try to run the ADC12 based on ACLK to see if you get any better result?

Thanks,

John.

________________________________
From: rdunlop3428
To: m...
Sent: Sunday, October 7, 2012 4:28 PM
Subject: [msp430] Re: Glitches with ADC12 internal temperature sensor


 
Have you looked at the errata sheet?
http://www.ti.com/lit/er/slaz016d/slaz016d.pdf
There are a number of issues with the ADC12, perhaps one of them is the cause?

bob

--- In m..., John Pitney wrote:
>
> On Sat, Oct 6, 2012 at 10:07 PM, old_cow_yellow wrote:
>
> > Just wonder if the internal reference voltage was connected to a pin with
> > external capacitor to AVss.
> >
>
> Olimex seems to have followed TI's recommendations here, and they have 10uF
> and 100nF capacitors connected to the VRef+ pin. I see 2.515V on the
> positive terminal of the 10uF capacitor, and to the extent I can see with
> my scope, it looks clean.
>
> I just tried running my temperature sensor test program with the JTAG
> debugger disconnected, just to see if that was causing the glitches, and
> the behavior was unchanged.
>
> Best regards,
> John
>
>
>
>




On Sun, Oct 7, 2012 at 6:28 PM, rdunlop3428 wrote:

> Have you looked at the errata sheet?
> http://www.ti.com/lit/er/slaz016d/slaz016d.pdf
> There are a number of issues with the ADC12, perhaps one of them is the
> cause?

I did, but only just before your post. I don't see anything there that
sounds like my problem.

Best regards,
John


On Sun, Oct 7, 2012 at 7:32 PM, john Mcdonald wrote:

> Did you try to run the ADC12 based on ACLK to see if you get any better
> result?
>

I just tried ADC12SSEL set for ACLK and then SMCLK, with various clock
dividers, and still had the same result.

If I'm not mistaken, with ACLK at 32768 Hz with a crystal, the 30us minimum
sampling period of the temperature sensor should be satisfied with 4
ADC12CLK cycles (the default for SHT0x and SHT1x). However, it seemed like
I needed to increase the sample-and-hold time above that, or else all of
the readings were all over the place.

Thanks,
John


I haven't looked at your code, so I don't know if this is your issue, but if the external capacitors are present, you need to wait a while after turning on the internal reference before the ADC gives correct results.

--- In m..., John Pitney wrote:
>
> On Sat, Oct 6, 2012 at 10:07 PM, old_cow_yellow wrote:
>
> > Just wonder if the internal reference voltage was connected to a pin with
> > external capacitor to AVss.
> > Olimex seems to have followed TI's recommendations here, and they have 10uF
> and 100nF capacitors connected to the VRef+ pin. I see 2.515V on the
> positive terminal of the 10uF capacitor, and to the extent I can see with
> my scope, it looks clean.
>
> I just tried running my temperature sensor test program with the JTAG
> debugger disconnected, just to see if that was causing the glitches, and
> the behavior was unchanged.
>
> Best regards,
> John
>
>

I've used the MSP430 series for 6 years, and have always found the ADC to be noisy. I average at least 16 samples before using, and often it takes more samples averaged to get a reading which is repeatable. Sometimes I average 512 or 1024 samples.

I don't know if this is considered a defect, considering that the LSBs are typically in the microvolts. But anyway, it doesn't surprise me at all.

Lloyd

--- In m..., John Pitney wrote:
>
> Hi all,
>
> I'm trying out the internal temperature sensor on an MSP430F449 with the
> ADC12. Most of the samples I get are within a few counts of the median,
> but some, maybe less than 10%, are 15 counts off, usually low.

On Mon, Oct 8, 2012 at 12:25 PM, lslonim2 wrote:

> I've used the MSP430 series for 6 years, and have always found the ADC to be noisy. I average at least 16 samples before using, and often it takes more samples averaged to get a reading which is repeatable. Sometimes I average 512 or 1024 samples.
>
> I don't know if this is considered a defect, considering that the LSBs are typically in the microvolts. But anyway, it doesn't surprise me at all.

I've noticed the same thing, but I have only been using the MSP430 for
about 18 months and I have little experience with the A/Ds of other
micros.

I have noticed that for low frequency DC on the ADC10, a cap on the
input makes a huge difference.

Last month I was playing with the SD16 on the F2013 and I was only
able to achieve about 12 usable bits. Now, in all fairness, this was
single-ended on a breadboard. I have been meaning to move the circuit
over to proto-board, switch to differential input, and eliminate all
other circuitry to see just what is causing the noise, or whether it
is inherent to the F2013.

I have some AFE253s to fall back on if I cannot get enough bits from
the F2013. I am guessing that the separate analog supply will help a
lot with the noise.

But I am curious what you have been doing to get the noise out of your
circuits, and what has and hasn't worked for you...

-p.

Memfault Beyond the Launch