Yahoo Groups archive

AVR-Chat

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

Message

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

Attachments

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.