Pages: [1]   Go Down
Author Topic: Delay in analogRead after switching pin  (Read 2501 times)
0 Members and 1 Guest are viewing this topic.
United Kingdom
Offline Offline
Tesla Member
***
Karma: 224
Posts: 6593
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Several users of the forum have hit the problem that if you do an analogRead from a pin driven from a high impedance source, and you previously read a different pin, then the value returned by analogRead is wildly inaccurate. I suggest the following changes:

- declare a new variable "static unsigned int analogReadDelay = 100;" in wiring_analog.c

- modify analogRead to call "delayMicroseconds(analogReadDelay)" between setting the multiplexer and starting the conversion (there is already a commented-out "delay(1);" call in the code at this location, see wiring_analog.c(64))

- add new function "void setAnalogReadDelay(unsigned int amount){ analogReadDelay = amount; }". Most users won't need to call this function, but it can be used to increase or reduce the delay if needed.

- fix the bug that "delayMicroseconds(0)" delays for a very long time instead of a minimal time, so that "setAnalogReadDelay(0)" works properly.

Possible improvements on this scheme:

1. Make the delay call only if a different pin was read last time.

2. Allow the delay to be set on a per-pin basis.

I have suggested 100 microseconds as the default delay, but other folks may have a better idea of what is needed e.g. when reading from a LM35 temperature sensor.

Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 202
Posts: 8719
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Perhaps copying this section from the ATmega datasheet would cover the problem of people using high impedance sources:

"The ADC is optimized for analog signals with an output impedance of approximately 10 kΩ or less. If such a source is used, the sampling time will be negligible. If a source with higher imped- ance is used, the sampling time will depend on how long time the source needs to charge the S/H capacitor, with can vary widely. The user is recommended to only use low impedance sources with slowly varying signals, since this minimizes the required charge transfer to the S/H capacitor."
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

United Kingdom
Offline Offline
Tesla Member
***
Karma: 224
Posts: 6593
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

johnwasser, I know what the datasheet says, but do you really expect everyone using a source with an impedance greater than 10K to buffer the signal? I would hazard a guess that a majority, or at least a substantial minority, of Arduino users connect sources with an impedance >10K to analog input pins. The forum is full of posts in which users have connected temperature sensors (other than thermocouples), LDRs, and phototransistors (with pullup resistors > 10k) to the analog input pins. It's simply not necessary to buffer the signal when reading a *slowly varying* signal such as provided by these types pof sensor, provided that sufficient delay is allowed between setting the mux and initiating the conversion.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 525
Posts: 26554
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Doesn't reading an input twice & ignoring the first read usually solve the problem?
Things like temperatures aren't changing all that  fast.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17263
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is also analogRead() inaccuracies after one first changes the reference source for the ADC function (to external Aref pin, to band-gap, etc). Typically the first value returned is pretty much garbage and somewhere it was recommended to do a 'dummy' read before performing a valid analogRead() function. I think this might also be independent of if the analog voltage has < 10k source impedenace, or which analog channel was last read from, but not positive about that.

 I've always considered the AVR's built-in 10 bit ADC function as very handy and useful, but not to be confused with instrumentation quality ADC devices. My current favorite is the TI ADS1115 16 bit I2C, 2 diff or 4 SE channels, five programmable input ranges, built in comparitor with digital output pin, works with either 3.3 or 5vdc systems, up to 860SPS, has internal reference voltage source, small as a baby asprin. Lot of bang for a $15 break-out module.
  http://www.ti.com/lit/ds/symlink/ads1115.pdf
  
http://www.ebay.com/itm/230619695873?ssPageName=STRK:MEWAX:IT&_trksid=p3984.m1423.l2649

Lefty

 
« Last Edit: August 18, 2011, 12:19:17 pm by retrolefty » Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 224
Posts: 6593
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Crossroads,

Yes, reading the pin twice and discarding the first reading does usually solve the problem. But many users facing this situation don't know they need to do that.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

United Kingdom
Offline Offline
Tesla Member
***
Karma: 224
Posts: 6593
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I've just seen YET ANOTHER post relating to this problem, see http://arduino.cc/forum/index.php/topic,69742.0.html. That's the 4th post I've seen by a user experiencing this problem, and I only joined the forum about 2 weeks ago. Anything that's causing this much trouble for Arduino users needs to be addressed, preferably in the software, or failing that in the documentation.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 525
Posts: 26554
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sure, but then how would we run up our post counts smiley-wink

= vs == also comes a lot.

Very many posters just dive in & ask questions without browsing the playground first; if they did that first (or were even aware that it exists it seems) that would resolve a lot of things.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17263
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've just seen YET ANOTHER post relating to this problem, see http://arduino.cc/forum/index.php/topic,69742.0.html. That's the 4th post I've seen by a user experiencing this problem, and I only joined the forum about 2 weeks ago. Anything that's causing this much trouble for Arduino users needs to be addressed, preferably in the software, or failing that in the documentation.

Well it is certainly a balancing act. We see many inexperienced people having trouble reading even simple push button switches using digitalRead() because they don't yet understand the concept of a 'floating input pin'. Does that mean the digitMode command should automatically enable the internal pull-up resistor when set to input mode?  I would think that trying to make the analogRead function fool proof for all possible problems would either be not effective or hamper the basic performance of the function.

 Still a very interesting topic. I recall a year or so ago where Coding Badly was helping me work out a method such that an arduino sketch could actually measure the voltage value of it's Vcc pin without any external wiring or components. Very useful function if you wish to have 'dynamic' calibration/correction capabilities, where you might be running on battery voltage which decreases voltage over time.

Lefty
Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 224
Posts: 6593
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Crossroads, my aim is indeed to reduce your post counts! smiley-grin (that wouldn't be such a bad thing, because I find the forum to be rather slow in responding compared to other sites). The = vs == issue is a defect in the C language, which we can't do much about (although good C/C++ programmers generally turn on enough compiler warnings to pick up accidental use of = where == was intended).

Lefty, not enabling pullups when they are needed is an issue of understanding basic electronics, not a limitation of the chip. But the need for a delay between switching pins and reading the ADC is a feature of the microcontroller. That is why I think it deserves to have a workaround built in to the Arduino software.

I'm going to experiment with various analogue signal source resistances to see what delay is needed.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
- fix the bug that "delayMicroseconds(0)" delays for a very long time instead of a minimal time, so that "setAnalogReadDelay(0)" works properly.
reported some time ago - http://code.google.com/p/arduino/issues/detail?id=576 -  

Fix proposed - http://arduino.cc/forum/index.php/topic,68383.msg504892.html#msg504892 -


I do not prefer the delay as a solution. I would rather encapsulate the analog port in a class that supports asynchronuous behaviour, a bit of

void AnalogPort[pin].request();
boolean AnalogPort[pin].ready();
int AnalogPort[pin].read();


In that way you can do something usefull while waiting for the conversion.


Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17263
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I'm going to experiment with various analogue signal source resistances to see what delay is needed.

A worthwhile effort I would say. You might consider using two analog inputs as best case source impedance wired to ground and +5vdc respectively, and then a third analog input pin could be your source impedance pin under test.

Lefty
Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 224
Posts: 6593
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

OK, this is the test setup I used:

Pin A0 connected to GND via resistance R
Pin A1 connected to +5 via resistance R
Read and store A0 10 times in a tight loop, then send the values to the serial port, then delay. Repeat for A1. Then start again.

Ideally I'd have read a pin driven by a variable voltage in case the above doesn't give worst-case conditions. I may try that when I have more time.

Using the standard Arduino software:

With R=10K: the readings are stable, 0 and 1023 every time.
With R=100K: the +5 pin sometimes reads as low as 1017 the first time, otherwise it is 1023. The GND pin always reads zero.
With R=1M: the GND pin may read as high as 345 on the first reading but reads 0 by the 4th reading. The 5v pin may read as low as 664 on the first reading but reads 1022 by the 5th reading, and often never reaches 1023 even on the 10th reading.

Using the 1M resistors, I tried inserting the delayMicroseconds call that I propose. With 150 microseconds delay, the 0v pin always reads zero and the +5v pin usually reads 1023 (occasionally 1022). With 120 microseconds delay, the readings are less consistent.

Using the 100K resistors, with a delay of 10us the readings were consistently 0 and 1023. With 5 microseconds they were 0 and 1022 or 1023.

I measured the time taken by an analogRead call (without extra delay) at around 110 microseconds.

Conclusion:

- The effect of high source resistance is worse when reading +5v than when reading 0v.
- If my mcu is typical, inserting a delay of 10us would give reliable results with source resistance of up to 100K or a little more.
- At 1M source resistance, the delay needs to be increased to 150us.
- If instead of adding the delay you read the pin several times, the time taken to obtain a stable and correct reading can be much longer. For example, 5 readings @ 110us each totalling 550us, vs. 1 reading @ 260us including the 150us delay. Or 2 readings at 110us each totalling 220us, vs. 1 reading at 120us including 10us delay.

If my suggestion is adopted, I suggest making the default delay 10us, with a recommendation to set the delay higher if the source resistance is >100k. This default delay adds less than 10% to the time taken by a call to analogRead.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 525
Posts: 26554
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

"I find the forum to be rather slow in responding"
Well, I do the best I can smiley-cool when I'm not at work or designing things or building things or writing code or teaching fencing classes or deleting spam posts ...
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Pages: [1]   Go Up
Jump to: