Skip to content

High Impedance analogRead #5646

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
rubberduck203 opened this issue Nov 28, 2016 · 3 comments
Closed

High Impedance analogRead #5646

rubberduck203 opened this issue Nov 28, 2016 · 3 comments

Comments

@rubberduck203
Copy link

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.

@cmaglie
Copy link
Member

cmaglie commented Nov 28, 2016

If you're measuring weak signals the hardware solution is to put an OPAMP between the source and the analog input.

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.

A simpler software trick is to do a fake analogRead to switch channel and put a delay before the real analogRead:

analogRead(0); // Switch MUX to channel 0 and discard the read
delay(1); // Wait for ADC S/H capacitor to charge
int chan0 = analogRead(0); // Read ADC

analogRead(1);
delay(1);
int chan1 = analogRead(1);

This way you don't need to change the core but you can keep all the changes into the sketch.

@rubberduck203
Copy link
Author

Thanks @cmagile. I'll keep that in mind the next time I come across this problem. Unfortunately, that would double my read time and I don't have that much to spare for this project.

Y'all can feel free to close. I mostly wanted to doc my work around for the community. Thanks for chiming in with other options.

@cmaglie
Copy link
Member

cmaglie commented Dec 21, 2016

Ok, thanks for your insights

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants