Overview
In this tutorial, we will learn how to use ADC in Raspberry Pi Pico with ADC Example Code using MicroPython. An analog to digital converter (ADC) is a circuit that converts a continuous voltage value (analog) to a binary value (digital) that can be understood by a digital device which could then be used for digital computation.
The Raspberry Pi Pico is built using an RP2040 microcontroller. The board exposes 26 multi-function GPIO pins from a total of 36 GPIO pins. Out of 36 GPIO Pins, there are 4 ADC pins but only 3 are usable.
The ADC in Raspberry Pi Pico is 12bits, which is 4 times better than the 10 bits ADC of the Arduino. We will write a MicroPython code to learn how we can use the ADC pin value with any analog sensors. A potentiometer is the best tool to vary the input Analog Voltage. But before jumping directly into the ADC guide, it is recommended to go through Raspberry Pi Pico Getting Started Tutorial.
What is Analog to Digital Converter (ADC)?
An Analog to Digital Converter (ADC) is a very useful feature that converts an analog voltage on a pin to a digital number. By converting from the analog world to the digital world, we can begin to use electronics to interface with the analog world around us.
In real-life applications, ADC is a system that converts an analog signal, such as a sound picked up by a microphone or light entering a digital camera, into a digital signal. An ADC may also provide an isolated measurement such as an electronic device that converts an input analog voltage or current to a digital number representing the magnitude of the voltage or current.
The ADC is perfect for these sensors. With the ADC, you can sense environmental parameters like light, sound, distance, gravity, acceleration, rotation, smell, gases, other particles.
How does an ADC work in a Microcontroller?
Most microcontrollers nowadays have built-in ADC converters. It is also possible to connect an external ADC converter to any type of microcontroller. ADC converters are usually 10 or 12 bits, having 1024 to 4096 quantization levels. A 16 bits ADC has 65536 quantization levels. A Raspberry Pi Pico has 12 Bits ADC with a quantization level of 4096.
The ADC conversion process must be started by the user program and it may take several hundreds of microseconds for a conversion to complete. ADC converters usually generate interrupts when a conversion is complete so that the user program can read the converted data as quickly as possible.
ADC in Raspberry Pi Pico
The Raspberry Pi Pico supports four 12-bit SAR based analog to digital converters. Out of the 4, you can only use 3 analog channels. The 4th analog channel is internally connected to the internal temperature sensor. You can measure the temperature using build-in temperature by reading the analog value of ADC4. The following table shows that the input signal for ADC0, ADC1, and ADC2 can be connected with GP26, GP27 & GP28 pins respectively.
ADC Module | GPIO Pins |
ADC0 | GP26 |
ADC1 | GP27 |
ADC2 | GP28 |
You can perform the A/D conversion in polling, interrupt & FIFO with DMA mode. The ADC conversion speed per sample is 2μs that is 500kS/s. The RP2040 microcontroller operates on a 48MHZ clock frequency which comes from USB PLL. So, its ADC takes a 96 CPU clock cycle to perform one conversion. Therefore, the sampling frequency is (96 x 1 / 48MHz) = 2 μs per sample (500kS/s).
Raspberry Pi Pico ADC Example Code
Now let us learn how to use ADC of Raspberry Pi Pico. We will use a 10K Potentiometer to vary the Analog input voltage. We will map the analog voltage from 0 to 3.3V with 12 Bit or 16 Bit ADC. The connection diagram is given below.
Connect Pin 1 & Pin 3 of Potentiometer to 3.3V Pin & GND Pin of the Raspberry Pi Pico. Connect the Pin 2 of the Potentiometer to GP28 of Raspberry Pie Pico.
Now it’s time to write a code and check the Analog Reading. To do that you can use Thonny IDE or go with uPyCraft IDE. Copy the following code and hit ‘Download & Run Button‘.
1 2 3 4 5 6 7 8 9 |
import machine import utime analog_value = machine.ADC(28) while True: reading = analog_value.read_u16() print("ADC: ",reading) utime.sleep(0.2) |
In this code part, I define the ADC input connected at pin 28. Then to create an infinite loop I make a while true. then I read the ADC value with the read u16 function. Then using print I can show the value on the shell monitor.
When you rotate the potentiometer and the value goes from 0 to 65536 and that’s weird because the value should go from 0 to 4096. This is supposed to be a 12bit ADC and not 16bit. Anyway, that’s how we can read analog values with the ADC on the raspberry Pi Pico.
If you want to add more analog pins to the Raspberry Pi Pico and read the ADC value more precisely, you may use the ADS1115 16-Bit ADC Module for your projects. You can follow the following Guide here:
10 Comments
Haven’t tested it yet, but documentation is describing ADC3 input as a monitor of VSYS divider.
Citation:
VSYS is the main system ‘input voltage’ and feeds the RT6150 buck-boost SMPS, which generates a fixed 3.3V outputfor the RP2040 device and its IO (and can be used to power external circuitry). VSYS is R-C filtered and divided by 3 (byR5, R6 and C3 in the Pico schematic) and can be monitored on ADC channel 3. This can be used for example as a crudebattery voltage monitor.
From the resistor make a watering kit with capacitive moisture sensor (using adc) and output to pump (3-5v). Could also incorporate the temp sensor reading. Could you do this, would you use a relay or mofset, to drive the pump?
Why do you go through an in depth explanation of the ADC down to the clock cycle level and then completely blow off the 16 bit result in your program example?
👆🏻 THIS
Agreed, it’s a bit lazy on his part. Anyway, from https://docs.micropython.org/en/latest/library/machine.ADC.html is seems it’s the analog_value.read_u16() that does a conversion internally.
STATIC uint16_t adc_config_and_read_u16(uint32_t channel) {
adc_select_input(channel);
uint32_t raw = adc_read();
const uint32_t bits = 12;
// Scale raw reading to 16 bit value using a Taylor expansion (for 8
return raw > (2 * bits – 16);
}
“The Raspberry Pi Pico supports four 12-bit SAR based analog to digital converters.”
NO, the RPi Pico has one ADC, with five channels that can be connected and read in a round robin fashion. Channels 3 and 4 (that is, the fourth and fifth cannels, channel 0 being the first) are reserved for the VSYS (Pi Pico specific) and the internal temperature sensor (fixed on the RP2040 chip)
because he doesn’t know what he’s talking about
ADC is useless if you don’t map digital readings to voltage values, it’s not really a step you can skip in a guide
ADC is NOT useless if you don’t map digital readings to voltage values, especially, when all you care about is the voltage as a percentage of the max voltage available. This is the case with linear actuators – after calibrating by getting the min/max readings from the feedback line, you can then map any input value to a percent of extension. Not knowing the voltage is an advantage because … you don’t need to know the voltage.
That was very important information for my purpose. Thank you!
Specifically: “scaled such that the minimum value is 0 and the maximum value is 65535′