尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

【CanMV K210】传感器实验 PS2 摇杆方向读取与按键状态检测

【CanMV K210】传感器实验 PS2 摇杆方向读取与按键状态检测 在智能小车、菜单控制器、机械臂调试台和交互式硬件作品中操作杆是一类非常常见的输入设备。它不像普通按键只有按下和松开两种状态而是可以通过 X 轴、Y 轴和中间按键表达方向、移动幅度和确认操作。对于 Python 硬件编程入门来说PS2 操作杆实验很适合用来理解“程序如何读取真实世界的动作”。本实验使用 CanMV K210 开发板通过 I2C 总线连接 PCF8591 模数转换模块再由 PCF8591 读取 PS2 操作杆的 X 轴、Y 轴和按键通道。程序会根据模拟量数值判断摇杆处于上、下、左、右、中心、轻微移动或按键按下状态并且只在状态变化时打印信息避免串口持续刷屏。学习目标说明理解模拟输入认识 PS2 操作杆 X 轴、Y 轴和按键通道的输入特点掌握 ADC 采集使用 PCF8591 将操作杆模拟电压转换成数字值理解 I2C 通信通过 CanMV K210 的软件 I2C 总线读取外部 ADC 模块数据学会阈值判断根据高低阈值、中心值和死区范围识别方向状态建立事件处理思路只在状态变化时触发输出为菜单、小车和交互控制打基础这段代码的价值不只是读取三个数值而是把模拟量采集、阈值判断、中心死区、按键识别和事件处理组合成一个完整输入控制流程。屏幕上的数值变化对应手指推动摇杆的真实动作后续可以自然扩展到菜单控制、小车方向控制、设备确认按钮和交互式项目输入。文章目录理论基础硬件设施软件代码扩展应用总结理论基础PS2 操作杆本质上是一个二维输入设备。推动摇杆时X 轴和 Y 轴会输出不同的模拟电压按下摇杆中间按钮时按键通道会产生明显的电平变化。普通数字 GPIO 只能稳定判断高电平或低电平不适合直接描述这种连续变化的模拟信号因此本实验引入 PCF8591 模数转换模块。PCF8591 的作用可以理解为“模拟世界和程序世界之间的转换器”。操作杆输出的是电压变化程序需要的是数字值。PCF8591 负责读取 X 轴、Y 轴和按键通道把这些模拟量转换成可以被 CanMV K210 读取的数字数据。CanMV K210 通过 I2C 总线访问 PCF8591再由程序根据读取到的数值判断方向和按键状态。本实验的控制链路不是“操作杆直接控制程序”而是“操作杆改变模拟电压PCF8591 完成 ADC 转换K210 通过 I2C 读取数据程序再根据阈值生成方向事件”。这个链路和后续传感器实验非常接近例如光敏电阻、声音传感器、土壤湿度传感器、旋钮电位器等模拟量模块都可以用类似方式完成采集和判断。PS2 操作杆X轴 / Y轴 / SW按键模拟电压变化方向移动与按键动作PCF8591 ADC通道0 / 通道1 / 通道2I2C 总线SCL / SDACanMV K210物理引脚6 / 物理引脚7Python 程序读取 X / Y / SW 数值状态判断上 / 下 / 左 / 右 / 中心 / 按下应用动作菜单控制 / 小车方向 / 参数调节模块供电VCC公共地线GND这张图可以从电路流程角度理解。PS2 操作杆负责产生输入信号PCF8591 负责模拟量转换I2C 总线负责数据通信CanMV K210 负责运行程序程序中的阈值逻辑负责把原始数值翻译成方向状态。真正进入业务逻辑的不是原始电压而是up、down、left、right、home、move、pressed这些更容易使用的状态。模拟量实验中最容易忽略的是“中心死区”。摇杆松手回到中心时X 轴和 Y 轴数值通常不会刚好固定在某一个数字上而是会在中心附近浮动。如果程序只用等于某个固定值判断中心串口输出会频繁抖动。代码中使用CENTER_VALUE和DEAD_ZONE保留一个容错范围只要 X 轴和 Y 轴都落在中心附近就认为摇杆处于中心状态。硬件设施本实验真正使用到的核心硬件是 CanMV K210 开发板、PCF8591 模数转换模块和 PS2 操作杆。PS2 操作杆输出的是模拟电压变化CanMV 不能直接通过普通数字 GPIO 精确读取这种连续变化因此代码中使用 PCF8591 作为 ADC 转换模块将模拟量转换成程序可以处理的数字值。软件侧主要依赖machine.I2C、fpioa_manager.fm和pcf8591驱动模块。硬件 / 软件作用说明CanMV / K210 开发板实验运行平台负责执行 MicroPython 程序并通过 I2C 总线读取外部 ADC 模块数据PS2 操作杆模块输入控制设备输出 X 轴、Y 轴和按键状态用于判断方向和确认动作PCF8591 模数转换模块模拟量采集模块将操作杆输出的模拟信号转换成数字值供程序读取物理引脚 6I2C 时钟线代码中作为I2C_SCL_PIN使用连接 PCF8591 的 SCL物理引脚 7I2C 数据线代码中作为I2C_SDA_PIN使用连接 PCF8591 的 SDAmachine.I2CI2C 通信模块创建软件 I2C 总线用于和 PCF8591 通信fpioa_manager.fm引脚功能映射模块将 SCL、SDA 对应到 K210 的高速 GPIO 功能pcf8591ADC 驱动模块封装 PCF8591 的读取方法通过read()获取通道数值time延时控制模块通过time.sleep_ms(80)控制采样节奏减少无效刷新接线关系需要结合代码中的 I2C 配置、ADC 通道编号和变量名进行理解。当前代码使用物理引脚 6 作为 I2C SCL物理引脚 7 作为 I2C SDAPCF8591 的通道 0、通道 1、通道 2 分别读取操作杆的 X 轴、Y 轴和按键值。不同 PS2 操作杆模块的 X/Y 方向可能存在差异实际方向与串口输出相反时调整get_direction()中的返回值即可底层读取结构不需要改变。接口 / 通道代码变量对应硬件说明物理引脚 6I2C_SCL_PINPCF8591 SCL作为 I2C 时钟线使用物理引脚 7I2C_SDA_PINPCF8591 SDA作为 I2C 数据线使用PCF8591 通道 0ADC_CHANNEL_XPS2 操作杆 X 轴用于读取横向或纵向模拟量PCF8591 通道 1ADC_CHANNEL_YPS2 操作杆 Y 轴用于读取另一方向模拟量PCF8591 通道 2ADC_CHANNEL_SWPS2 操作杆按键用于读取按键模拟值GPIOHS1gsclfm.fpioa.GPIOHS1I2C SCL 映射功能用于软件 I2C 的时钟引脚功能绑定GPIOHS2gsdafm.fpioa.GPIOHS2I2C SDA 映射功能用于软件 I2C 的数据引脚功能绑定VCC模块供电PCF8591 与 PS2 操作杆根据模块标识连接到对应供电端GND公共地线CanMV、PCF8591 与 PS2 操作杆保证通信和模拟量采集具有统一参考电平零件图主要用于认识实验器材。PS2 操作杆负责产生输入变化PCF8591 负责读取模拟输入通道CanMV K210 负责运行程序并分析状态。这个实验和普通按键实验的区别在于普通按键通常只关心高低电平而操作杆需要关注连续数值变化因此需要引入阈值、中心值和死区范围。物理引脚可以理解成开发板对外连接模块的真实接口I2C 的 SCL 和 SDA 是开发板与 PCF8591 通信的两根信号线ADC 通道则是 PCF8591 读取操作杆模拟量的入口。代码中ADC_CHANNEL_X 0表示从通道 0 读取 X 轴ADC_CHANNEL_Y 1表示从通道 1 读取 Y 轴ADC_CHANNEL_SW 2表示从通道 2 读取按键值。程序并不直接读取操作杆而是通过 PCF8591 作为中间转换层获取数字化结果。成品状态重点观察三件事PCF8591 是否正常供电SCL/SDA 是否连接到代码指定的物理引脚PS2 操作杆的 X/Y/SW 是否接入对应 ADC 通道。程序运行后推动摇杆会让串口中的 X 轴和 Y 轴数值发生变化按下摇杆中间按钮会让 SW 数值进入按下判断范围。实验现象正常表现异常提示摇杆居中X、Y 数值接近中心参考值状态显示home中心状态频繁变化时需要调整CENTER_VALUE或DEAD_ZONE向上推动X 或 Y 某一路数值进入低阈值或高阈值范围状态变为up实际方向相反时调整get_direction()中的方向返回值向下推动方向状态变为down数值不变化时检查对应 ADC 通道接线向左推动方向状态变为left左右相反时对调left和right的返回逻辑向右推动方向状态变为right方向不稳定时检查阈值和中心死区按下摇杆状态中出现pressed按下无反应时观察 SW 原始值并调整BUTTON_PRESSED轻微移动状态显示move代表数值不在明确方向阈值内也不完全处于中心死区软件代码本实验代码围绕 PS2 操作杆的数据读取和状态判断展开。程序先配置 I2C 总线并创建 PCF8591 对象再读取 X 轴、Y 轴和按键通道数据。方向判断依赖低阈值、高阈值和中心死区按键判断依赖按下阈值。主循环会持续读取状态但只有状态发生变化时才打印避免串口输出被重复信息淹没。软件环境作用检查重点CanMV IDE编辑、运行和调试 K210 程序能识别开发板串口并能正常运行基础print()测试CanMV 固件提供machine.I2C、fpioa_manager等模块固件环境需要支持当前代码中的 I2C 与 FPIOA 写法USB 串口驱动让电脑识别开发板串口设备管理器或串口工具中能看到对应端口PCF8591 驱动模块封装 ADC 读取方法代码能够正常import pcf8591串口终端查看操作杆状态变化推动摇杆时能看到 X、Y、SW 和当前状态输出#!/usr/bin/env python3# -*- coding: utf-8 -*- CanMV K210 PS2 操作杆实验 Demo 功能说明 1. 通过 PCF8591 读取 PS2 操作杆的 X 轴、Y 轴、按键值 2. 根据模拟量判断上、下、左、右、中心状态 3. 支持按键按下识别 4. 只在状态变化时打印避免串口刷屏 importtimefrommachineimportI2Cfromfpioa_managerimportfmimportpcf8591# # 硬件配置区# I2C_SCL_PIN6I2C_SDA_PIN7ADC_CHANNEL_X0ADC_CHANNEL_Y1ADC_CHANNEL_SW2LOW_THRESHOLD35# 小于该值认为摇杆偏向一侧HIGH_THRESHOLD220# 大于该值认为摇杆偏向另一侧CENTER_VALUE125# 摇杆中心参考值DEAD_ZONE20# 中心死区减少轻微抖动带来的误判BUTTON_PRESSED30# 按键通道低于该值认为按下# # 初始化# defsetup(): 初始化 I2C 与 PCF8591 模数转换模块 PS2 操作杆输出的是模拟量需要通过 PCF8591 转换成数字值 i2cI2C(I2C.I2C_SOFT,freq400000,sclI2C_SCL_PIN,sdaI2C_SDA_PIN,gsclfm.fpioa.GPIOHS1,gsdafm.fpioa.GPIOHS2)adcpcf8591.PCF8591(i2c)returnadc# # 数据读取# defread_joystick(adc): 读取 PS2 操作杆数据 返回 x_value : X 轴模拟值 y_value : Y 轴模拟值 sw_value : 按键模拟值 x_valueround(adc.read(ADC_CHANNEL_X))y_valueround(adc.read(ADC_CHANNEL_Y))sw_valueround(adc.read(ADC_CHANNEL_SW))returnx_value,y_value,sw_value# # 状态判断# defis_center(x_value,y_value): 判断摇杆是否处于中心位置 摇杆中心值不会绝对固定因此需要保留死区范围 x_centerabs(x_value-CENTER_VALUE)DEAD_ZONE y_centerabs(y_value-CENTER_VALUE)DEAD_ZONEreturnx_centerandy_centerdefget_direction(x_value,y_value): 根据 X 轴和 Y 轴模拟值判断方向 不同模块接线方向可能相反如方向不一致只需调整返回值 ifx_valueLOW_THRESHOLD:returnupifx_valueHIGH_THRESHOLD:returndownify_valueHIGH_THRESHOLD:returnleftify_valueLOW_THRESHOLD:returnrightifis_center(x_value,y_value):returnhomereturnmovedefis_pressed(sw_value): 判断摇杆按键是否按下 常见 PS2 操作杆按键按下时为低电平 returnsw_valueBUTTON_PRESSEDdefget_joystick_state(adc): 获取完整操作杆状态 同时返回方向和按键状态 x_value,y_value,sw_valueread_joystick(adc)directionget_direction(x_value,y_value)pressedis_pressed(sw_value)ifpressed:statedirection_pressedelse:statedirectionreturn{x:x_value,y:y_value,sw:sw_value,direction:direction,pressed:pressed,state:state}# # 场景动作映射# defhandle_joystick_event(data): 根据摇杆状态执行对应动作 当前 Demo 使用打印模拟实际项目动作 directiondata[direction]presseddata[pressed]ifpressed:print(按键按下可用于确认、选择、启动任务)returnifdirectionup:print(方向上可用于菜单上移或小车前进)elifdirectiondown:print(方向下可用于菜单下移或小车后退)elifdirectionleft:print(方向左可用于菜单左切或小车左转)elifdirectionright:print(方向右可用于菜单右切或小车右转)elifdirectionhome:print(方向中心设备保持待机状态)else:print(方向轻微移动处于过渡区域)# # 主循环# defloop(adc): 循环读取操作杆状态 只有状态发生变化时才打印避免重复输出 last_statewhileTrue:dataget_joystick_state(adc)current_statedata[state]ifcurrent_state!last_state:print(--------------------------------)print(X轴{} Y轴{} 按键{}.format(data[x],data[y],data[sw]))print(当前状态{}.format(current_state))handle_joystick_event(data)last_statecurrent_state time.sleep_ms(80)# # 程序入口# if__name____main__:try:adcsetup()loop(adc)exceptKeyboardInterrupt:print(程序已停止)图 4 推动操作杆或按下按键后串口输出对应的数值和状态变化这段程序可以理解成三个层级。底层是setup()和read_joystick()负责建立 I2C 通信并读取 PCF8591 的三个 ADC 通道中间层是is_center()、get_direction()、is_pressed()和get_joystick_state()负责把原始数值转换成方向、按键和完整状态上层是handle_joystick_event()和loop()负责把状态变化映射成实际动作。硬件配置区把 I2C 引脚、ADC 通道、方向阈值、中心值、死区范围和按键阈值集中放在顶部。调试时不需要进入函数内部修改逻辑。摇杆中心值不稳定时可以调整CENTER_VALUE和DEAD_ZONE方向触发不灵敏时可以调整LOW_THRESHOLD和HIGH_THRESHOLD按键无法识别时可以根据串口中的 SW 数值调整BUTTON_PRESSED。last_state是本实验中很实用的设计。普通读取程序如果每隔几十毫秒打印一次数据串口很快会被大量重复信息填满真正的状态变化反而不容易观察。当前代码只有在current_state ! last_state时才打印这种写法更接近真实项目中的事件驱动思路输入设备可以持续采样但业务逻辑只关心状态是否发生变化。函数名功能对应现象setup()初始化 I2C 与 PCF8591开发板建立与 ADC 模块的通信关系read_joystick(adc)读取 X 轴、Y 轴和按键通道串口中可以看到三个模拟量数值变化is_center(x_value, y_value)判断摇杆是否回到中心摇杆松手后识别为home状态get_direction(x_value, y_value)根据阈值判断方向推动摇杆时识别上、下、左、右或移动状态is_pressed(sw_value)判断中间按键是否按下按下摇杆时状态中出现pressedget_joystick_state(adc)组合完整状态数据返回包含数值、方向、按键和状态的字典handle_joystick_event(data)根据状态执行模拟动作串口打印菜单移动、小车控制或待机说明loop(adc)持续读取并过滤重复状态状态变化时才输出避免串口刷屏扩展应用PS2 操作杆实验涉及模拟量采集、I2C 通信和阈值判断调试时常见问题主要集中在通信失败、数值异常、方向相反、中心抖动和按键识别不准确等方面。排查时可以先观察串口打印的 X、Y、SW 原始值再根据数值变化判断是硬件连接问题还是阈值设置问题。问题现象可能原因处理思路程序运行后没有任何输出I2C 接线错误、PCF8591 未正常通信、程序没有进入主循环检查 SCL 是否连接物理引脚 6SDA 是否连接物理引脚 7确认 PCF8591 供电和接地正常X、Y 数值一直不变化操作杆 X/Y 输出没有接入对应 ADC 通道核对 PS2 操作杆 X 轴、Y 轴是否分别接到 PCF8591 通道 0 和通道 1方向判断与实际方向相反模块接线方向或摇杆坐标方向与代码假设不同修改get_direction()中的返回值例如将up和down对调或将left和right对调松手后不能稳定显示中心摇杆中心值与CENTER_VALUE偏差较大死区范围太小观察松手时 X、Y 数值将CENTER_VALUE调整到接近实际中心值适当增大DEAD_ZONE摇杆轻微晃动频繁触发方向阈值设置过于敏感或者模块模拟量抖动明显适当降低灵敏度增大中心死区或调整LOW_THRESHOLD与HIGH_THRESHOLD按键按下没有识别SW 通道接线不一致或按下时数值没有低于阈值观察按下时sw数值将BUTTON_PRESSED调整到合适范围串口输出很少代码只在状态变化时打印静止状态不会重复输出推动摇杆或按下按键触发状态变化这是当前程序的正常设计状态一直显示move数值不在方向阈值范围也不在中心死区范围根据实际 X、Y 数值重新设置LOW_THRESHOLD、HIGH_THRESHOLD和DEAD_ZONE无法导入pcf8591驱动文件没有放到开发板运行环境中检查pcf8591.py是否已经上传到对应目录或确认固件示例库是否包含该模块PS2 操作杆实验的扩展价值在于把连续输入变成可编程状态。上、下、左、右、中心、按下这些状态可以映射到不同动作代码中的handle_joystick_event()已经给出了这种设计雏形。当前 Demo 使用打印语句模拟动作在真实项目中同样的位置可以替换成菜单切换、小车运动、机械臂控制、摄像头云台调整或任务确认逻辑。应用场景实现思路可扩展能力菜单方向控制将up、down、left、right映射为菜单移动后续可扩展 LCD 显示实现可视化菜单操作智能小车控制将方向状态映射为前进、后退、左转、右转后续可接入电机驱动模块实现摇杆遥控小车机械臂姿态调节使用 X/Y 方向控制舵机角度变化后续可扩展 PWM 舵机控制实现多轴调试摄像头云台控制使用方向状态调整摄像头观察角度后续可结合 AI 摄像头识别实现目标跟随参数调节旋钮用上下方向增加或减少参数用按键确认可用于阈值调试、模式选择和设备配置游戏交互输入将方向和按键转换成角色移动与确认动作可扩展为嵌入式小游戏或教学互动项目任务启动确认使用按键状态触发确认、选择或启动任务可用于设备控制台、实验流程确认和安全启动从工程角度看当前程序已经具备较好的输入设备抽象能力。底层的read_joystick()只负责读取数据中间的get_direction()和is_pressed()负责状态判断上层的handle_joystick_event()负责业务动作映射。这种分层结构很适合继续扩展后续即使把打印替换成电机控制、屏幕菜单或网络指令也不需要重写底层采集逻辑。总结本实验通过 CanMV K210、PCF8591 和 PS2 操作杆完成了一个完整的模拟输入读取案例核心能力包括 I2C 通信、ADC 通道读取、模拟量阈值判断、中心死区处理、按键识别、状态封装和事件映射。代码从硬件配置开始把操作杆的 X 轴、Y 轴和按键值转换成程序可理解的方向状态再通过主循环持续检测状态变化实现了从真实动作到程序事件的转换。这类实验非常适合作为智能硬件输入控制的入门案例。推动摇杆时串口中的数值和状态会同步变化按下中间按钮时程序可以识别确认动作状态变化过滤又能让输出更接近真实项目中的事件触发方式。后续课程可以在此基础上继续扩展 LCD 菜单、蜂鸣器反馈、电机控制、舵机云台、传感器参数调节和 AI 摄像头交互等内容让操作杆从一个输入模块逐步变成智能硬件项目中的控制入口。
返回列表