Raspberry pi PICO ADC reading [closed]
Asked 2 months ago
Modified 1 month ago
Viewed 755 times
0
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 months ago.
Why not get zero when taking ADC readings on Raspberry Pi Pico? Even though I ground the ADC pin, the analog reading always fluctuates between 10 to 20. How can analog reading be reduced to zero?
EditFollowFlag
111k9393 gold badges296296 silver badges369369 bronze badges
asked Apr 21 at 6:32
2133 bronze badges
- 1Please share your code showing how you read the ADC. Note that it is a 12-bit ADC with 4096 quantisation levels, so a reading of 20 corresponds to just 0.5% noise. – Mark Setchell Apr 21 at 9:24
- Perhaps you can try the demo code in the following tutorial, and I can repeat your experiment and see if I get the same results as yours: how2electronics.com/…. – tlfong01 Apr 23 at 4:28
- And a couple of troubleshooting suggestions: (1) Swapping technique: Pico has 4 ADC pins. You can swap the pin a see if all pins have the same error/tolerance levels. If all pins have move or less random error margins, say 1% of max analog signal value, then the might be the spec and you cannot change tha.t. (2) Pico has the Analog reference pin. If you use a low max/ reference signal level, say 1.8/2.0V, then if error rate is still 1% of max, you can have relevative lower error spec.round, then you would have less noise noice releated to power/mains ground noise, / to continue, … – tlfong01 Apr 23 at 8:30
- / continued, … (3) Pico has a specific “Analog ground pin”, which you should use specifically for analog signal ground (also avoid, messing with power ground). (4) If your anslogue signal to measure is stable, low frequency, then you can use a low frequency filter to filter high frequency noise. (4) Avoid using long wiring/cables to reduce picking up surrounding noise. (5) use double shielded, pseudo differential pair wiring/cables twisted pair cables, … – tlfong01 Apr 23 at 8:37
- Now let us use the following picture as a reference, focusing on the ADC pins in pink, and write a program to calibrate the Pico ADC performance: imgur.com/a/0oU6DOb – tlfong01 Apr 23 at 13:13
- The How2Tlectronics tutorialha a good newbie explanation on how to do the programming: Raspberry Pi Pico Complete Guide| Pinout + Features + ADC Tutorial (08:56) + I2C + OLED + Internal Temperature Sensor + DHT11: youtube.com/watch?v=oaM80GyVIwA&t=2s. – tlfong01 Apr 23 at 13:28
- The video tutorial part, starting from 08:56, actually points out why the ADC conversion results for 0V is not 0, but 200+. Perhaps we should do some modification to the program, as requested by the OP, to make the output range from 0 to 4096, instead of 200+ to 65536. – tlfong01 Apr 23 at 13:37
- Now the time has come for us to try to write a program to give an ADC output range of 0 to 4096. Stay tuned, … – tlfong01 Apr 24 at 3:31
- Update 2022may10 – (1) I just read that Pico ADC has a design bug, so I am considering an alternative: AD7705. (2) Reference: Raspberry Pi Pico ADC & Quick Experiments – TK Hareendran, Codrey Electronics, 2022may10 codrey.com/raspberry-pi/raspberry-pi-pico-adc-quick-experiments. – tlfong01 May 10 at 3:43
1 Answer
Sorted by: Highest score (default) Trending (recent votes count more) Date modified (newest first) Date created (oldest first)
3
Question
How to make Rpi Pico do ADC with an output range starting from zero, and hopefully no fluctuation of 10 to 20?
Answer
- I googled and found How2Electronics has a newbie friendly tutorial on Pico ADC, with a short demo code (References 1, 2. Appendices B, C).
- The demo code does not seem to have any problem as reported by the OP. So I decided to try the demo code in my Pico setup, to see if I can repeat the OP’s situation.
- I read the Pico datasheet which says that Pico ADC has an internal offset of about 30mV, and that its offset can be reduced by using an external voltage of 3.0V (Appendix D).
- Now the OP says his ADC results of 0V (signal grounded) always fluctuates between 10 and 20. So let me calculate if this 10~20 offset is within the Pico datasheet’s 20~30mV internal/intrinsic zero offset. Since Pico ADC resolution is 12 bit, and if 3V3 power rail is used as analog reference, then the intrinsic is 30mV / 3V * 4096 ~= 30/3000 * 4096 ~= 5 < 10. In other words, the OP’s zero offset seems twice the spec.
- I have not verified my always dodgy calculation. Perhaps I can verify it by working backwards: What is the offset in mV, if offset value is 20/4096. Suppose analog reference is 3V3, then offset in mV = 3V3 * (20/4096) = 3300mV * 20 / 4096 = 16mV, looks OK.
- Anyway, perhaps I can repeat the OP’s test and compare with his zero offsets.
- I modified/expanded How2Electronics’s demo program, to do the following: (a) Do ADC with the three ADC pins, ADC0, ADC1, ADC2, (b) Find max, min, avg values and print out results (Appdenix F).
- I then use the program to find the outputs of ADC0, 1, 2 pins connected to (a) Analog Ground, (b) Enabled 3V3. The ADC results are summarized below:— Sample Output — %Run -c $EDITOR_CONTENT Name = testPicoAdcV01() Function = test Pico ADC pins GP26, 27, 28 Date = 2022apr25hkt1111ADC Results = [368, 368, 336] (ADC0, 1, 2 connected Aanlog Gound) Max = 368 Min = 336 Avg = 357ADC Results = [65391, 65519, 65519] (ADC0, 1, 2 connected 3V3) Max = 65519 Min = 65391 Avg = 65476
The ADC output for (a) 3V3 input is avg 65476, and (b) Analog ground is avg is 357, or
ADC zero offset of 357/65476 = 5.45% ~= 5%, or 3V3 = 3300mV * 5% ~= 165mV.
- The Pico ADC error spec of 5% or 150mV (not yet verified) of measurement range of 3V3 does not seem reasonably good. So I am thinking of using an external 3V0 voltage reference for the Pico Analog Reference pin, hoping that accuracy could be improved. I will be using the voltage reference IC TL431 to check if it is good (Appendix H, Ref 5).
- Using a 2.5V external reference, the zero offset has improved to 0.4%, but still not very good. I would prefer to use AD7705, with two real differential input channels, built in PGA, and assembled modules with on board LM285-2.5 voltage references.
/ to continue, …
References
(1) How to use ADC in Raspberry Pi Pico – How2Electronics, 2021apr21
(3) Rpi Pico Datasheet (4.3. Using the ADC) – Rpi
(4) Raspberry Pi Pico 3.3V_EN pin control voltage inquiry – EE.SE, Asked 2021jun22, Viewed 1k times
(5) TL431 / TL432 Precision Programmable Reference IC – TI
(6) LM385B-2.5 2.5V Micropower Voltage References – TI
(7) Zonri ADS1256 24-Bit Sampling Module, ADC Module, Single/Differential Input – AliEXpress US$26
(8) AD7705 SPI 2 fully differential input channel 16-bit Σ-Δ ADC, PGA Datasheet – Analog Devices
/ to continue, …
Appendices
Appendix A – Rpi Pico ADC Pinout

Appendix B – Rpi Pico wiring for testing ADC program v0.1
------------------------------------------------------------------------------------
Pin name Pin # Connected to
-------------------------------------------------------------------------------------
Rpi 3V3 Output 36 -
Rpi 3V3 Enable 37 -
Analog Gnd 33 Rpi Pico Ground
Analog Ref 35 Rpi 3V3
ADC0 26 Rpi Ground
ADC1 27 Rpi 3V3
ADC2 28 2V5
ADC3 - Not available, connected to Pico internal temperature sensor
-------------------------------------------------------------------------------------
Appendix C – How2Eloectronics’s ADC Demo Code

Appendix D – How to improve ADC Performance
Rpi Pico Datasheet (4.3. Using the ADC) – Rpi
4.3. Using the ADC
The RP2040 ADC does not have an on-board reference and therefore uses its own power supply as a reference.
On Pico the ADC_AVDD pin (the ADC supply) is generated from the SMPS 3.3V by using an R-C filter (201 ohms into 2.2μF). This is a simple solution but does have the following drawbacks:
- We are relying on the 3.3V SMPS output accuracy which isn’t great
- We can only do so much filtering and therefore ADC_AVDD will be somewhat noisy
- The ADC draws current (about 150μA if the temperature sense diode is disabled, but it varies from chip to chip) and therefore there will be an inherent offset of about 150μA200 = ~30mV*. There is a small difference in current draw when the ADC is sampling (about +20μA) so that offset will also vary with sampling as well as operating temperature.
Changing the resistance between the ADC_VREF and 3V3 pin can reduce the offset at the expense of more noise – which may be OK especially if the use case can support averaging over multiple samples.
Driving high the SMPS mode pin (GPIO23), to force the power supply into PWM mode, can greatly reduce the inherent ripple of the SMPS at light load, and therefore the ripple on the ADC supply. This does reduce the power efficiency of the board at light load, so the low-power PFM mode can be re-enabled between infrequent ADC measurements by driving GPIO23 low once more. See Section 4.4.
The ADC offset can be reduced by tying a second channel of the ADC to ground, and using this zero-measurement as an approximation to the offset.
For much improved ADC performance, an external 3.0V shunt reference, such as LM4040, can be connected from the ADC_VREF pin to ground.
Note that if doing this the ADC range is limited to 0-3.0V signals (rather than 0-3.3V), and the shunt reference will draw continuous current through the 200R filter resistor (3.3V-3.0V)/200 = ~1.5mA.
Note that the 1R resistor on Pico (R9) is designed to (maybe) help with shunt references that would otherwise become unstable when directly connected to 2.2μF. It also makes sure there is a little filtering even in the case that 3.3V and ADC_VREF are shorted together (which is a valid thing to do if you don’t care about noise and want to reduce the inherent offset).
Finally, R7 is a physically large 1608 metric (0603) package resistor, so can be relatively easily removed if a user wants to isolate ADC_VREF and do their own thing with the ADC voltage, for example powering it from an entirely separate voltage (e.g. 2.5V). Note that the ADC on RP2040 has only been qualified at 3.0/3.3V but should work down to about 2V.
Appendix E – Pico 3V3 Enable pin to enable 3V3 Power
Raspberry Pi Pico 3.3V_EN pin control voltage inquiry – Asked 2021jun22, Viewed 1k times

Appendix F – Testing Pico’s 3 ADC Pins V0.1
programName = 'testPicoAdcV01()'
programFunction = 'test Pico ADC pins GP26, 27, 28'
programDate = '2022apr25hkt1111'
programAuthor = 'tlfong01'
systemInfo = 'Chinese Windows 10, Thonny IDE 3.3.13, Python 3.7.9, Rpi Pico'
import machine
import utime
# *** Configuration ***
adcPinNum0 = 26
adcPinNum1 = 27
adcPinNum2 = 28
adcPin0 = machine.ADC(adcPinNum0)
adcPin1 = machine.ADC(adcPinNum1)
adcPin2 = machine.ADC(adcPinNum2)
adcPinDict = \
{
'0' : {
'AdcPinNum': 0,
'AdcPin' : adcPin0,
},
'1' : {
'AdcPinNum': 1,
'AdcPin' : adcPin1,
},
'2' : {
'AdcPinNum': 2,
'AdcPin' : adcPin2,
},
}
# *** Adc Functions ***
def getAdcResults(adcPinNum):
adcPin = adcPinDict[str(adcPinNum)]['AdcPin']
adcResults = adcPin.read_u16()
return adcResults
# *** Sample Test ***
#adcResults = getAdcResults(adcPinNum = 0)
#print(adcResults)
def getAdcResultsList(adcPinNumList):
adcResultsList = [0] * len(adcPinNumList)
for adcPinNum in adcPinNumList:
adcResults = getAdcResults(adcPinNum)
adcResultsList[adcPinNum] = adcResults
return adcResultsList
# *** Sample Tests ***
#adcResultsList = getAdcResultsList([0, 1, 2])
#print(adcResultsList)
def printAdcResultsList(adcResultsList):
print('ADC Results =', adcResultsList)
print('Max =', max(adcResultsList))
print('Min =', min(adcResultsList))
print('Avg =', (sum(adcResultsList)) / len(adcResultsList))
return
# *** Sample Tests ***
#adcResultsList = getAdcResultsList([0, 1, 2])
#printAdcResultsList(adcResultsList)
def testPicoAdcV01():
print('Name =', programName)
print('Function =', programFunction)
print('Date =', programDate)
adcResultsList = getAdcResultsList([0, 1, 2])
printAdcResultsList(adcResultsList)
return
# *** Main ***
testPicoAdcV01()
# *** End of Program ***
# *** Sample Output ***
'''
>>> %Run -c $EDITOR_CONTENT
Name = testPicoAdcV01()
Function = test Pico ADC pins GP26, 27, 28
Date = 2022apr25hkt1102
ADC Results = [208, 20645, 17828]
Max = 20645
Min = 208
Avg = 12893.67
>>>
'''
# *** End of sample output ***
Appendix G – ADC results with ADC0, 1, 2 connected to (a) Analog Ground, (b) Enabled 3V3 Output
Complete program listing with sample output
# *** Sample Output ***
'''
>>> %Run -c $EDITOR_CONTENT
Name = testPicoAdcV01()
Function = test Pico ADC pins GP26, 27, 28
Date = 2022apr25hkt1111
ADC Results = [368, 368, 336] (ADC0, 1, 2 connected Aanlog Gound)
Max = 368
Min = 336
Avg = 357
ADC Results = [65391, 65519, 65519] (ADC0, 1, 2 connected 3V3)
Max = 65519
Min = 65391
Avg = 65476
>>>
'''
Appendix H – Rpi Pico ADC External Analog Voltage Reference Using TL431


Appendix I – Rpi Pico ADC External Analog Voltage Reference Using TI LM385B25 2V5 Volgtage References
LM385B-2.5 Micropower Voltage References – TI


Appendix J – Zonri ADS1256 24-bit ADC Module to calibrate Rpi Pico ADC Pins

Appendix K – AD7705 16-bit ADC to Calibrate Rpi Pico ADC
(8) AD7705 SPI 2 fully differential input channel 16-bit Σ-Δ ADC Datasheet – Analog Devices
(9) AD7705 16-Bit ADC Module, Input Gain, Programmable SPI Interface, TM7705- AliExpress US$1.2


/ to continue in TEAMS, …
.END
EditDeleteFlag
answered Apr 24 at 3:38

30044 silver badges88 bronze badges
Categories: Uncategorized