Skip to content

High Impedance analogRead #5646

@rubberduck203

Description

@rubberduck203

I'm not sure that this is a bug. It's likely by design, but I ran into an issue with analogRead() and high impedance input. This affects the Atmel 32U4, but may also affect other Atmel chips, I'm not sure. I mostly want to document the issue & work around here where people may find it.

It's known and documented that Atmel recommends an impedance of <10 kOhm input on the ADC circuit.
ATmega16U4/ATmega32U4 datasheet Section 24.7.1.

The issue behaves much like cross talk and manifests itself when rapidly switching between and reading different input channels. The common recommendation is to place a capacitor between the high impedance sensor and the analog input, but this isn't sensible for some applications.

This issue can be solved in software by using a small delay in between switching channels on the ADCMUX and starting the conversion. In fact, it seems that @damellis ran into this way back in 2009. There remains a commented out delay in the wiring_analog.c module.

// without a delay, we seem to read from the wrong channel
//delay(1);

reference

I imagine the delay was removed for performance reasons, similar to #3064, and should probably remain commented out. Although, some option/hook to allow for a configurable delay between changing channels and reading would be very nice to have, as the amount of delay you need to charge the ADC circuit's capacitor is dependent on the input impedance.

For any of these modes, you want to be sure that the S/H capacitor is engaged long enough for your signal to propagate. This is usually 4RC, where R is your source impedance, and C is the sum of all capacitances (MUX, S/H, PCB traces, etc.). For example, if you have a 10Mohm CDS photocell, and 6pF of PCB trace capacitance plus 14pF of ADC capacitance, you will have to wait 410Mohm20pF = 800us. One way to do that is to set ADMUX to your channel, enable the ADC, wait 800us, and then tell the ADC to sample.

http://www.openmusiclabs.com/learning/digital/atmega-adc/

The 32u4 datasheet (Section 24.7.1) also seems to imply that using differential input (#1256) could solve the apparent "crosstalk", but its unclear on how.


Workaround:

It's possible to override the core library's implementation for a specific project by copying the wiring_analog.c file from the Arduino installation directory (C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\wiring_analog.c) into your project and uncommenting the delay. The linker will pick up the modified file from the project. This allows you to change the behavior of analogRead() locally.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions