从硬件到代码:Pico 模拟电位器 ADC 采集实战(含 LED 控制与 SerialPlot 串口波形采集)
模拟电位器是电子设备中常见的组件,用于调整电压或电流。它通过物理旋转来改变电阻值,从而改变输出信号的强度。简单来说,电位器是一个可调电阻器,通常有三个引脚:两个外侧引脚连接到电阻器的两端,中间引脚(滑动触点)可以移动,从而改变与电阻器两端的接触点位置;当旋转电位器时,中间引脚与两端引脚之间的电阻会发生变化。这可以用来调整电压分布,从而实现对输出信号的控制。

常用的 RK09L1240A12 型电位器
这里,我们定时采集模拟电位器上的电压值,并根据其电压值调节板载 LED 灯亮度,同时将电压值通过串口发送给 SerialPlot 串口绘图仪查看电压波形。
这里,我们需要将风雅一号板-通用兼容扩展板插入到风雅一号板-LCD屏幕人机交互板上,同时打开风雅一号板-LCD屏幕人机交互板上 SWITCH2 拨码开关的 POT 选项,实物连接图如下所示:



除此之外,我们还需要将 MiniUSB 数据线连接到风雅一号板-通用兼容扩展板上的串口,这里,GP0 和 GP1 是树莓派 Pico 的硬件串口 UART0 的默认引脚:

器件接线情况如下表所示:

以下代码可以在我们提供的资料包中 elegance-devkit v1\Demo\58 ADC_Potentiometer 文件夹找到。
示例代码如下所示:
# Python env : MicroPython v1.23.0
# -*- coding: utf-8 -*-
# @Time : 2024/8/27 上午11:33
# @Author : 李清水
# @File : main.py
# @Description : ADC类实验,读取电位器两端电压
# ======================================== 导入相关模块 ========================================
# 导入硬件模块
from machine import ADC, Timer, Pin, PWM, UART
# 导入时间相关模块
import time
# 导入访问和控制 MicroPython 内部结构的模块
import micropython
# ======================================== 全局变量 ============================================
# ======================================== 功能函数 ============================================
# 用户自定义回调函数
def user_callback(value: float) -> None:
"""
用户自定义的回调函数,用于打印采集到的模拟电位器电压值。
Args:
value (float): 采集到的模拟电位器电压值。
Returns:
None
"""
# 声明全局变量
global LED, uart
# 打印采集到的模拟电位器电压值
print("Analog potentiometer value is %f" % value)
# 调整LED的占空比,占空比为 ( value / SimulatedPotentiometer.conversion_factor )/ 65535
LED.duty_u16(int(value/SimulatedPotentiometer.conversion_factor))
# 串口发送value值,格式化浮点数为保留小数点后两位的字符串
formatted_value = "{:.2f}".format(value)
uart.write(str(formatted_value)+'\r\n')
# ======================================== 自定义类 ============================================
# 自定义模拟电位器类
class SimulatedPotentiometer:
"""
模拟电位器类,用于通过ADC引脚采集模拟电位器的电压值,并通过定时器定期更新数据。
该类封装了ADC引脚和定时器的初始化,提供了启动、停止采集以及获取当前电压值的功能。
支持通过用户自定义回调函数处理采集到的电压值。
Attributes:
conversion_factor (float): 电压转换系数,用于将ADC的原始值转换为实际电压值。
adc (ADC): ADC实例,用于读取模拟电位器的原始数据。
timer (Timer): 定时器实例,用于定期采集数据。
freq (int): 定时器频率,单位为Hz。
value (float): 当前采集到的电压值。
callback (Optional[Callable[[float], None]]): 用户自定义的回调函数,用于处理采集到的电压值。
Methods:
__init__(self, adc_id: int, freq: int = 100, callback=None):
初始化模拟电位器类实例。
start(self):
启动模拟电位器采集。
_timer_callback(self, timer: Timer):
定时器回调函数,用于采集模拟电位器的电压值并进行转换。
stop(self):
停止模拟电位器采集。
get_value(self) -> float:
返回当前电位器的电压值。
"""
# 电压转换系数
conversion_factor = 3.3 / (65535)
def __init__(self, adc_id: int, freq: int = 100, callback=None) -> None:
"""
初始化模拟电位器类。
Args:
adc_id (int): 使用的ADC引脚编号,只能使用0~2之间的数字。
freq (int): 定时器频率,默认为100Hz。
callback (Optional[Callable[[float], None]]): 采集完成后调用的用户自定义回调函数。
Raises:
ValueError: 如果adc_id不在0~2范围内。
"""
# 入口参数检查
if adc_id > 2 or adc_id < 0:
raise ValueError("adc_id must be 0~2")
# 初始化ADC引脚和定时器
self.adc = ADC(adc_id)
self.timer = Timer(-1)
self.freq = freq
# 采集到的电压值
self.value = 0
# 引用用户自定义的回调函数
self.callback = callback
def start(self) -> None:
"""
启动模拟电位器采集。
Args:
None
Returns:
None
"""
# 启动定时器,并设置定时器回调函数
self.timer.init(period=int(1000/self.freq), mode=Timer.PERIODIC, callback=self._timer_callback)
def _timer_callback(self, timer: Timer) -> None:
"""
定时器回调函数,用于采集模拟电位器的电压值并进行转换。
Args:
timer (Timer): 定时器对象。
Returns:
None
"""
# 读取ADC值并存储到self.value
self.value = self.adc.read_u16() * SimulatedPotentiometer.conversion_factor
# 调用用户自定义的回调函数,传递采集到的电位器电压值
micropython.schedule(self.callback, self.value)
def stop(self) -> None:
"""
停止模拟电位器采集。
Args:
None
Returns:
None
"""
# 停止定时器
self.timer.deinit()
def get_value(self) -> float:
"""
返回当前电位器的值。
Args:
None
Returns:
float: 当前电位器的电压值。
"""
# 返回当前电位器的值
return self.value
# ======================================== 初始化配置 ==========================================
# 上电延时
time.sleep(3)
# 打印调试信息
print("FreakStudio : Analog potentiometer experiment")
# 配置呼吸LED引脚
LED = PWM(Pin(25), freq=100, duty_u16=0)
# 创建模拟电位器实例,使用ADC2-GP28, 定时器频率为100Hz, 回调函数为user_callback
potentiometer = SimulatedPotentiometer(2, 100, user_callback)
# 创建串口对象,设置波特率为115200
uart = UART(0, 115200)
# 初始化uart对象,波特率为115200,数据位为8,无校验位,停止位为1
# 设置串口超时时间为100ms
uart.init(baudrate = 115200,
bits = 8,
parity = None,
stop = 1,
tx = 0,
rx = 1,
timeout = 100)
# ======================================== 主程序 ===========================================
# 启动模拟电位器
potentiometer.start()
# 运行一段时间,观察电位器的值
time.sleep(20)
# 停止模拟电位器
potentiometer.stop()
# 获取最后一次读取的电位器值
print("Final Potentiometer value:", potentiometer.get_value())
这里,我们首先定义了一个 SimulatedPotentiometer 类,用于模拟电位器的采集操作:该类通过指定的 ADC 引脚读取模拟电位器的电压,并在定时器的帮助下定期执行采集操作。
在主程序中,通过调用 potentiometer.start() 启动模拟电位器的采集操作,定时器以 10Hz 的频率触发。
在每次定时器触发时,调用 _timer_callback 函数,该函数读取当前电位器的电压值,并将其存储在 self.value 中,调用用户自定义的回调函数 user_callback,传递电压值。user_callback 完成以下工作:
- 调整 LED 的亮度,亮度与电位器的电压值成比例
- 将电压值格式化为保留两位小数的字符串,并通过串口发送
在模拟电位器运行 20 秒后,停止定时器并获取最后一次读取的电位器值,打印输出。
在烧录代码之前,我们需要完成 SerialPlot 串口绘图仪的配置:

- 配置串口参数:在
Port选项卡中,选择正确的串口(如COM4),并设置波特率为 115200,数据位设置为 8,停止位设置为 1,无校验位 - 点击“Open”:确认配置无误后,点击右上角的“
Open”按钮,打开串口

- 选择数据格式:切换到
Data Format选项卡,选择“ASCII”格式。在单通道数据传输情况下,默认选择逗号作为数据分隔符

烧录代码,连接中断,输出如下:


可以看到,随着我们移动电位器,终端显示的电压数据不断改变同时板载 LED 灯的亮度也不断变化。

串口绘图仪的波形如上图所示,我们可以右键框选我们想要仔细看的波形:

即可放大显示:

我们也可以在其运行过程中,保存接收到的数据到 csv 文件中:

操作步骤如下:
- 在接收数据之前,点击 Record 选项卡和 Record 按键,选择一个文件夹并创建一个新的 CSV 文件,或直接输入你想要保存的文件名,文件扩展名为
.csv - 确保选中了
Write header line选项,这样文件的第一行会包含数据的标题,方便后续分析,你还可以选择其他选项,如:Auto increment file name:如果选中,系统会在文件名后自动添加数字来防止覆盖已有文件Record while paused:即使接收暂停,仍然可以记录数据Stop recording when port closed:当关闭串口时自动停止记录
- 当你完成数据接收时,点击
Record按钮停止记录
刚刚保存的电位器两端电压值数据如下:



模拟电位器是电子设备中常见的组件,用于调整电压或电流。它通过物理旋转来改变电阻值,从而改变输出信号的强度。简单来说,**电位器是一个可调****电阻器****,通常有三个****引脚****:两个外侧引脚连接到电阻器的两端,中间引脚(滑动触点)可以移动,从而改变与电阻器两端的接触点位置**;当旋转电位器时,中间引脚与两端引脚之间的电阻会发生变化。这可以用来调整电压分布,从而实现对输出信号的控制。
浙公网安备 33010602011771号