High input impedance with analog read

pito: The issue is the S/H period is fixed to 1.5 ADC clock period. So it cannot be "prolonged" from outside by a delay(). With 16MHz/128 = 125kHz ADC clock that means S/H period is 12usecs. That is "a little bit more" than worst case scenario for 10k input impedance..

No quite, what the datasheet actually says is "The actual sample-and-hold takes place 1.5 ADC clock cycles after the start of a normal conversion and 13.5 ADC clock cycles after the start of an first conversion". In other words, the sample capacitor is disconnected from the multiplexer 1.5 ADC clock cycles after the start of the conversion, so you've got up to then to charge it. The period during which the input pin is connected to the sample capacitor is the period from when the multiplexer selects the desired input pin to 1.5 ADC clock periods after the start of the conversion. So the sample period can indeed be prolonged using a delay. Try it - it works!

That would be great, but how to decipher this diagram then - from MUX update (my understanding is the mux switches from A0 to A3 for example) to S/H (where the capacitor disconnects from mux) I see 1.5clock…

Yes, that diagram does imply that the mux might not be updated until the start of the conversion. However, section 24.5 of the atmega328p datasheet says:

"The MUXn and REFS1:0 bits in the ADMUX Register are single buffered through a temporary register to which the CPU has random access. This ensures that the channels and reference selection only takes place at a safe point during the conversion. The channel and reference selection is continuously updated until a conversion is started. Once the conversion starts, the channel and reference selection is locked to ensure a sufficient sampling time for the ADC. Continuous updating resumes in the last ADC clock cycle before the conversion completes (ADIF in ADCSRA is set)."

So I think "MUX update" in that diagram really means "MUX locked".

Ok, I did following, grrh:

  1. Sketch below connects a 1.8Mohm/1.8Mohm divider to analog input n1, input to the divider comes from D23 (0V or 3V).
  2. 1284p@16Meg, 2.56V internal refence, 3V Vcc, solderless breadboard, noisy
  3. I’ve patched analogRead(pin, shdelay) where shdelay is uint16_t passed to delayMicroseconds(shdelay), placed before the ADC is being started
  4. Scenario - divider’s input LOW, wait, divider’s input HIGH, do single ADC(shdelay) while measuring time, show adcvalue and the time
  5. repeat
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  analogReference(INTERNAL2V56);
}

void loop() {
  // put your main code here, to run repeatedly: 

  int adcdata;

  digitalWrite(23,LOW);  // set divider's input to 0V
  delay(200);
  adcdata = analogRead(1, 100);
  Serial.println(adcdata);
  delay(200);

  digitalWrite(23,HIGH);   // set divider's input to 3V

  long t1 = micros();   // do measure time = S/Hdelay + ADC conversion + overhead
  adcdata = analogRead(1, 200);    // patched analogRead(channel, S/H delay in usecs)
  long t2 = micros();

  digitalWrite(23,LOW);   // set divider's input to 0V

  Serial.print(adcdata);
  Serial.print(" ");
  Serial.println(t2-t1);

  delay(300);
}

The noisy output after "filtering has been put into a graph (x - S/H delay in useconds, y - adcvalue returned :

shdel.jpg

table.jpg

dc42: In one design that was powered from a 9V battery, to measure the battery voltage I used a voltage divider made from two 4.7M resistors, giving an effective source resistance of 2.35M. The reason for such high resistors was that the design didn't have an on/off switch, it just put everything to sleep when inactive; so I needed to minimize the current consumption of the voltage divider.

Another option is to connect one end of the divider to a digital pin and toggle it to high impedance between analog reads. This would limit current draw through the divider to when it's actually needed.

@dc42 - yes, you are right, it is visible now (even to me) the longer S/H delay before the actual ADC start the higher the returned value with large resistive divider (high input impedance). So maybe the next revision shall incorporate the shdelay parameter into the analogRead.

...
if (shdelay > 0) delayMicroseconds(shdelay);
#if defined(ADCSRA) && defined(ADCL)
    // start the conversion
    sbi(ADCSRA, ADSC);
...

BenF:

dc42:
In one design that was powered from a 9V battery, to measure the battery voltage I used a voltage divider made from two 4.7M resistors, giving an effective source resistance of 2.35M. The reason for such high resistors was that the design didn’t have an on/off switch, it just put everything to sleep when inactive; so I needed to minimize the current consumption of the voltage divider.

Another option is to connect one end of the divider to a digital pin and toggle it to high impedance between analog reads. This would limit current draw through the divider to when it’s actually needed.

When you disconnect (by putting it into high impedance) the low-side (and maybe the middle as well) of the divider, still the current will flow from 9V battery via high-side resistor to the input and there via the clamping diode to Vcc of the 328p. The clamping diodes are wired to each pin hard.
The current will be aprox I = (9V - 0.4V - Vcc)/Resistor
Here are the resistors connected to two high-impedance pins (aprox, the exact model of the clamping diodes not available), the current flowing from the battery is 0.8uA (not bad however, that is current of an DS1307 RTC).

divdis.jpg

pito: @dc42 - yes, you are right, it is visible now (even to me) the longer S/H delay before the actual ADC start the higher the returned value with large resistive divider (high input impedance). So maybe the next revision shall incorporate the shdelay parameter into the analogRead.

I've been suggesting this for about 18 months now, to no avail.

I've been suggesting this for about 18 months now, to no avail.

That is a typical selling cycle duration nowadays :)

pito: When you disconnect (by putting it into high impedance) the low-side (and maybe the middle as well) of the divider, still the current will flow from 9V battery via high-side ...

Not if you replace your top-side resistor with a zener.

This is a measuring system which shall demonstrate the S/H sampling delay with larger input impedances. It measures the actual ADC data based on S/H delay (see my previous posts above) when the analog input is connected to an divider (in this case 1.8Meg/1.8Meg).
As a bonus it also calculates the “RC constant based ADC value” based on - input impedance, internal charging resistor, internal S/H capacitor, stray capacitance, the S/H delay, the S/H delay offset (1.5clock) and the final voltage when S/H capacitor fully charged.

// ADC S/H delay investigation tool
// copyright Pito 5/2013

#include <DigitalIO.h>

// Class with runtime pin numbers.
PinIO pin23(23);   // divider connected to this pin

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  analogReference(INTERNAL2V56);
  delay (1000);  //stabilise the internal reference
}

void loop() {
  unsigned long adcdata, maxadc;
  unsigned int i, samples, shdelay;
  float adcvoltage;

  adcdata = 0;
  samples = 200;

  // Calculate the voltage based on RC constant
  float R = 900.0e3 + 100.0e3;  //your divider impedance + internal 100k resistor
  float C = 14.0e-12 + 10.0e-12;  // S/H capacitor + stray capacitance
  float shoffset = 12.0e-6;  // initial S/H delay = 1.5clock @125kHz ADC clock

  // To be value measurement
  pin23.high();    // set divider's input to 3V, start charging
  delay(300);
  adcdata = 0;
  Serial.println("*** To-be ADC value ***");
  for ( i = 1; i<=5000; i++) {
    adcdata = adcdata + analogRead(1, 500);  // ADC input at Ain 1
  }
  Serial.print("To-be ADC value: ");
  Serial.println(adcdata/5000);

  maxadc = adcdata/5000;

  // S/H delay investigation
  Serial.println("*** Start ***");
  delay(300);
  adcdata = 0;

  for ( shdelay = 0; shdelay <= 250; shdelay = shdelay + 3) {
    for ( i = 1; i<=samples; i++) {
      pin23.low();  // set divider's input to 0V
      delay(20);   // discharge fully to 0V
      pin23.high();  // set divider's input to 3V, start charging
      adcdata = adcdata+ analogRead(1, shdelay);
    }

    Serial.print("S/H delay par. [us]: ");
    Serial.print(shdelay);
    Serial.print("   Tot. S/H delay [us]: ");
    Serial.print(shdelay + shoffset*1.0e6);
    Serial.print("   ADC value: ");
    Serial.print(adcdata/samples);

    // Calculate the voltage based on RC constant
    adcvoltage = (float)maxadc*(1.0-exp(-(((float)shdelay*1.0e-6)+shoffset)/(R*C)));

    Serial.print("   ADC value based on RC: ");
    Serial.println(adcvoltage);

    adcdata = 0;
    delay(200);
  }
  Serial.println("*** Stop ***");
  while(1){
  };
}

And the results:

*** To-be ADC value ***
To-be ADC value: 619
*** Start ***
S/H delay par. [us]: 0   Tot. S/H delay [us]: 12.00   ADC value: 319   ADC value based on RC: 243.56
S/H delay par. [us]: 3   Tot. S/H delay [us]: 15.00   ADC value: 320   ADC value based on RC: 287.67
S/H delay par. [us]: 6   Tot. S/H delay [us]: 18.00   ADC value: 325   ADC value based on RC: 326.61
S/H delay par. [us]: 9   Tot. S/H delay [us]: 21.00   ADC value: 390   ADC value based on RC: 360.96
S/H delay par. [us]: 12   Tot. S/H delay [us]: 24.00   ADC value: 391   ADC value based on RC: 391.28
S/H delay par. [us]: 15   Tot. S/H delay [us]: 27.00   ADC value: 422   ADC value based on RC: 418.04
S/H delay par. [us]: 18   Tot. S/H delay [us]: 30.00   ADC value: 456   ADC value based on RC: 441.65
S/H delay par. [us]: 21   Tot. S/H delay [us]: 33.00   ADC value: 451   ADC value based on RC: 462.49
S/H delay par. [us]: 24   Tot. S/H delay [us]: 36.00   ADC value: 485   ADC value based on RC: 480.88
S/H delay par. [us]: 27   Tot. S/H delay [us]: 39.00   ADC value: 487   ADC value based on RC: 497.11
S/H delay par. [us]: 30   Tot. S/H delay [us]: 42.00   ADC value: 487   ADC value based on RC: 511.43
S/H delay par. [us]: 33   Tot. S/H delay [us]: 45.00   ADC value: 518   ADC value based on RC: 524.07
S/H delay par. [us]: 36   Tot. S/H delay [us]: 48.00   ADC value: 517   ADC value based on RC: 535.23
S/H delay par. [us]: 39   Tot. S/H delay [us]: 51.00   ADC value: 530   ADC value based on RC: 545.07
S/H delay par. [us]: 42   Tot. S/H delay [us]: 54.00   ADC value: 542   ADC value based on RC: 553.76
S/H delay par. [us]: 45   Tot. S/H delay [us]: 57.00   ADC value: 542   ADC value based on RC: 561.42
S/H delay par. [us]: 48   Tot. S/H delay [us]: 60.00   ADC value: 558   ADC value based on RC: 568.19
S/H delay par. [us]: 51   Tot. S/H delay [us]: 63.00   ADC value: 559   ADC value based on RC: 574.16
S/H delay par. [us]: 54   Tot. S/H delay [us]: 66.00   ADC value: 560   ADC value based on RC: 579.43
S/H delay par. [us]: 57   Tot. S/H delay [us]: 69.00   ADC value: 573   ADC value based on RC: 584.08
S/H delay par. [us]: 60   Tot. S/H delay [us]: 72.00   ADC value: 574   ADC value based on RC: 588.18
S/H delay par. [us]: 63   Tot. S/H delay [us]: 75.00   ADC value: 580   ADC value based on RC: 591.80
S/H delay par. [us]: 66   Tot. S/H delay [us]: 78.00   ADC value: 584   ADC value based on RC: 595.00
S/H delay par. [us]: 69   Tot. S/H delay [us]: 81.00   ADC value: 585   ADC value based on RC: 597.82
S/H delay par. [us]: 72   Tot. S/H delay [us]: 84.00   ADC value: 592   ADC value based on RC: 600.31
S/H delay par. [us]: 75   Tot. S/H delay [us]: 87.00   ADC value: 592   ADC value based on RC: 602.50
S/H delay par. [us]: 78   Tot. S/H delay [us]: 90.00   ADC value: 592   ADC value based on RC: 604.44
S/H delay par. [us]: 81   Tot. S/H delay [us]: 93.00   ADC value: 597   ADC value based on RC: 606.15
S/H delay par. [us]: 84   Tot. S/H delay [us]: 96.00   ADC value: 598   ADC value based on RC: 607.66
S/H delay par. [us]: 87   Tot. S/H delay [us]: 99.00   ADC value: 600   ADC value based on RC: 608.99
S/H delay par. [us]: 90   Tot. S/H delay [us]: 102.00   ADC value: 602   ADC value based on RC: 610.17
S/H delay par. [us]: 93   Tot. S/H delay [us]: 105.00   ADC value: 602   ADC value based on RC: 611.21
S/H delay par. [us]: 96   Tot. S/H delay [us]: 108.00   ADC value: 606   ADC value based on RC: 612.12
S/H delay par. [us]: 99   Tot. S/H delay [us]: 111.00   ADC value: 606   ADC value based on RC: 612.93
S/H delay par. [us]: 102   Tot. S/H delay [us]: 114.00   ADC value: 606   ADC value based on RC: 613.64
S/H delay par. [us]: 105   Tot. S/H delay [us]: 117.00   ADC value: 609   ADC value based on RC: 614.27
S/H delay par. [us]: 108   Tot. S/H delay [us]: 120.00   ADC value: 608   ADC value based on RC: 614.83
S/H delay par. [us]: 111   Tot. S/H delay [us]: 123.00   ADC value: 610   ADC value based on RC: 615.32
S/H delay par. [us]: 114   Tot. S/H delay [us]: 126.00   ADC value: 610   ADC value based on RC: 615.75
S/H delay par. [us]: 117   Tot. S/H delay [us]: 129.00   ADC value: 611   ADC value based on RC: 616.13
S/H delay par. [us]: 120   Tot. S/H delay [us]: 132.00   ADC value: 611   ADC value based on RC: 616.47
S/H delay par. [us]: 123   Tot. S/H delay [us]: 135.00   ADC value: 613   ADC value based on RC: 616.77
S/H delay par. [us]: 126   Tot. S/H delay [us]: 138.00   ADC value: 612   ADC value based on RC: 617.03
S/H delay par. [us]: 129   Tot. S/H delay [us]: 141.00   ADC value: 613   ADC value based on RC: 617.26
S/H delay par. [us]: 132   Tot. S/H delay [us]: 144.00   ADC value: 613   ADC value based on RC: 617.47
S/H delay par. [us]: 135   Tot. S/H delay [us]: 147.00   ADC value: 613   ADC value based on RC: 617.65
S/H delay par. [us]: 138   Tot. S/H delay [us]: 150.00   ADC value: 615   ADC value based on RC: 617.81
S/H delay par. [us]: 141   Tot. S/H delay [us]: 153.00   ADC value: 615   ADC value based on RC: 617.95
S/H delay par. [us]: 144   Tot. S/H delay [us]: 156.00   ADC value: 615   ADC value based on RC: 618.07
S/H delay par. [us]: 147   Tot. S/H delay [us]: 159.00   ADC value: 615   ADC value based on RC: 618.18
..
S/H delay par. [us]: 192   Tot. S/H delay [us]: 204.00   ADC value: 617   ADC value based on RC: 618.87
S/H delay par. [us]: 195   Tot. S/H delay [us]: 207.00   ADC value: 617   ADC value based on RC: 618.89
S/H delay par. [us]: 198   Tot. S/H delay [us]: 210.00   ADC value: 617   ADC value based on RC: 618.90
S/H delay par. [us]: 201   Tot. S/H delay [us]: 213.00   ADC value: 617   ADC value based on RC: 618.91
S/H delay par. [us]: 204   Tot. S/H delay [us]: 216.00   ADC value: 617   ADC value based on RC: 618.92
..
S/H delay par. [us]: 234   Tot. S/H delay [us]: 246.00   ADC value: 616   ADC value based on RC: 618.98
S/H delay par. [us]: 237   Tot. S/H delay [us]: 249.00   ADC value: 617   ADC value based on RC: 618.98
S/H delay par. [us]: 240   Tot. S/H delay [us]: 252.00   ADC value: 617   ADC value based on RC: 618.98
S/H delay par. [us]: 243   Tot. S/H delay [us]: 255.00   ADC value: 618   ADC value based on RC: 618.98
S/H delay par. [us]: 246   Tot. S/H delay [us]: 258.00   ADC value: 618   ADC value based on RC: 618.99
S/H delay par. [us]: 249   Tot. S/H delay [us]: 261.00   ADC value: 618   ADC value based on RC: 618.99
*** Stop ***