Supply Voltage Measurement

This experiment has no particular purpose but to satisfy my curiosity. At one point in the past I read that the Atmega 328p used in the Arduino has an internal voltage reference that can be measured with the ADC. Sine the voltage of the reference is assumed to be fixed this actually delivers an indirect measurement of the supply voltage of the chip. Of course I had to try this.

Instead of just measuring the supply voltage I measure it against different loads. This is easy as my Blinkenlight setup allows for up to 18 LEDs to be switched on or off for different load conditions. So I just add more and more LEDs and see what happens to the chip’s supply voltage.

//
//  www.blinkenlight.net
//
//  Copyright 2013 Udo Klein
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program. If not, see http://www.gnu.org/licenses/

long read_vin_mv() {
    // data sheet 24.9.1 ADC Multiplexer Selection Register
    ADMUX = (1<<REFS0) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1);
   // wait for adc to settle 
    delay(5); 
         
    // trigger conversion     
    ADCSRA |= 1<<ADSC;
    
    // wait for conversion to finish
    while (ADCSRA & (1<<ADSC)) {};
    
    // read result
    uint16_t adc;
    adc = ADCL;
    adc |= ADCH<<8;
    
    // data sheet 24.7 ADC Conversion Result
    // ADC = vref * 1024 / vin
    // notice that vin and vref have exchanged roles because we 
    // measure the reference voltage against vin
    // ==> vin [V] = vref [V] * 1024 / adc
    // ==> vin [mV] = 1.1 * 1000 * 1024 / adc
    return 1126400L / adc;
}

void setup() {  
    Serial.begin(115200);
    for (uint8_t led=2; led<20; ++led) {
        pinMode(led, OUTPUT);
    }
}

void enable_n_leds(uint8_t n) {
    for (uint8_t led=2; led<20; ++led) {
        digitalWrite(led, led<2+n? HIGH: LOW);
    }
}

void loop() {
    for (uint8_t n=0; n<= 18; ++n) {
        enable_n_leds(n);
        Serial.print(n, DEC);
        Serial.print(';');
        delay(1500);  
        Serial.println(read_vin_mv(), DEC );
    }
}

As expected increasing the load will decrease the supply voltage. See the picture below for a scatter plot of the results.

Voltage Measurements Scatter Plot

As you can see the measurements are all in discrete steps. This is of course due to the limited resolution of the analog digital converter (ADC). As you can also see the last two digits of the converter are not to reliable at all. Now how do we figure out the “real” values? According to the Atmel datasheet it is appropriate to measure often and then to compute the averages. So this is what I did. Here comes the plot after averaging 73 samples per LED. If you wonder why 73 – there is no specific reason I just measured for some time and this happened to sample 73 measurements per LED.

Voltage Measurement Averages Plot

So the values start to be closer to a linear graph (as predicted by common theory). A closer look reveals that the drop is about 9.4mV per additional LED.

Of course I also measured the current consumption during this experiment. See the video for the current consumption.

If you pick have a look at the current ratings in the video you will that each LED adds about 2.4mA of current consumption. Or with other words the USB power supply seems to have an impedance of about 4Ω which is unexpected high. Since the USB bus may source up to 500mA this is definitely to high. So how come? Well, I suspect the build in polyfuse but I did not investigate this very much further.

In case you might wonder how I spliced into the USB power to measure the current consumption. This was very easy. I did not use an original Arduino but my own Board (aka Blinkenlighty) with build in LEDs. Unlike the newer Arduinos it features manual selection of the power supply. I have put this into my design intentionally. Thus I can just remove the red power supply shunt in order to measure the current consumption.

Red Shunts

One Response to Supply Voltage Measurement

  1. You have observed very interesting points! ps decent web site

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s