Raspberry pi PICO ADC 读数

Raspberry pi PICO ADC reading

Raspberry Pi Pico 上获取 ADC 读数时,为什么不得到 ?即使我将 ADC 引脚接地,模拟读数始终在 10 到 20 之间波动。如何将模拟读数减少到零?

问题

如何让Rpi Pico做ADC,输出范围从0开始,希望没有10到20的波动?


回答

  1. 我用谷歌搜索发现 How2Electronics 有一个关于 Pico ADC 的新手友好教程,带有简短的演示代码(参考 1、2。附录 B、C)。

  2. 演示代码似乎没有OP报告的任何问题。所以我决定在我的 Pico 设置中尝试演示代码,看看我是否可以重复 OP 的情况。

  3. 我读了 Pico 数据表,上面说 Pico ADC 有 大约 30mV 的内部偏移,并且使用 3.0V 的外部电压 (附录 D)可以减少其偏移量。

  4. 现在 OP 说他的 0V(信号接地)ADC 结果总是在 10 到 20 之间波动。所以让我计算一下这个 10~20 的偏移量是否在 Pico 数据表的 20~30mV internal/intrinsic 零偏移量。由于 Pico ADC 分辨率为 12 位,如果使用 3V3 电源轨作为模拟参考,则本征为 30mV / 3V * 4096 ~= 30/3000 * 4096 ~= 5 < 10。换句话说,OP 的零偏移似乎规格的两倍。

  5. 一向狡猾的计算我还没有验证。也许我可以通过倒推来验证它:如果偏移值为 20/4096,偏移量是多少 mV。假设模拟参考是 3V3,那么偏移 mV = 3V3 * (20/4096) = 3300mV * 20 / 4096 = 16mV,看起来没问题。

  6. 无论如何,也许我可以重复OP的测试并与他的零偏移量进行比较。

  7. 我modified/expandedHow2Electronics的demo程序,做如下操作: (a) 使用三个 ADC 引脚 ADC0、ADC1、ADC2 进行 ADC,(b) 查找最大值、最小值、平均值并打印出结果(附录 F)。

  8. 然后我使用该程序找到连接到 (a) 模拟地,(b) 启用 3V3 的 ADC0、1、2 引脚的输出。 ADC 结果总结如下:

    --- 示例输出 --- %运行 -c $EDITOR_CONTENT 名称 = testPicoAdcV01() 功能 = 测试 Pico ADC 引脚 GP26、27、28 日期 = 2022apr25hkt1111

    ADC 结果 = [368、368、336](ADC0、1、2 连接 Aanlog Gound) 最大值 = 368 最小 = 336 平均 = 357

    ADC 结果 = [65391、65519、65519](ADC0、1、2 连接 3V3) 最大值 = 65519 最小 = 65391 平均 = 65476

(a) 3V3 输入的 ADC 输出是 avg 65476,(b) 模拟地是 avg 是 357,或者

357/65476 的 ADC 零偏移 = 5.45% ~= 5%,或 3V3 = 3300mV * 5% ~= 165mV.

  1. 5%或150mV(尚未验证)3V3测量范围的Pico ADC误差规格似乎不太好。因此,我正在考虑为 Pico Analog Reference 引脚使用外部 3V0 电压参考,希望可以提高精度。我将使用电压参考 IC TL431 来检查它是否正常(附录 H,参考 5)。

  2. 使用2.5V外部参考,零偏移改善为0.4%,但仍然不是很大好的。我更愿意使用 AD7705,具有两个真正的差分输入通道,内置 PGA,以及带有板载 LM285-2.5 电压基准的组装模块。


/ 继续,...


参考文献

(1) How to use ADC in Raspberry Pi Pico - How2Electronics, 2021apr21

(2) Raspberry Pi Pico Complete Guide [Pinout + Features + ADC (08:56) + I2C + OLED + Internal Temperature Sensor + DHT11 - How2Electronics

(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

(8) AD7705 SPI 2 fully differential input channel 16-bit Σ-Δ ADC, PGA Datasheet - Analog Devices

(9) AD7705/TM7705 16-Bit ADC Module, Input Gain, Programmable SPI Interface, (LM285-2.5 external voltage reference)- AliExpress US.2


/ 继续,...


附录

附录 A - Rpi Pico ADC 引出线


附录 B - 用于测试 ADC 程序 v0.1 的 Rpi Pico 接线

------------------------------------------------------------------------------------
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
-------------------------------------------------------------------------------------

附录 C - How2Eloectronics 的 ADC 演示代码


附录 D - 如何提高 ADC 性能

Rpi Pico Datasheet (4.3. Using the ADC) - Rpi

4.3。使用 ADC

RP2040 ADC 没有 on-board 参考,因此使用它自己的电源作为参考。

在 Pico 上,ADC_AVDD 引脚(ADC 电源)是通过使用 R-C 滤波器(201 欧姆到 2.2μF)从 SMPS 3.3V 产生的。这是一个简单的解决方案,但确实有以下缺点:

  1. 我们依赖 3.3V SMPS 输出精度,这不是很好

  2. 我们只能做这么多过滤,因此ADC_AVDD会有些嘈杂

  3. ADC消耗电流(温度检测二极管关闭时约为150μA,但因芯片而异o 芯片),因此 将存在大约 150μA200 = ~30mV* 的固有偏移。 ADC 采样时的电流消耗略有不同(约 +20μA),因此偏移量也会随采样和工作温度而变化。

改变 ADC_VREF 和 3V3 引脚之间的电阻可以减少偏移,但会增加噪声 - 这可能没问题,特别是如果用例可以支持多个样本的平均。

将 SMPS 模式引脚 (GPIO23) 拉高,强制电源进入 PWM 模式,可以大大降低 SMPS 在轻负载时的固有纹波,从而降低 ADC 电源上的纹波。这确实会降低电路板在轻负载时的电源效率,因此 low-power PFM 模式可以通过再次将 GPIO23 驱动为低电平在不频繁的 ADC 测量之间 re-enabled。参见第 4.4 节。

可以通过将 ADC 的第二个通道接地并使用此 zero-measurement 作为偏移的近似值来减少 ADC 偏移。

为了大大提高 ADC 性能,可以将外部 3.0V 分流基准(例如 LM4040)从 ADC_VREF 引脚接地。

请注意,如果这样做,ADC 范围仅限于 0-3.0V 信号(而不是 0-3.3V),并且分流参考将通过 200R 滤波电阻器(3.3V-3.0V)汲取连续电流/200 = ~1.5mA.

请注意,Pico (R9) 上的 1R 电阻器旨在(可能)帮助分流参考,否则当直接连接到 2.2μF 时会变得不稳定。它还确保即使在 3.3V 和 ADC_VREF 短路在一起的情况下也有一点过滤(如果您不关心噪声并想减少固有偏移,这是一个有效的做法)。

最后,R7 是一个物理尺寸较大的 1608 公制 (0603) 封装电阻器,因此如果用户想要隔离 ADC_VREF 并自行处理 ADC 电压,例如供电,则可以相对轻松地移除它来自一个完全独立的电压(例如 2.5V)。请注意,RP2040 上的 ADC 仅在 3.0/3.3V 下合格,但应该可以低至 2V 左右工作。


附录 E - Pico 3V3 启用引脚启用 3V3 电源

Raspberry Pi Pico 3.3V_EN pin control voltage inquiry - Asked 2021jun22, Viewed 1k times


附录 F - 测试 Pico 的 3 个 ADC 引脚 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 ***

附录 G - ADC0、1、2 连接到 (a) 模拟地,(b) 启用 3V3 输出的 ADC 结果

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
>>> 
'''

附录 H - 使用 TL431 的 Rpi Pico ADC 外部模拟电压参考



附录 I - 使用 TI LM385B25 2V5 电压参考的 Rpi Pico ADC 外部模拟电压参考

LM385B-2.5 Micropower Voltage References - TI




附录 J - Zonri ADS1256 24 位 ADC 模块校准 Rpi Pico ADC 引脚


附录 K - 用于校准 Rpi Pico ADC 的 AD7705 16 位 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.2

/ 继续 TEAMS, ...


.END