Measuring DC Voltage with a Raspberry Pi Pico (MicroPython)

Created:  
Updated:   05Aug2024   03:12:23   UTC 2024-08-05T03:12:23Z
Rating:   (0 reviewsThis article has not been rated yet)

This tutorial shows how to measure 0V to 3.3V DC voltage with the Raspberry Pi (RPiRaspberry Pi) Pico microcontroller board, including how to improve the precision and accuracy of DC voltage measurements by calibrating the Pico ADCAnalog-to-Digital Converter (ADC, A/D, or A-to-D) or by using an external precision voltage reference.

ADC Inputs & VREF

The RPi Pico RP2040 MCUMicrocontroller Unit has a 12-bit 500kSPSKilo Samples Per Second (1000 samples/s) ADCAnalog-to-Digital Converter (ADC, A/D, or A-to-D) that can read between 0V and 3.3V analog signals with three channels that can be used as inputs (there is a fourth channel that is used internally for the onboard temperature sensor). This converter scales an analog signal in a range of 0 to 4095 counts, with a resolution between readings of 3.3V per 4095 counts (0.8mV/count).

RPi Pico Analog Input and VREF Pins
Analog Input Pins:
There are 3 analog input pins on the Pico: ADC0, ADC1, and ADC2. The voltage range on all of these inputs is 0V to 3.3V.
ADC_VREF Pin:
The ADC_VREF pin is the voltage reference for the ADC that uses by default the 3.3V power supply voltage filtered using an RC filter (201Ω into 2.2μF) to reduce noise. For improved ADC performance you can provide an external precision voltage reference, such as the LM4040, that is connected to the ADC_VREF pin to ground AGND pin, but this will reduce the analog input voltage range from 0V to 3.0V.
AGND Pin:
The Analog Ground AGND pin is a separate ground reference than GND that is connected to the same ground point as the power supply. It is designed for analog circuitry sensitive to noise, such as ADCs, by providing a cleaner ground reference for analog signals that helps reduce noise and improve the accuracy of analog-to-digital conversions.

Measuring DC Voltage

The RPi Pico can measure DC voltages between 0V and 3.3V with its analog pins. This could be a sensor or other voltage source such as a 1.5V AA battery, as long as its under 3.3V. For measuring external voltage sources, the positive voltage terminal is connected to the analog ADC0 pin and negative terminal to the GND pin (the DC voltage source and Pico must share a common ground).

DC Voltage Measurement Hookup

The RPi Pico MicroPython code provided below makes voltage measurements on the ADC0 pin at a sampling interval of a half a second (500 milliseconds). The Pico ADC has a 12-bit resolution with a range from 0 to 4095, but the MicroPython read_u16() scales the values to a 16-bit integer in the range of 0 to 65535. A 3.3V voltage reference is used to convert the ADC counts to 0V - 3.3V. The USB port on the RPi Pico board is connected to a computer to transfer the data serially and display the results in an IDEIntegrated Development Environment (IDE) is a software application that helps develop software code efficiently. console such as Thonny.

read_dc_voltage.py
            

The output of measuring a AA battery, which has a nominal voltage of 1.5V, is provided below.

read_dc_voltage.py Console Output
            

Calibration

VREF Calibration

The voltage on the ADC_AREF pin is used to convert the ADC count reading to a voltage according to the equation below.

ADC Voltage and VREF Equation

In the previous MicroPython code VREF was assumed to be 3.3V, but it can be slightly different (e.g., 3.25V) and cause errors in the ADC voltage measurements. Differences in the voltage reference mostly depend on the power source for the RPi Pico board. By default VREF is supplied by the 3.3V SMPSSwitch-Mode Power Supply of the Pico.

More accurate voltage measurements can be obtained by measuring the ADC_VREF pin with a Digital Voltmeter (DVMDigital Voltmeter) and using the measured value in your MicroPython code when converting the ADC counts to volts. For example, the following code uses a measured voltage reference of 3.25V. If the Pico power source changes by switching from USB to battery, or even plugging the USB into a different computer, then the ADC_VREF pin needs to be remeasured.

read_dc_voltage_vref_cal.py
              

Linear Calibration

The VREF calibration in the previous section is a single point calibration. The accuracy of RPi Pico voltage measurements can be further improved by calibrating the ADC with multiple samples across the range of your measurements. This can be achieved by changing the ADC input voltage with a variable power supply and measuring the voltages with both the ADC and a Digital Voltmeter (DVMDigital Voltmeter). A linear fit between the DVM measured voltages and ADC counts can be computed to determine the mapping between counts and volts given below. The slope of the linear fit is in Volts/Count and the offset should be a small value in Volts.

ADC Linear Calibration Equation

You can use the following MicroPython code to obtain the ADC values in counts. This will output a sampling of the ADC counts every half second. Even with a stable input voltage, the ADC output may vary by a few counts due to noise. To reduce the error in the results due to noise you could average the samples.

read_dc_voltage_in_counts.py
              

An example of ADC readings from an input voltage between 0.5V and 3.0V in 0.5V steps is provided below. It is best not to take measurements close to the 0V and 3.3V limits of the ADC because most single ended ADCs have difficulty close to their power rails. You also don't want to risk damaging the RPi Pico by exceeding 3.3V due to noise or voltage spikes. Measuring too close to 0V will just include more quantization noise than desired into the calibration results.


Linear Calibration Data
ADC Counts Input Voltage
631.24 0.53V
1301.51 1.06V
1879.95 1.52V
2583.72 2.08V
3129.65 2.51V
3819.82 3.06V
ADC Linear Calibration Data Plot

A least squares Linear fit to the data determines the slope (0.7935 × 10-3 Volts/Count) and offset (2.8406 × 10-2 Volts) calibration parameters. The MicroPython code below shows how to use these parameters to convert ADC counts into voltage values.

read_dc_voltage_linear_cal.py
              

External Reference Voltage

The ADC_VREF pin is the reference voltage for the ADC where the voltage value is the full-scale value of the ADC (the maximum conversion value possible). The input range of the ADC_VREF pin is 0V to 3.3V DC.

Supplying a lower VREF voltage than the 3.3V default can be used to reduce the input voltage range of the ADC closer to your measurement range and improve its resolution (smaller voltage differences between digital steps). For example, if you wanted to use the ADC to monitor a signal that had a 0V to 2.0V range you could change the full-scale of the ADC by connecting VREF to a 2.0V source, which will provide a resolution of 2.0/4096 instead of 3.3V/4096. For the best results you should choose a reference that is just a little larger than the expected range of your measurements.

A stable and precise external voltage reference can also improve the accuracy of DC voltage measurements. The accuracy of the ADC is no better than the reference voltage VREF, where small variations in VREF become variations in the ADC reading. By default VREF is supplied by the 3.3V SMPSSwitch-Mode Power Supply of the Pico. This means that the default voltage reference can be different depending on the power source, which can be a problem if the source changes.

One option is to use an external regulated power supply with a precise voltage output. If you are using an external power supply, be sure to connect the GND to the Pico's GND pin. Another option is to use the Pico's 3.3V pins with a precision shunt voltage reference component. The LM4040 is a common precision micropower shunt voltage reference chip that comes in fixed Reverse-Breakdown Voltages of 1.225V, 2.048V, 2.500V, 3.000V, 4.096V, and 5.000V. LM4040 versions with a voltage of 3.0V or less can be used with the RPi Pico. An example of how to hookup the LM4040 to the RPi Pico is shown in the figure below.

RPi Pico Shunt Voltage Reference

By default the ADC_VREF voltage reference pin for the ADC uses the 3.3V power supply voltage and is filtered using an RC filter (200Ω + 1Ω into 2.2μF) to reduce noise. The 1Ω resistor on the Pico (R9) is designed to help with shunt references that would otherwise become unstable when directly connected to the 2.2μF capacitor. A shunt reference connected from the ADC_VREF pin to AGND pin will draw continuous current of (3.3V-3.0V)/200 ≈ 1.5mA through the 200Ω filter resistor to provide a stable and precise voltage known as its fixed reverse-breakdown voltage.

The LM4040 also comes in modules such as the Adafruit (PID 2200) breakout module shown below. This module comes with two different high precision shunt voltage references, 2.048V and 4.096V, with 0.1% accuracy. The 2.048V reference is useful for 3.3V microcontrollers, such as the RPi Pico and ESP32. The the 4.096V reference is used for 5V microcontrollers, such as the Arduino Uno R3. You can power the module with a supply between 5V and 12V, or 3V if you only want to use the 2.048V reference.

Adafruit LM4040 Module

The figure below shows how to hookup the Adafruit LM4040 Module to the RPi Pico. The supply voltage of the LM4040 module VIN is connected to the 3.3V output pin of the Pico board. The LM4040 module and Pico board need to share a common ground by connecting the LM4040 module GND pin to the Pico's AGND pin. The 2.048V pin of the LM4040 module is the reference voltage connected to the VREF pin of the Pico.

Adafruit LM4040 Module Hookup

A MicroPython code example using the external LM4040 reference module is provided below. The RPi Pico has no external reference voltage configuration setting in the code like there is for the Arduino boards.

dc_voltage_using_external_vref.py
            

Conclusion

This tutorial covered how to measure 0V to 3.3V DC voltage with the RPi Pico microcontroller board, and improving the precision and accuracy of measurements by calibrating the Pico ADCAnalog-to-Digital Converter (ADC, A/D, or A-to-D) or by using an external precision voltage reference.

If you need to measure voltages above 3.3V, then you can to attenuate the signal with a voltage divider circuit or module. The Pico ADC also has difficulty resolving small voltage signals less than 1mV when using a 3.3V range and cannot measure negative voltages, but these signals can be amplified and/or shifted into the positive range with OpAmp circuitry. More details on attenuating, amplifying, and shifting signals are covered in the Interfacing Analog Inputs article.

Related Content

Products


RP2040 <span class="tooltip">RPi<span class="tooltiptext">Raspberry Pi</span></span> Pico Board Products

Created:   27Jul2023   23:50:32   UTC 2023-07-27T23:50:32Z
Updated:   04Sep2024   00:31:23   UTC 2024-09-04T00:31:23Z

Processor:
32-bit 133MHz Dual-Core ARMAdvanced Reduced Instruction Set Computer (RISC) Machines Cortex-M0+
Memory:
2MB QSPIQuad Serial Peripheral Interface (QSPI) is a serial communication interface designed for talking to flash chips by using 4 data lines. Flash and 264KB SRAMStatic Random Access Memory
Interface:
1x Micro-B USB, Up to 30x Digital I/OInput/Output with PWMPulse-Width Modulation, 4x Analog Inputs 12-bit ADCAnalog-to-Digital Converter (ADC, A/D, or A-to-D), 2x UARTUniversal Asynchronous Receiver-Transmitter, 2x I2CInter-Integrated Circuit. Also referred to as IIC or I2C., 2x SPISerial Peripheral Interface, and PIOProgrammable Input/Output (PIO) can be programmed to process data transmission, such as a non-standard serial interface, without using resources from the CPU.
Boards:
RPiRaspberry Pi Pico, Pico H, Pico W, and Pico WH

RP2040 Microcontroller Products

Created:   11Dec2022   23:50:41   UTC 2022-12-11T23:50:41Z
Updated:   04Sep2024   22:33:49   UTC 2024-09-04T22:33:49Z

Processor:
32-bit 133MHz Dual-Core ARMAdvanced Reduced Instruction Set Computer (RISC) Machines Cortex-M0+
Memory:
2MB QSPIQuad Serial Peripheral Interface (QSPI) is a serial communication interface designed for talking to flash chips by using 4 data lines. Flash and 264KB SRAMStatic Random Access Memory
Interface:
Up to 30x Digital I/OInput/Output with PWMPulse-Width Modulation, 4 channel 12-bit 500kbs ADCAnalog-to-Digital Converter (ADC, A/D, or A-to-D), USB 1.1 Host and Device Full/Low speed, and UARTUniversal Asynchronous Receiver-Transmitter/I2CInter-Integrated Circuit. Also referred to as IIC or I2C./SPISerial Peripheral Interface/PIOProgrammable Input/Output (PIO) can be programmed to process data transmission, such as a non-standard serial interface, without using resources from the CPU.
Boards:
  • RPiRaspberry Pi Pico, Pico H, Pico W, Pico WH
  • Adafruit QT Py, ItsyBitsy, Feather
  • SparkFun Pro Micro, Thing Plus
  • Pimoroni Tiny 2040, Pico LiPo
  • Seeed Studio XIAO
  • Waveshare RP2040-Zero, RP2040-Plus

Voltage Reference Products

Created:   26May2024   21:29:57   UTC 2024-05-26T21:29:57Z
Updated:   27May2024   03:59:16   UTC 2024-05-27T03:59:16Z

  • LM4040 Modules
  • AD584 Modules

Resistor Voltage Divider Sensor Module Products

Created:   12Apr2023   21:11:53   UTC 2023-04-12T21:11:53Z
Updated:   07May2024   09:46:17   UTC 2024-05-07T09:46:17Z

  • Two precision resistors (1% tolerance)
  • 0V to 25V DC input range
  • 0V to 5V output with 4.89mV resolution

Article Rating

Sign in to rate this article

Sign In


(0) Comments

Sign in to leave a comment

Sign In