On an AVR ATmega328P, once per second I am doing 3 AD conversions immediately following each other with 16x oversampling using SLEEP_MODE_ADC like this:
EMPTY_INTERRUPT(ADC_vect);
uint16_t getVoltage(uint8_t pin) {
ADMUX = (0b11110000 & ADMUX) | pin;
uint32_t overValue = 0;
for (uint8_t i = 0; i < 16; i++) {
sleep_mode();
overValue += ADC;
}
int16_t mV = (((overValue >> 2) * AREF_MV) >> 12);
return mV;
}
It works fine.
At the same time, I am generating a 4 kHz beep with a timer toggling an output pin, and I am reading and writing data over USART.
The beep has a short click once per second which looks like this:
And every now and then a character sent over USART gets garbled.
While I’d expect that the beep timer is put to sleep during AD conversion in order reduce internal noise, I didn’t quite expect USART tx/rx to be disturbed.
When I don’t use sleep mode and do AD conversions like this:
// sleep_mode();
ADCSRA |= (1 << ADSC);
loop_until_bit_is_clear(ADCSRA, ADSC);
the beep is “clean”, there are no more USART tx/rx issues, and after some extensive measuring, I am pretty sure the AD conversion results are just as accurate as they are with sleep mode.
So I am wondering about two things:
- Is it expected that USART tx/rx gets disturbed by
SLEEP_MODE_ADC? - Does sleep mode actually make sense in combination
with oversampling? Does some noise maybe not even help to increase
accuracy (dithering) or does that apply only to noise coming from
the sensors?