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?
CraigMessage
Noisy ADC lines
2004-05-11 by Craig Limber
Attachments
- No local attachments were found for this message.