Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Thread

Noisy ADC lines

Noisy ADC lines

2004-05-11 by Craig Limber

Hi there;

I am having a wee bit of trouble with a noisy analog to digital conversion
setup and was wondering if anyone out there could suggest some things
to try to clean it up.

The processor is a Mega32 running at 8 MHz with a crystal.  Power is
regulated 5 volts from a battery.  The circuit has a very generous
supply of bypass and filter capacitors.  A 'scope on the power and ADC
lines doesn't show any noise that it can detect.  I am using the LC
circuit the manual recommends for the AVCC and it's voltage measures
the same as that found on the chip's VCC lines.  I have a .1uf disk cap
going from AREF to ground but nothing else since I am using the
Internal voltage reference.  All other aspects of the circuit work as I
expect.  No motors or other inductive loads are currently in use or
hooked up.  I am using avr-libc and gcc.

The sensors I am trying to read are Sharp GP2D120 4-30cm infrared
range sensors.  I have four.  If I read just one on any channel the
signal is clean and consistent.  As soon as I try to multiplex them I
run into trouble.  The values keep jumping about plus or minus about
half a volt around the reading I expect to get.  It is so wild that
even a routine to average out the results isn't good enough.  The
sensors are powered all the time.  I switch channels once every 100
milliseconds and don't try to get the first reading until 500
milliseconds after poweron.  The sensors themselves are getting a good,
well filtered 5 volt power from the same source that powers the rest of
the circuit.

I am using the interrupts to handle conversion.

Here is my setup code:

// global variables
uint8_t curchannel = 0, // the current channel I want to read
        doingadc = 0,   // don't start new conversion before previous done
        adchannel[4];   // where to store the results

  ADMUX = _BV(ADLAR)     // left justify result; 8 bits good enough
        | _BV(REFS0)     // AREF has external capacitor
        | _BV(REFS1);    // use internal 2.56 volt reference
  ADCSRA = _BV(ADEN)     // enable ADC doodad
         | _BV(ADIE);    // enable ADC interrupt

// using minimum prescaler of 2

So, once every 100 milliseconds I do this:

if (!doingadc)
{
  if (curchannel & 0x01) sbi(ADMUX, MUX0); else cbi(ADMUX, MUX0);
  if (curchannel & 0x02) sbi(ADMUX, MUX1); else cbi(ADMUX, MUX1);
  if (curchannel & 0x04) sbi(ADMUX, MUX2); else cbi(ADMUX, MUX2);
  doingadc = 1;
  sbi(ADCSRA, ADSC);  // start conversion
  curchannel++;       // prepare for next one
  if (curchannel == 4)
    curchannel = 0;
}
else
  error("started new conversion before previous one was done");

Here is my signal routine:

SIGNAL(SIG_ADC)
{
  adchannel[curchannel] = ADCH;
  doingadc = 0;
}

If I insert a statement to set curchannel to a fixed value instead 
of incrementing it then it works.  As soon as I try to read from
more than one channel after another the noise comes in.  The pins 
in use have no other purposes and are not used as outputs or have
the internal pullup resistors activated.  I have low-pass filters
attached to the ADC input pins that I can enable/disable with jumpers.
I tried going to a direct connection as well but that didn't make any
difference that I could see.  I tried shielding and/or twisting the
cables to the sensors but that didn't help either.

The doingadc variable is just a way to test that I am not trying to 
start a new conversion before the last one was finished.   I tried
using the ADC sleep mode to help with noise but no joy there.

So, I am stumped and scratching my head.  Any suggestion on how I can 
clean it up?

Craig

Re: [AVR-Chat] Noisy ADC lines

2004-05-11 by Mike Murphree

Craig Limber said:
>
> Hi there;
>
> I am having a wee bit of trouble with a noisy analog to digital
> conversion setup and was wondering if anyone out there could suggest
> some things to try to clean it up.

I didn't see anything in your code that allowed some settling time
after you switched the mux...

I might suggest the sequence to eliminate a redundant delay:

1 - Start conversion
2 - Read result
3 - Switch mux
4 - Wait 100 ms
5 - Repeat

Mike

Re: [AVR-Chat] Noisy ADC lines

2004-05-11 by David VanHorn

At 10:49 AM 5/11/2004 -0600, Craig Limber wrote:


>Hi there;
>
>I am having a wee bit of trouble with a noisy analog to digital conversion
>setup and was wondering if anyone out there could suggest some things
>to try to clean it up.
>
>The processor is a Mega32 running at 8 MHz with a crystal.  Power is
>regulated 5 volts from a battery.  The circuit has a very generous
>supply of bypass and filter capacitors.  A 'scope on the power and ADC
>lines doesn't show any noise that it can detect.

AC couple, at about 1mV/Div. Your ADC is 10 bit, so that's 1mV per volt on AREF, per ADC count.

>  I am using the LC
>circuit the manual recommends for the AVCC and it's voltage measures
>the same as that found on the chip's VCC lines.  I have a .1uf disk cap
>going from AREF to ground 


Which ground?

> As soon as I try to multiplex them I
>run into trouble.  The values keep jumping about plus or minus about
>half a volt around the reading I expect to get. 

Key point. IIRC you're supposed to toss the conversion immediately after a channel change.
I've done this by using an int to roll through the channels, changing the channel before starting the next conversion.

I seem to remember there's a finite time that you have to wait after an ADMUX selection, for the mux output amplifier to settle, as well.

Re: [AVR-Chat] Noisy ADC lines

2004-05-11 by Bruce Parham

Craig,

I am currently using the code below to run the ADC on an 'M128 with external mux'es to expand
the system to 42 channels. The whole mess is scanned once per second (without putting the
cpu to sleep) and I'm only seeing +/- one bit of noise. Each mux input has a 10K/.1uF RC filter
and all of the filters and mux'es are (SMT) mounted on the top of the board right next to the
'M128 and are over and connected only to an isolated ground plane (1st inner layer below the top)
that is connected to the AGND pin. To my amazement, this setup worked so well that I didn't need 
to do noise canceling.


	// setup the muxes for a conversion
	// vp points to the target channel

	void set_mux(struct VOLT_SRC * vp)
	{
	    static BYTE last_iic_addr = 0;
	    BYTE cur_iic_addr;
    
	    cur_iic_addr = vp->iic_addr;
    
	    ADMUX = (ADMUX & 0xf8) | (vp->amux_addr);
    
	    if(last_iic_addr != cur_iic_addr)   // if current is different chip
	        iic_set_mux(last_iic_addr, 0);  // disable last
        
	    iic_set_mux(cur_iic_addr, vp->lmux_addr | 0x08);
    
	    last_iic_addr = cur_iic_addr;
	}

	// measure all analog voltages

	void scan_analog(void)
	{
	    BYTE i;
	    int val;
    
	    for(i = 0; i < CH_COUNT; ++i)
	    {
	        set_mux(&volts[i]);                 // set the mux'es
	        while(ADCSRA & (1 << ADSC));        // wait for ADC idle
	        ADCSRA |= (1 << ADSC);              // start new conversion
	        while(ADCSRA & (1 << ADSC));        // wait for conversion done
	        val  = ADCL;                        // Read 8 low bits first (important)
	        val |=((int)ADCH << 8) | 0x8000;    // 2 high bits and new value bit
	        adc_Val[i] = (VWORD) val;
	    }
	}



> Here is my signal routine:
>
> SIGNAL(SIG_ADC)
> {
>   adchannel[curchannel] = ADCH;
>   doingadc = 0;
> }

The 'M128 ADC must be read low byte first in order to latch the upper bits into a temp register.
I haven't checked the 'M32 data sheet but I suspect the same restrictions apply.

Hope this helps.

Bruce

Re: [AVR-Chat] Noisy ADC lines

2004-05-11 by David VanHorn

At 12:38 PM 5/11/2004 -0700, Bruce Parham wrote:

>Craig,
>
>I am currently using the code below to run the ADC on an 'M128 with external mux'es to expand
>the system to 42 channels. The whole mess is scanned once per second (without putting the
>cpu to sleep) and I'm only seeing +/- one bit of noise. Each mux input has a 10K/.1uF RC filter
>and all of the filters and mux'es are (SMT) mounted on the top of the board right next to the
>'M128 and are over and connected only to an isolated ground plane (1st inner layer below the top)
>that is connected to the AGND pin. To my amazement, this setup worked so well that I didn't need 
>to do noise canceling.

This is pretty typical in my experience, just beware the "precision" reference on chip.
2.7V for a 2.5V reference, into a 10 bit ADC, is pretty funny, in my opinion.

Re: [AVR-Chat] Noisy ADC lines

2004-05-11 by Bruce Parham

David VanHorn wrote:
> 
> At 12:38 PM 5/11/2004 -0700, Bruce Parham wrote:
> 
> >Craig,
> >
> >I am currently using the code below to run the ADC on an 'M128 with external mux'es to expand
> >the system to 42 channels. The whole mess is scanned once per second (without putting the
> >cpu to sleep) and I'm only seeing +/- one bit of noise. Each mux input has a 10K/.1uF RC filter
> >and all of the filters and mux'es are (SMT) mounted on the top of the board right next to the
> >'M128 and are over and connected only to an isolated ground plane (1st inner layer below the top)
> >that is connected to the AGND pin. To my amazement, this setup worked so well that I didn't need
> >to do noise canceling.
> 
> This is pretty typical in my experience, just beware the "precision" reference on chip.
> 2.7V for a 2.5V reference, into a 10 bit ADC, is pretty funny, in my opinion.

No kidding! This is at the top of the ADC module:


  	// adc "precision" ref correction value in EEPROM

	#pragma data:eeprom

	//double  Ref_Cal_Val = 1.071094;     // Bd #1 = 2.742V
	double  Ref_Cal_Val = 0.9921875;     // Bd #2 = 2.540V

	#pragma data:data


Bruce

Re: [AVR-Chat] Noisy ADC lines

2004-05-11 by David VanHorn

>
>> This is pretty typical in my experience, just beware the "precision" reference on chip.
>> 2.7V for a 2.5V reference, into a 10 bit ADC, is pretty funny, in my opinion.
>
>No kidding! This is at the top of the ADC module:
>
>
>        // adc "precision" ref correction value in EEPROM
>
>        #pragma data:eeprom
>
>        //double  Ref_Cal_Val = 1.071094;     // Bd #1 = 2.742V
>        double  Ref_Cal_Val = 0.9921875;     // Bd #2 = 2.540V
>
>        #pragma data:data


In my case, when I discovered this, I had to add an external reference.
Now this meant that the external reference would be a hand-add until the new PCBs became available, so I had to check wether the external PRECISION reference was present by checking it against the internal "precision" reference..  

Isn't development fun?

Re: [AVR-Chat] Noisy ADC lines

2004-05-11 by John Johnson

You might lookup how to sleep while the conversion is being done,
this reduces noise. The ADC interrupt will wake you up
when it has completed.

Regards,
   JJ
Show quoted textHide quoted text
On Tuesday, May 11, 2004, at 12:49 PM, Craig Limber wrote:

>
> Hi there;
>
> I am having a wee bit of trouble with a noisy analog to digital  
> conversion
> setup and was wondering if anyone out there could suggest some things
> to try to clean it up.
>
> The processor is a Mega32 running at 8 MHz with a crystal.  Power is
> regulated 5 volts from a battery.  The circuit has a very generous
> supply of bypass and filter capacitors.  A 'scope on the power and ADC
> lines doesn't show any noise that it can detect.  I am using the LC
> circuit the manual recommends for the AVCC and it's voltage measures
> the same as that found on the chip's VCC lines.  I have a .1uf disk cap
> going from AREF to ground but nothing else since I am using the
> Internal voltage reference.  All other aspects of the circuit work as I
> expect.  No motors or other inductive loads are currently in use or
> hooked up.  I am using avr-libc and gcc.
>
> The sensors I am trying to read are Sharp GP2D120 4-30cm infrared
> range sensors.  I have four.  If I read just one on any channel the
> signal is clean and consistent.  As soon as I try to multiplex them I
> run into trouble.  The values keep jumping about plus or minus about
> half a volt around the reading I expect to get.  It is so wild that
> even a routine to average out the results isn't good enough.  The
> sensors are powered all the time.  I switch channels once every 100
> milliseconds and don't try to get the first reading until 500
> milliseconds after poweron.  The sensors themselves are getting a good,
> well filtered 5 volt power from the same source that powers the rest of
> the circuit.
>
> I am using the interrupts to handle conversion.
>
> Here is my setup code:
>
> // global variables
> uint8_t curchannel = 0, // the current channel I want to read
>         doingadc = 0,   // don't start new conversion before previous  
> done
>         adchannel[4];   // where to store the results
>
>   ADMUX = _BV(ADLAR)     // left justify result; 8 bits good enough
>         | _BV(REFS0)     // AREF has external capacitor
>         | _BV(REFS1);    // use internal 2.56 volt reference
>   ADCSRA = _BV(ADEN)     // enable ADC doodad
>          | _BV(ADIE);    // enable ADC interrupt
>
> // using minimum prescaler of 2
>
> So, once every 100 milliseconds I do this:
>
> if (!doingadc)
> {
>   if (curchannel & 0x01) sbi(ADMUX, MUX0); else cbi(ADMUX, MUX0);
>   if (curchannel & 0x02) sbi(ADMUX, MUX1); else cbi(ADMUX, MUX1);
>   if (curchannel & 0x04) sbi(ADMUX, MUX2); else cbi(ADMUX, MUX2);
>   doingadc = 1;
>   sbi(ADCSRA, ADSC);  // start conversion
>   curchannel++;       // prepare for next one
>   if (curchannel == 4)
>     curchannel = 0;
> }
> else
>   error("started new conversion before previous one was done");
>
> Here is my signal routine:
>
> SIGNAL(SIG_ADC)
> {
>   adchannel[curchannel] = ADCH;
>   doingadc = 0;
> }
>
> If I insert a statement to set curchannel to a fixed value instead
> of incrementing it then it works.  As soon as I try to read from
> more than one channel after another the noise comes in.  The pins
> in use have no other purposes and are not used as outputs or have
> the internal pullup resistors activated.  I have low-pass filters
> attached to the ADC input pins that I can enable/disable with jumpers.
> I tried going to a direct connection as well but that didn't make any
> difference that I could see.  I tried shielding and/or twisting the
> cables to the sensors but that didn't help either.
>
> The doingadc variable is just a way to test that I am not trying to
> start a new conversion before the last one was finished.   I tried
> using the ADC sleep mode to help with noise but no joy there.
>
> So, I am stumped and scratching my head.  Any suggestion on how I can
> clean it up?
>
> Craig
>
>
> ------------------------ Yahoo! Groups Sponsor  
> ---------------------~-->
> Make a clean sweep of pop-up ads. Yahoo! Companion Toolbar.
> Now with Pop-Up Blocker. Get it for free!
> http://us.click.yahoo.com/L5YrjA/eSIIAA/yQLSAA/dN_tlB/TM
> --------------------------------------------------------------------- 
> ~->
>
>
> Yahoo! Groups Links
>
>
>
>
>

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.