Electronic – arduino – Inaccurate BandGap measurement

accuracyadcarduinovoltage-reference

I've followed advice on the web on how to use "bandgap" voltage reference to measure supply voltage, however, the measurements are not as accurate as the ADC can be on an Arduino Mega.

On the one hand, I've measured the 1.1V ref to actually be 1.087V using a DMM to measure the voltage across a capacitor from AREF to GND with the appropriate code.

On the other hand, measuring the BG internally with the ADC using the attached code returns an ADC average reading of 226.5 which is 1.107V with a 5V supply (measured using a DMM from the 5V pin). This is a 20mV error. I've being getting about 5mV accuracy when using the ADC to measure an external voltage source.

The Arduino Mega is powered via USB.

  • An external supply of 1.087V was simultaneously (alternately) measured with the analog pin yielded a different reading. What is the difference between the two passes?

    #define N 128
    #define ND 128.0D
    
    int analogReadBG(){
      uint8_t low, high;
      ADMUX = 0;
      bitClear(ADCSRB,MUX5); // Set ADC input as BG (1.1V)
      bitSet(ADMUX,MUX4);
      bitSet(ADMUX,MUX3);        
      bitSet(ADMUX,MUX2);
      bitSet(ADMUX,MUX1);        
      bitSet(ADMUX,REFS0);  // Set 5V as ADC reference voltage
    
      for (int i=0;i<7;i++){ // Perform several converstions for reading to settle
        bitSet(ADCSRA, ADSC);
        while (bit_is_set(ADCSRA, ADSC));
      }
      low  = ADCL;
      high = ADCH;
      return (high << 8) | low;
    }
    
    void setup() {
      Serial.begin(115200);
    }
    long movingSum;
    double movingAverage;
    void loop() {  
      movingSum = 0;
      for (int i=0;i<N;i++){
        movingSum += analogReadBG();
      }
      movingAverage = movingSum/ND;
      Serial.println(movingAverage);
      delay(1000);
    }
    

Best Answer

There are two big sources of error you do not appear to have considered- the reference voltage (your USB supply voltage), which could easily be low by 2%, and the ADC error, which is of the order of 2-4LSBs. Since you're only using the lower 20% of the ADC range, that represents a relatively large percentage error of 1-2% of reading. Averaging many readings does not reduce either of those errors.

Also your number of 266.5 does not make sense with a 5.000V reference. 226.7 would be expected from your calculation and 222.6 as the nominal exact value with a 5.000V reference and a 1.087V input.