Raspberry pi PICO ADC 读数
Raspberry pi PICO ADC reading
在 Raspberry Pi Pico 上获取 ADC 读数时,为什么不得到 零 ?即使我将 ADC 引脚接地,模拟读数始终在 10 到 20 之间波动。如何将模拟读数减少到零?
问题
如何让Rpi Pico做ADC,输出范围从0开始,希望没有10到20的波动?
回答
我用谷歌搜索发现 How2Electronics 有一个关于 Pico ADC 的新手友好教程,带有简短的演示代码(参考 1、2。附录 B、C)。
演示代码似乎没有OP报告的任何问题。所以我决定在我的 Pico 设置中尝试演示代码,看看我是否可以重复 OP 的情况。
我读了 Pico 数据表,上面说 Pico ADC 有 大约 30mV 的内部偏移,并且使用 3.0V 的外部电压 (附录 D)可以减少其偏移量。
现在 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 的零偏移似乎规格的两倍。
一向狡猾的计算我还没有验证。也许我可以通过倒推来验证它:如果偏移值为 20/4096,偏移量是多少 mV。假设模拟参考是 3V3,那么偏移 mV = 3V3 * (20/4096) = 3300mV * 20 / 4096 = 16mV,看起来没问题。
无论如何,也许我可以重复OP的测试并与他的零偏移量进行比较。
我modified/expandedHow2Electronics的demo程序,做如下操作:
(a) 使用三个 ADC 引脚 ADC0、ADC1、ADC2 进行 ADC,(b) 查找最大值、最小值、平均值并打印出结果(附录 F)。
然后我使用该程序找到连接到 (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.
5%或150mV(尚未验证)3V3测量范围的Pico ADC误差规格似乎不太好。因此,我正在考虑为 Pico Analog Reference 引脚使用外部 3V0 电压参考,希望可以提高精度。我将使用电压参考 IC TL431 来检查它是否正常(附录 H,参考 5)。
使用2.5V外部参考,零偏移改善为0.4%,但仍然不是很大好的。我更愿意使用 AD7705,具有两个真正的差分输入通道,内置 PGA,以及带有板载 LM285-2.5 电压基准的组装模块。
/ 继续,...
参考文献
(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
(8) AD7705 SPI 2 fully differential input channel 16-bit Σ-Δ ADC, PGA Datasheet - Analog Devices
/ 继续,...
附录
附录 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 产生的。这是一个简单的解决方案,但确实有以下缺点:
我们依赖 3.3V SMPS 输出精度,这不是很好
我们只能做这么多过滤,因此ADC_AVDD会有些嘈杂
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
在 Raspberry Pi Pico 上获取 ADC 读数时,为什么不得到 零 ?即使我将 ADC 引脚接地,模拟读数始终在 10 到 20 之间波动。如何将模拟读数减少到零?
问题
如何让Rpi Pico做ADC,输出范围从0开始,希望没有10到20的波动?
回答
我用谷歌搜索发现 How2Electronics 有一个关于 Pico ADC 的新手友好教程,带有简短的演示代码(参考 1、2。附录 B、C)。
演示代码似乎没有OP报告的任何问题。所以我决定在我的 Pico 设置中尝试演示代码,看看我是否可以重复 OP 的情况。
我读了 Pico 数据表,上面说 Pico ADC 有 大约 30mV 的内部偏移,并且使用 3.0V 的外部电压 (附录 D)可以减少其偏移量。
现在 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 的零偏移似乎规格的两倍。
一向狡猾的计算我还没有验证。也许我可以通过倒推来验证它:如果偏移值为 20/4096,偏移量是多少 mV。假设模拟参考是 3V3,那么偏移 mV = 3V3 * (20/4096) = 3300mV * 20 / 4096 = 16mV,看起来没问题。
无论如何,也许我可以重复OP的测试并与他的零偏移量进行比较。
我modified/expandedHow2Electronics的demo程序,做如下操作: (a) 使用三个 ADC 引脚 ADC0、ADC1、ADC2 进行 ADC,(b) 查找最大值、最小值、平均值并打印出结果(附录 F)。
然后我使用该程序找到连接到 (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.
5%或150mV(尚未验证)3V3测量范围的Pico ADC误差规格似乎不太好。因此,我正在考虑为 Pico Analog Reference 引脚使用外部 3V0 电压参考,希望可以提高精度。我将使用电压参考 IC TL431 来检查它是否正常(附录 H,参考 5)。
使用2.5V外部参考,零偏移改善为0.4%,但仍然不是很大好的。我更愿意使用 AD7705,具有两个真正的差分输入通道,内置 PGA,以及带有板载 LM285-2.5 电压基准的组装模块。
/ 继续,...
参考文献
(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
(8) AD7705 SPI 2 fully differential input channel 16-bit Σ-Δ ADC, PGA Datasheet - Analog Devices
/ 继续,...
附录
附录 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 产生的。这是一个简单的解决方案,但确实有以下缺点:
我们依赖 3.3V SMPS 输出精度,这不是很好
我们只能做这么多过滤,因此ADC_AVDD会有些嘈杂
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