用Raspberry Pi Pico和MicroPython实现ADC数据采集与波形可视化
在嵌入式学习路径里“读一个模拟信号”这个需求会出现在很多地方旋钮调音量、电池电量检测、传感器输出读取、光敏电阻判断亮度。这些本质上都是同一个动作——用ADC把电压变成数字。Raspberry Pi Pico作为一块带12位ADC、价格又便宜的开发板特别适合把这件事一次性讲透。这篇文章我按照自己的实操过程从硬件接线到MicroPython代码再到SerialPlot串口波形可视化完整走一遍Pico读电位器、控制LED亮度、实时绘制波形的全过程。你会看到每个关键参数怎么选、每根线为什么这么接、代码里那个数字为什么是65535而不是4096、SerialPlot为什么一行文本就能画出动态曲线。整个过程不需要额外买昂贵设备一块Pico、一个电位器、一个LED再加几根杜邦线就能开干。1. 项目整体设计与思路拆解先说清楚这个项目想解决什么问题验证Pico的ADC功能是否正常、手感是否灵敏、数值是否稳定并且让采集结果看得见。很多人第一次接触ADC拿着万用表量了半天最后只看到串口里刷出一堆跳动的数字既不知道准不准也不知道和实际电压有什么关系。所以我这个设计里加入了两个可视化手段——LED亮度和SerialPlot波形一个是直观体现数值变化的物理量一个是精确呈现数值细节的软件曲线。在方案选型上用电位器作为信号源是最合理的。电位器本质是一个三端可变电阻中间抽头输出的电压随着旋钮角度线性变化在0V到参考电压之间连续可调。这比用拨码开关、按键去模拟数字信号要真实得多也最能体现模拟量的特点。LED作为输出端不只是为了闪灯而是让ADC采集到的小数范围变得触手可及——你旋动电位器LED随之亮暗直觉反应就是ADC读到了一个正在变化的电压。1.1 为什么选Pico而不是其他板子Pico在当前这个价位段ADC配置是很有诚意的。大多数人熟悉的STM32虽然也是12位ADC但需要配置时钟树、采样周期、通道映射一系列寄存器新手容易在半路放弃。Pico配合MicroPython只需要一行machine.ADC(pin)就能拿到原始值这个极低的上手门槛让我在入门阶段能更集中精力理解ADC本身的机制而不是和寄存器搏斗。不过Pico的ADC通道数量有限一共有4个可用通道其中3个引到了GPIO引脚上GPIO26对应ADC0、GPIO27对应ADC1、GPIO28对应ADC2第4个通道在芯片内部专门读取板载温度传感器的输出电压。实际项目中如果传感器数量多就得考虑外扩ADC芯片比如ADS1115或者换用带更多ADC通道的芯片。就入门验证和技术原理学习来说Pico这个配置刚刚好。还有一个关键点Pico的ADC采样精度是12位但MicroPython的ADC.read_u16()返回的是16位范围的值0到65535。很多人在这一步被绕晕以为Pico的ADC精度是16位。实际上这是MicroPython为了方便和PWM的16位占空比范围对齐把12位的采样结果左移了4位。后面代码部分我再细说这个映射关系。1.2 板载LED和外部LED如何分工我在这套电路里用了两处LED一处是Pico板载的LED连接在GPIO25上另一处是外接到GPIO16的LED。这样设计的好处是能直观对比两种控制方式——板载LED我只用普通GPIO做简单亮灭验证电路基本工作外部LED接在PWM通道上通过调整占空比实现无级调光验证真正的模拟输出效果。如果你的LED亮度变化断层感明显很可能是PWM频率设置不合理。Pico的PWM默认频率大约1kHz对人眼来说已经足够平滑但如果换到某些相机拍摄环境会出现频闪纹。我在这个项目里把频率设到5kHz视觉效果和录制视频都更稳定。同时注意LED必须串联限流电阻Pico的GPIO输出不宜长期超过10mA电流太大轻则LED烧坏重则损伤引脚。1.3 ADC工作的基本原理ADC全称Analog-to-Digital Converter中文叫模数转换器。它的工作就是把连续的电压信号离散成一个个数字。Pico内置的是SAR型ADC全称逐次逼近型ADC。你可以把它想象成一台天平秤先用一个较大的砝码比如参考电压的一半试探比较输入电压和砝码大小大了就减砝码小了就加砝码每次试探都让砝码重量减半经过若干次逼近后砝码的总重量就近似等于输入电压。对于12位ADC这个过程需要12次比较能够区分2^12即4096个不同电压等级。如果参考电压是3.3V那么每一个最小量化单位对应3.3V/4096约等于0.8mV。也就是说Pico的ADC能分辨约0.8mV的电压变化。这个精度放到日常旋钮控制、传感器读取场景完全够用但如果你要测微伏级的微弱信号就得考虑外部高精度ADC了。2. 硬件设计与连接细节很多人拿到开发板第一件事就是插上USB线开始写代码等到要接传感器才开始翻引脚图。我的习惯是先把硬件连接想清楚再动手因为接线错误会直接烧坏组件或者导致采样结果离谱排查起来比写代码还费时间。2.1 元件清单与接线表这套项目用到的元件很少大部分人会手头就有Raspberry Pi Pico带排针版本或者裸板加面包板面包板1个10kΩ电位器1个B型线性旋钮普通LED 1个颜色随意红色绿色都行220Ω限流电阻1个杜邦线若干接线是整个项目最直观的部分我把完整的连接对应关系放在下面Pico引脚连接目标关键说明3V3_OUTPin36电位器第1脚提供3.3V参考电压AGNDPin33电位器第3脚模拟地与数字地共用ADC0GPIO26Pin31电位器第2脚中间抽头采集分压电压GP16Pin21电阻LED正极PWM输出控制亮度GND任一接地点LED负极形成电流回路GP25板载LED无需外接验证程序基础运行有几个细节我要特别提醒电位器的三个引脚第1、3脚接的是固定电压两端第2脚是滑动端。接反了问题也不大只是旋钮方向相反。但如果你把3V3和GND接反芯片会直接烧掉。杜邦线选母对公或者公对公看你的面包板类型我这里用的是公对公跳线。2.2 为什么电位器输出端必须连接到AGND而不是其他GNDPico的引脚设计里AGND和GND都在Pin33附近很多新手会随手插到最近的GND。从原理上看AGND是ADC模块的独立参考地数字地是有噪声的——板上高速数字信号的电流变化会在GND上形成微小压差如果ADC的参考地和数字地之间有明显电压差采样结果会周期性跳动。我在实际测试中对比过把电位器地线接到普通GND采样曲线在高低电平切换时毛刺明显增多平均偏差大约有十几mV改接到AGND后基线明显干净。所以凡是模拟信号相关的地线都建议统一走AGND。数字器件比如LED、按键的地线也最终汇聚到同一个GND本质上数字地和模拟地最终是要相通的只是模拟部分尽量单独走线避免数字开关噪声直接耦合进模拟采样回路。2.3 LED驱动电路注意事项LED内部是PN结导通压降大约在1.8V到3.3V之间红黄LED约1.8V蓝白LED约3.0V以上它不能像电阻那样直接跨接在电源两端必须用限流电阻限制电流。如果直接用GPIO的3.3V去驱动一个红光LED而不加电阻电流可能瞬间达到几十毫安LED很快过热GPIO引脚也会因为过流而性能下降甚至损坏。限流电阻的取值公式是R (Vcc - Vf) / If。其中Vcc是GPIO高电平电压约3.3VVf是LED的正向压降红色LED取1.8VIf是期望电流典型值10mA。计算得到(3.3-1.8)/0.01等于150Ω我手边只有220Ω用220Ω也没问题只是亮度稍微低一点更安全。注意PWM输出也是高电平脉冲占空比100%时的电压就是3.3V所以限流电阻同样必要。3. 代码实现与核心逻辑硬件接好以后最重要的就是把逻辑跑通。我习惯先用一个最小的脚本验证ADC读数是否正常确认电位器转动对应电压变化再添加LED控制和串口输出最后接SerialPlot。这样分步骤排查每一步出错都容易定位。3.1 创建项目文件和基础环境Pico在MicroPython环境下开发首先需要将MicroPython固件烧录到板子里。去树莓派官网下载对应的UF2文件按住Pico板载BOOTSEL键的同时插入USB线计算机上会弹出一个名为RPI-RP2的U盘把UF2文件拖进去板子会自动重启烧录完成。之后用Thonny编辑器写代码选择MicroPython (Raspberry Pi Pico)解释器连接串口就能在线运行。项目文件结构很简单我在Pico内部新建一个main.py作为主程序这样上电会自动运行。也可以在Thonny里直接编写代码按运行按钮效果一样。目录结构pico_adc_led/ ├── main.py # 主程序包含ADC读取、PWM控制、串口输出 └── (可选) 测试脚本.py # 单独测试ADC或PWM的小脚本3.2 最简ADC读取代码from machine import ADC, Pin import time # 创建ADC对象GPIO26对应ADC0 adc ADC(Pin(26)) while True: # 读取原始值范围0~65535 raw_value adc.read_u16() # 打印原始值和对应的电压 print(raw , raw_value, voltage , round(raw_value * 3.3 / 65535, 2)) time.sleep(0.1)运行这个脚本旋转电位器串口打印的数字会在0到65535之间变化。如果电位器旋到一端时接近0、另一端接近65535说明接线正确。如果数值一直在0或者一直在65535不变优先检查电位器第2脚是否接到GPIO26、第1脚是否接到3V3。这里解释一下read_u16()返回65535这个数Pico的ADC物理分辨率是12位也就是能输出0到4095的范围。MicroPython为了方便用户直接对接PWM的16位占空比控制自动把12位结果左移4位等效到0到65535。计算电压时有两种方式一种是用65535作为满量程分母因为read_u16返回的就是16位范围另一种是先把数值右移4位恢复成12位范围再除以4095。两种算法结果一致。我用的是前一种在代码注释里写明3.3V对应65535。3.3 ADC数值与真实电压的换算ADC的最终目的是还原真实世界的模拟量。对于Pico来说参考电压是3.3V所以电压值 read_u16() × 3.3 / 65535比如串口输出raw 32768对应电压约1.65V正好是电位器旋转到中间位置时的分压值。这个换算思路后面扩展其他传感器时同样适用比如光敏电阻和固定电阻组成分压电路时读取的电压值能反推出光敏电阻的阻值进一步推断环境亮度。需要注意的是Pico的3.3V电源是从USB的5V经过板载稳压得到的它本身有一定误差不同板子之间可能有几十mV差异。如果项目对绝对电压精度要求高可以用万用表实测3V3输出比如实测3.28V就把代码里的3.3改为3.28。这个修正看似微小对于锂电池电压监测、精密传感器读取场景影响很明显。3.4 加入LED控制和PWM实现调光接下来加入LED控制。LED亮度如果只用GPIO高/低电平只能实现亮或灭两种状态无法体现ADC数值的连续变化。所以我给GPIO16配置成PWM输出通过改变占空比实现0到100%的调光from machine import ADC, Pin, PWM import time adc ADC(Pin(26)) led PWM(Pin(16)) led.freq(5000) # 设置PWM频率5kHz避免LED频闪 def clamp(value, min_value0, max_value65535): 将数值限制在指定范围内 return max(min_value, min(value, max_value)) while True: raw_value adc.read_u16() # 直接将ADC读数作为PWM占空比 led.duty_u16(raw_value) voltage raw_value * 3.3 / 65535 print(raw , raw_value, voltage , round(voltage, 2)) time.sleep(0.05)PWM的占空比也是一个0到65535的16位值所以ADC的读数可以直接映射到PWM占空比上不需要额外的缩放。旋钮转到一端LED最暗约0%亮度另一端最亮约100%亮度。这个直接映射还有一个好处——系统响应非常线性旋钮的旋转角度与LED亮度几乎一致。如果感觉LED在低亮度区域有抖动可以在循环里加入几个采样值取平均或者用软件滤波。我后面会专门讲滤波。还有个细节PWM引脚选GPIO16是因为它支持PWM功能实际上Pico上大多数GPIO都支持PWM只要不是特殊用途引脚比如ADC专用引脚就行。这个设计前后一致性很好ADC值和PWM值范围相同连数据类型都不用转换。3.5 完整主程序带滤波和串口输出为了让SerialPlot能绘制平滑曲线我在最终代码里加了一阶低通滤波滤除信号中高频噪声。这个滤波的实现原理非常简单新值等于上次的值乘以一个平滑系数加上当前采样值乘以另一部分。系数越大滤得越干净但响应越迟钝。我取alpha为0.2意思是每次更新只采纳20%的新数据80%保留历史信息这样既能看到电位器变化的趋势又能压掉大多数抖动from machine import ADC, Pin, PWM import time adc ADC(Pin(26)) led PWM(Pin(16)) led.freq(5000) # 初始化滤波值为第一次读取的ADC filtered adc.read_u16() def low_pass_filter(new_sample, last_sample, alpha0.2): 一阶低通滤波器 new_sample: 最新采样值 last_sample: 上一次滤波结果 alpha: 平滑系数0~1之间越小越平滑 return alpha * new_sample (1 - alpha) * last_sample while True: raw_value adc.read_u16() filtered low_pass_filter(raw_value, filtered, 0.2) led.duty_u16(int(filtered)) # 输出两个值供SerialPlot绘制双通道曲线 print({},{}.format(raw_value, int(filtered))) time.sleep(0.01)串口输出格式用的是raw,filtered两个值逗号分隔。SerialPlot的文本解析协议恰好支持这种格式一行中的多个逗号分隔值会被视为多个通道。如果你只想画一条波形输出一个值就够了。在这个项目里我特意同时输出原始值和滤波值方便你直观看到低通滤波的效果。3.6 为什么串口输出一行要加换行SerialPlot和普通的串口助手一样是以行为单位解析数据的。print()函数默认会在末尾加回车换行这正是SerialPlot需要的结束标志。如果直接在MicroPython里用sys.stdout.write()就必须手动加上\n不然SerialPlot会一直等待一行数据结束波形不更新。另外注意打印的数据量不要太大。MicroPython在每次print时都会短暂阻塞CPU如果循环里同时做ADC采样和print频率太高会导致采样间隔不均匀波形看起来会有一跳一跳的顿挫感。我在这版代码里用的sleep(0.01)即1000Hz左右输出SerialPlot绘制这个频率的波形已经足够流畅而且不会给USB通信造成太大压力。4. SerialPlot 串口波形可视化看到这里你已经拥有了一个电位器→ADC→PWM→LED的完整闭环系统。但一个人盯着串口助手刷数字时间长了谁也看不出规律。要找规律就得把数据画成曲线。SerialPlot是我试过的几个串口绘图工具里最适合这个场景的——免费、轻量、解析简单还支持多通道绘制。4.1 SerialPlot的工作机制SerialPlot本质上是一个串口数据接收器和实时绘图器。它从串口读取数据流按文本协议拆分数据把每个通道的数据作为纵坐标绘制在时间轴上。横坐标可以是采样点数或时间。它支持两种主要协议文本协议逗号分隔数值和二进制协议。Pico的MicroPython用print输出逗号分隔文本天然匹配SerialPlot的默认文本格式。和市面上其他工具相比SerialPlot最大的好处是上手零门槛打开软件选对串口号和波特率点击Connect就能看到波形。市面上另一款常用工具是Processing自带的串口绘图但需要写额外代码还有Arduino IDE自带的Serial Plotter效果也不错但只能画一个串口的数据通道数量有限而且只支持Arduino环境。SerialPlot则独立于任何开发环境只要是串口输出文本数据它都能画。4.2 连接与配置步骤首先确保Pico通过USB线连接到电脑设备管理器里能看到一个COM口在Thonny里运行程序后该串口被占用。这时要关闭Thonny里与Pico连接的终端窗口因为同一串口不能同时被多个程序打开。然后打开SerialPlot按下面的步骤操作在Port下拉框选择Pico对应的COM口可以拔插USB线对比确认哪个是新增的端口Baud rate选择115200与MicroPython的默认USB串口波特率一致USB CDC虚拟串口的波特率实际上自动匹配但SerialPlot要求设置保持115200即可新版本的SerialPlot需要在Format区域选择ASCII或TXT格式点击右上角的Connect按钮波形区域就会开始滚动显示曲线如果波特率不匹配常见现象是波形完全不更新、随机乱码、或者一条直线不变。设置时建议确认和Thonny里右下角显示的波特率一致。Pico的USB串口本质上是虚拟串口不受真正波特率限制但SerialPlot依然按所选波特率解析流所以不同波特率可能会得到截然不同的解析结果。4.3 数据格式与多通道显示SerialPlot的文本协议规则很清晰一行文本中包含N个逗号分隔的数值就对应N个通道。比如我的代码输出raw,filtered那SerialPlot就会显示两条曲线左侧图例依次为Channel 1和Channel 2。比如在程序里输出三个值它就会画三条曲线。如果只想显示其中某条曲线可以在SerialPlot的曲线列表里单独勾选或取消。如果发现两条曲线完全重叠可能是滤波系数存在bug或者值被无条件赋值成了同一个变量。另外SerialPlot默认的纵坐标范围是固定的如果数据都在0到100之间跳动看起来像一条水平直线但换到0到65535范围就会呈现明显坡度。这个可以在纵轴设置里调整范围。4.4 用SerialPlot验证滤波效果接上SerialPlot以后我做的第一件事是快速转动电位器并松开。你会看到RAW通道的波形在停止转动后仍然存在细密的高频抖动而FILTERED通道的抖动幅度明显减小曲线更圆润。这就是低通滤波在起作用旋钮突然变化引起的大幅阶跃会同时体现在两条曲线上而静止时的微小噪声被滤波器削平了。为了让这个对比更清晰我把alpha调到0.05更平滑波形几乎变成一条缓慢变化的平滑曲线。代价是电位器快速旋转时LED的亮度变化明显滞后——滤波本质上是用响应速度换稳定性。具体工程里选多大alpha取决于信号是慢变的光照强度还是快速变化的音频信号。音频信号要尽量小的滤波光照传感器可以大胆平滑。5. 调试技巧与常见问题排查我在这个项目里踩过不少坑很多问题不是代码逻辑问题而是硬件连接、串口占用、参数理解方面的低级错误。把这些问题整理成速查表你照着排查能省很多时间。5.1 常见问题速查表问题现象可能原因解决方案串口输出无数据程序没运行/板卡未正确连接点击Thonny运行按钮查看MicroPython终端是否有输出串口输出乱码SerialPlot波特率设置错误设置串口为115200且确保SerialPlot和Thonny不同时占用端口ADC读数始终为0电位器接线错误/GPIO选错检查电位器第2脚是否接GPIO263V3和GND是否接在第1/3脚ADC读数始终为65535电位器第2脚悬空或接触不良重新插拔杜邦线排除面包板接触问题LED不亮限流电阻过大/GPIO引脚错检查LED极性和GPIO16连接确认PWM占空比不是0LED亮度跳跃不连续PWM频率过低设置led.freq(5000)以上SerialPlot无波形更新串口被占用/数据格式不匹配关闭Thonny终端确认输出是逗号分隔文本波形锯齿明显采样间隔不均匀/滤波不足减少sleep时间、使用低通滤波电压读数偏高或偏低3V3实际输出与理论值有偏差用万用表量取实际3V3修改换算系数5.2 关于ADC使用中容易被忽略的引脚限制Pico的ADC输入要求电压不高于3.3V。如果你试图用5V传感器输出直接接GPIO26会损坏ADC输入级。很多传感器模块比如土壤湿度模块、光敏模块明确标注是3.3V供电才能使用但在5V单片机上用多了顺手就接到了5V输出上这个坑我见过很多次。如果传感器输出范围是0到5V需要先经过电阻分压或电平转换电路再接Pico。简单的分压电路是两个电阻R1接传感器输出R2接地中点接入Pico。根据分压公式R2/(R1R2)乘以5V得到最终电压要让最终电压在3.3V以下选R110kΩ、R220kΩ即可将5V降到约3.33V。此外Pico的ADC采样在高速率下需要信号源内阻较低。电位器本身动辄10kΩ确实会在信号源与ADC采样电容之间形成RC延迟影响高速采样的准确性。我们这个项目只有千赫兹级别的采样率影响不大但如果你打算用Pico做音频采样就要注意信号源驱动能力的问题。5.3 电源纹波对ADC的影响Pico的3.3V稳压输出并非理想电压源当板子功耗波动较大时比如点亮大电流LED、驱动电机3.3V会有几毫伏到几十毫伏的纹波。ADC采样时如果参考电压本身在波动任何值都会跟着波动串口里表现为稳定的偏差或周期性正弦波动。我在调试中遇到过一次很有意思的现象LED亮度和ADC读数存在相关性LED越亮ADC读到的值越低。排查后发现是同一时刻电机启动导致3V3跌落。解决办法是LED的供电不要从3V3取电或者从USB 5V端取电经过独立稳压芯片给模拟电路供电。即使是纯LED项目也建议LED的电源和ADC参考电源分开简单办法是LED正极接5V外接电源PWM只控制GPIO引脚的电平中间的压差由限流电阻和LED自身承担。5.4 如何判断ADC采样结果的准确性离线测试中我发现一个快速验证ADC准确性的方法电位器旋转到某个固定角度连续读取1000次的平均值。用平均值和万用表实测的电压值对比。如果偏差小于20mV基本说明电路和代码都是正常的。如果偏差较大优先怀疑参考电压是否准确接着检查接线是否牢固。另一个有效手段是两端校准法把电位器旋到一端测满量程值再旋到另一端测零点值。记录这两个值对应的标准电压然后对中间所有值做线性校正。公式是实际电压 (标准满量程 - 标准零点) / (实测满量程 - 实测零点) × 当前值 零点偏移。这个方法简单可靠几乎能消除所有固定增益和偏移误差我在很多项目里都用它不需要复杂的数学背景。6. 项目扩展思路和进阶方向走完这一套流程你已经理解了模拟量输入→数字量处理→模拟量输出的数据通路。这个知识框架能直接拓展到非常多实际应用中。我简单列几个我亲自验证过的方向供你举一反三。6.1 光敏电阻替代电位器自动亮度控制把电位器换成光敏电阻和10kΩ电阻组成的分压网络光敏电阻一端接3V3另一端接地分压点接GPIO26代码几乎不用改动ADC采集的就是环境光强度。在循环里加一个阈值判断亮度低于某值时打开LED高于某值时关闭LED这就是一个简单的自动夜灯。如果LED换成继电器的控制引脚还能驱动更大功率的照明设备。这里和电位器项目唯一的区别是信号源的阻抗特性不同光敏电阻的阻值随光照剧烈变化分压点的等效阻抗变化也较大。如果发现波形明显波动一是增加滤波强度二是用运算放大器做缓冲电压跟随器之后再送入ADC。6.2 多通道ADC采集与数据融合Pico的ADC0、ADC1、ADC2三个通道可以同时接三个不同传感器。在MicroPython里创建多个ADC对象循环读取所有通道串口输出三通道数据。SerialPlot会自动显示三条曲线一次就能对比各通道信号的变化趋势。我把它用到过温湿度传感器加光敏三通道的环境监测盒子里效果很好。多通道采样时要注意采样顺序和时间戳的同步问题。MicroPython的循环是串行的通道1和通道2的采样时间点会相差几微秒到几百微秒这在慢变信号场景下完全够用但如果采样快速变化的信号就需要用DMA或中断机制来同步采样。Pico本身更擅长实时控制而不是高速数据处理真要高速多通道同步采集建议用STM32或ESP32等芯片的DMA功能。6.3 用ADC测量锂电池电压Pico板载没有锂电池充电和电量检测电路但你可以用ADC读取锂电池电压实现电量指示。锂电池电压满电约4.2V放空约3.0V因此不能直接接GPIO26必须先用两个电阻分压。例如R1100kΩ、R2100kΩ分压比为1/2最大输入是2.1V低于3.3V限制。读取电压后乘以分压系数再映射百分比就能在OLED屏幕上显示剩余电量。这里要特别强调锂电池电压测量需要在电池和ADC之间加入低通滤波电容比如并联一个1uF陶瓷电容否则电池内阻变化或者负载波动会让采样值剧烈跳动。这个电容其实一直接在信号与GND之间不是串联别接错了。我也遇到过几个案例加了电容后波形立刻稳定下来。6.4 与姿态传感器、蓝牙模块联动如果把这个ADC采集项目接入MPU6050姿态传感器或者HC-05蓝牙模块就能形成更复杂的系统电位器控制虚拟3D物体的旋转角度或者通过蓝牙把传感器数据传输到手机。Pico的I2C接口连接MPU6050只需要4根线VCC、GND、SDA、SCL代码也简单但要注意MPU6050的数据输出速率远低于串口输出速率需要适当降低打印频率否则数据会积压。Unity里控制3D角色身体姿态、Pico配合虚拟现实手柄做方向追踪核心也都是读取传感器数值→校准→映射到物理/虚拟参量和这篇文章里读ADC→滤波→映射占空比的思路完全一致。底层物理量不同但数据通路是相通的。结语从数学到物理的直通感串口波形绘制成功那一刻你会亲眼看到旋钮的每一次转动都精确地反映在曲线和LED亮度上这种从物理到数字再到物理的回路有一种无法替代的成就感。我在第一次把SerialPlot波形稳定显示出来时反复旋转电位器观察了十几分钟就像小时候第一次把手电筒开关按出节奏一样兴奋。几个小经验分享给你接线前先用万用表测通断贴标签纸区分ADC通道和PWM引脚USB线尽量选带磁环的代码里sleep时间不要太短MicroPython的Print函数处理不过来时波形会失真。这套项目做完你对Pico的板级资源和ADC整个链路会形成非常扎实的理解后面延伸到任何传感器项目心里都有底。