CircuitPython HID实战:用Python轻松打造自定义键盘鼠标与数据记录仪

news2026/5/19 2:18:56
1. 项目概述与核心价值如果你玩过一些老游戏或者用过一些专业软件可能会遇到一个头疼的问题你想用一个自制的硬件控制器来操作它但软件根本不支持外接硬件只认键盘鼠标。以前遇到这种情况要么放弃要么得去研究复杂的驱动开发。但现在有了 CircuitPython 和它的 HID 功能这事儿变得跟搭积木一样简单。HID也就是人机接口设备是 USB 协议里专门给键盘、鼠标、游戏手柄这类设备定的一套“语言”。你的电脑天生就懂这套语言。CircuitPython 的厉害之处在于它把这套“语言包”直接内置了。这意味着你手上那块像邮票大小的开发板比如 Adafruit 的 ItsyBitsy、Feather 系列只要刷上 CircuitPython写几行 Python 代码就能瞬间“变身”成一个标准的 USB 键盘或鼠标。电脑会把它当成一个普通的输入设备完全不需要安装任何额外驱动。这个项目的核心价值就在这里它极大地降低了硬件交互的门槛。你不需要是个驱动开发专家甚至对 USB 协议一知半解也没关系。你只需要会用 Python 控制 GPIO 引脚读取个按钮状态或者用 ADC 读取个摇杆电压然后调用现成的adafruit_hid库就能让这些物理动作转化为电脑能识别的按键和鼠标移动。无论是给残疾人士做一个特制的输入设备还是给自己做一个一键完成复杂操作的“宏按键”或者做一个自动测试的硬件工具都变得非常可行。我最初接触这个功能是想做一个物理的“剪辑快捷键面板”。视频剪辑软件快捷键太多记不住我就用带按键的板子做了几个常用快捷键比如“切割”、“撤销”、“渲染”一按就行效率提升非常明显。这比在软件里设置键盘宏更稳定也更“有感觉”。下面我就把从环境搭建到代码实战再到数据采集扩展的完整流程以及我踩过的坑和总结的技巧毫无保留地分享出来。2. 环境准备与核心库解析工欲善其事必先利其器。在开始敲代码之前我们需要把“战场”布置好。这个过程看似简单但很多新手都在第一步卡住其实关键就在于细节。2.1 硬件选型与连接首先你需要一块支持 CircuitPython 的开发板。Adafruit 的系列是首选因为文档和库的支持最完善。对于 HID 项目我推荐以下两款ItsyBitsy M4 Express这是我的主力推荐。它使用 ATSAMD51 芯片速度快内存足自带 2MB 的额外 Flash这就是“Express”的含义可以轻松装下 CircuitPython 系统和各种库文件。引脚排布规整非常适合焊接和插线。Feather M4 Express如果你需要更多的扩展可能性Feather 生态有大量翅膀扩展板或者项目需要电池供电板载锂电池充电电路那么 Feather 系列是更好的选择。注意务必确认你拿到的是Express版本。非 Express 版本如 Trinket M0、Gemma M0虽然便宜但存储空间非常紧张只有约50KB用于文件系统无法容纳 HID 等大型库功能受限严重不适合做复杂的项目。硬件连接就是简单的 USB 数据线。建议使用质量好的 USB 数据线有些充电线只能供电不能传输数据会导致电脑识别不到设备。连接后电脑应该会识别出一个名为CIRCUITPY的可移动磁盘这就代表 CircuitPython 系统已经正常运行了。2.2 软件环境搭建库文件部署这是新手最容易出错的一步。CircuitPython 的核心库并不包含 HID 功能需要手动添加。很多教程只说“下载库文件”但没讲清楚怎么下、下哪个、放哪里。下载正确的库包访问 CircuitPython 官方库包发布页面。关键点来了你必须下载与你的 CircuitPython 固件版本匹配的库包。比如你板子上的 CircuitPython 是 8.x 版本却下载了 7.x 的库很可能无法工作。在库包页面找到 “adafruit-circuitpython-bundle-py-版本号” 这个文件下载整个 ZIP 包。解压与寻找解压下载的 ZIP 文件里面会有一个lib文件夹。我们需要的所有库文件都在这里。精准拷贝打开你的CIRCUITPY磁盘如果里面没有lib文件夹就新建一个。然后从解压后的lib文件夹里找到以下两个.mpy文件CircuitPython 的编译库格式复制到你的CIRCUITPY/lib/目录下adafruit_hid如果你需要非美式键盘布局比如德语、法语可能还需要对应的adafruit_hid/keyboard_layout_xx.mpy文件。实操心得不要图省事把整个lib文件夹的内容全拷贝进去这会导致CIRCUITPY磁盘空间迅速被占满尤其是空间不大的非 Express 板子。只拷贝项目必需的库是保持项目整洁和高效的好习惯。你可以把常用的库包解压到电脑上一个固定位置每次做新项目时像“逛超市”一样从中选取需要的库文件。2.3 代码编辑器选择CIRCUITPY磁盘根目录下的code.py文件就是主程序CircuitPython 启动后会自动运行它。你可以用任何纯文本编辑器修改它但我强烈推荐使用Mu Editor或VS Code 配合 CircuitPython 插件。Mu Editor专为教育和小型项目设计内置了串行终端Serial Console查看打印信息、错误提示非常方便。它还有一个“文件系统”视图可以直接管理CIRCUITPY磁盘上的文件。对于初学者和快速原型开发Mu 是首选。VS Code CircuitPython 插件如果你已经是 VS Code 用户安装 CircuitPython 插件后可以获得代码自动补全、语法高亮、一键上传、串口监视器等强大功能开发体验更接近专业的 IDE。我个人更倾向于 VS Code因为它的代码管理和编辑功能更强大。当你代码量变大需要管理多个.py文件时VS Code 的优势就体现出来了。3. HID键盘模拟实战从引脚触发到字符串输入键盘模拟是最基础也最常用的功能。想象一下用一个物理按钮来触发“CtrlS”保存操作或者用一个光敏电阻在光线变暗时自动按下“F11”全屏是不是很酷我们一步步来实现。3.1 基础电路与代码解析我们先从最简单的开始用两个引脚A1, A2接地来模拟按键。电路很简单用一根导线或鳄鱼夹将开发板的 A1 或 A2 引脚与 GND地引脚短暂连接一下就相当于按下了一个键。让我们深入看看代码的每一部分理解其背后的逻辑# SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries # SPDX-License-Identifier: MIT CircuitPython Essentials HID Keyboard example import time import board import digitalio import usb_hid from adafruit_hid.keyboard import Keyboard from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS from adafruit_hid.keycode import Keycode # 1. 定义按键引脚和对应的输出 keypress_pins [board.A1, board.A2] # 我们将监视这两个引脚 keys_pressed [Keycode.A, Hello World!\n] # 引脚触发时发送的内容 control_key Keycode.SHIFT # 组合键这里用SHIFT配合A打出大写A # 2. 初始化键盘对象 time.sleep(1) # 关键给主机一点时间识别HID设备避免竞争条件 keyboard Keyboard(usb_hid.devices) keyboard_layout KeyboardLayoutUS(keyboard) # 使用美式键盘布局 # 3. 配置引脚为输入模式并启用内部上拉电阻 key_pin_array [] for pin in keypress_pins: key_pin digitalio.DigitalInOut(pin) key_pin.direction digitalio.Direction.INPUT key_pin.pull digitalio.Pull.UP # 启用内部上拉引脚默认高电平 key_pin_array.append(key_pin) # 4. 配置板载LED作为状态指示 led digitalio.DigitalInOut(board.LED) led.direction digitalio.Direction.OUTPUT print(Waiting for key pin...) # 5. 主循环检测引脚状态 while True: for key_pin in key_pin_array: if not key_pin.value: # 引脚被拉低接地了 i key_pin_array.index(key_pin) print(fPin #{i} is grounded.) led.value True # 点亮LED表示正在处理 # 等待引脚释放断开接地 while not key_pin.value: pass # 执行按键动作 key keys_pressed[i] if isinstance(key, str): keyboard_layout.write(key) # 发送字符串 else: keyboard.press(control_key, key) # 按下组合键 keyboard.release_all() # 释放所有按键非常重要 led.value False # 熄灭LED time.sleep(0.01) # 短暂延迟降低CPU占用关键点解析与避坑指南time.sleep(1)的必要性这不是随便写的。当开发板通过USB插入电脑时电脑需要时间枚举和配置这个新发现的HID设备。如果代码立刻开始发送按键信号而此时主机驱动还没准备好这些信号就会被忽略或导致错误。这1秒的等待是避免“竞争条件”的黄金法则。内部上拉电阻 (pulldigitalio.Pull.UP)这是实现“按下即接地”触发逻辑的核心。启用上拉后引脚内部通过一个电阻连接到3.3V使其默认保持高电平value为True。当用导线将引脚连接到GND时引脚被强制拉低到0Vvalue变为False从而被代码检测到。这省去了外部电阻简化了电路。keyboard.release_all()至关重要想象一下你按下了键盘上的“A”键但没松开电脑就会一直输入“aaaaa...”。在代码中keyboard.press()相当于按下你必须显式地调用release_all()来松开。忘记这行会导致“粘键”非常麻烦。一个好的习惯是在每次press()操作后立即安排release_all()。字符串与键码keys_pressed列表里可以混合Keycode对象和字符串。Keycode.A代表单个按键A而Hello World!\n字符串会被keyboard_layout.write()方法逐个字符地“敲”出来\n代表回车键。这为输入大段文本或命令提供了便利。3.2 进阶应用使用实体按钮与多个按键组合用导线触发毕竟不实用我们来换成真正的按钮。电路连接按钮一脚接开发板引脚如A1另一脚接GND。代码上只需要把检测“引脚接地”的逻辑理解为“按钮按下”即可因为按钮按下时就将引脚短路到了GND。如何实现复杂的组合键比如“CtrlAltDelete”adafruit_hid库支持同时按下最多6个键。看下面的例子from adafruit_hid.keycode import Keycode # 模拟 CtrlAltDelete (Windows 安全选项) keyboard.press(Keycode.CONTROL, Keycode.ALT, Keycode.DELETE) time.sleep(0.1) # 保持按下状态一小会儿更模拟真人操作 keyboard.release_all() # 模拟 CtrlC (复制) keyboard.press(Keycode.CONTROL, Keycode.C) time.sleep(0.05) keyboard.release_all() # 模拟 WinL (Windows 锁屏) - 注意Keycode 中 Windows 键可能是 Keycode.GUI 或 Keycode.WINDOWS keyboard.press(Keycode.GUI, Keycode.L) time.sleep(0.1) keyboard.release_all()注意事项发送系统级快捷键如CtrlAltDelete,WinL时一定要谨慎最好在测试时先打开一个文本编辑器确认按键映射正确再应用到系统操作上。否则可能意外锁屏或弹出任务管理器。4. HID鼠标模拟实战用摇杆控制光标键盘模拟解决了按键输入鼠标模拟则让我们能控制光标移动和点击。最常见的应用就是自制游戏手柄或轨迹球。我们用一个双轴摇杆带按键来实现。4.1 摇杆硬件连接与原理摇杆本质上就是两个电位器X轴和Y轴加一个按键。我们需要用到开发板的模拟输入引脚ADC来读取电压。接线方式通用摇杆 VCC- 开发板3.3V摇杆 GND- 开发板GND摇杆 X轴- 开发板A0(或其他模拟输入引脚)摇杆 Y轴- 开发板A1摇杆 SW按键- 开发板A2(或其他数字输入引脚)代码深度解析import time import analogio import board import digitalio import usb_hid from adafruit_hid.mouse import Mouse mouse Mouse(usb_hid.devices) # 初始化模拟输入和数字输入 x_axis analogio.AnalogIn(board.A0) y_axis analogio.AnalogIn(board.A1) select digitalio.DigitalInOut(board.A2) select.direction digitalio.Direction.INPUT select.pull digitalio.Pull.UP # 按键默认高电平按下时拉低 # 电压范围校准 - 这是关键 pot_min 0.00 pot_max 3.29 step (pot_max - pot_min) / 20.0 def get_voltage(pin): 将ADC原始值0-65535转换为电压值0-3.3V return (pin.value * 3.3) / 65536 def steps(axis): 将电压值映射到0-20的整数步进中心点是10 return round((axis - pot_min) / step) while True: x get_voltage(x_axis) y get_voltage(y_axis) # 按键检测鼠标左键单击 if select.value is False: mouse.click(Mouse.LEFT_BUTTON) time.sleep(0.2) # 按键去抖延时 # X轴移动控制 if steps(x) 11.0: mouse.move(x1) # 轻微右移 if steps(x) 9.0: mouse.move(x-1) # 轻微左移 if steps(x) 19.0: mouse.move(x8) # 快速右移 if steps(x) 1.0: mouse.move(x-8) # 快速左移 # Y轴移动控制 (注意屏幕Y轴向下为正这里做了反转) if steps(y) 11.0: mouse.move(y-1) # 轻微上移 if steps(y) 9.0: mouse.move(y1) # 轻微下移 if steps(y) 19.0: mouse.move(y-8) # 快速上移 if steps(y) 1.0: mouse.move(y8) # 快速下移4.2 核心算法死区与非线性映射这段代码的精髓在于steps()函数和后续的条件判断。它实现了一个带“死区”和“两级速度”的控制逻辑。电压映射 (steps())摇杆在静止时电压并非精确的1.65V3.3V的一半且不同摇杆的电位器阻值也有误差。我们实测一个电压范围如0.00V-3.29V并将其线性映射到0-20的整数。这样摇杆中心位置大约对应 step10。这个映射过程将模拟量的微小波动转换为了离散的、稳定的整数值避免了光标因电压噪声而抖动。死区设计看判断条件steps(x) 11.0和 9.0。这意味着只有当摇杆偏离中心位置超过1个步进即step10的上下各1时才会触发移动。9-11这个区间就是“死区”。摇杆在中心附近轻微的晃动会被忽略光标非常稳定。这是制作可用鼠标控制器的关键没有死区的摇杆光标会乱飘。非线性速度控制第二组判断steps(x) 19.0和 1.0检测摇杆是否推到了极限位置。如果是则一次移动8个像素实现快速移动在中间区域则一次移动1个像素实现精细定位。这种“慢速-快速”的两级控制非常符合直觉。实操心得校准你的摇杆代码中的pot_min和pot_max最好是实际测量值。你可以先写一段简单的代码打印出get_voltage(x_axis)和get_voltage(y_axis)在摇杆推到四个极限位置时的读数用这些实际值来替换。这样映射会更准确死区也更对称。4.3 鼠标其他功能扩展adafruit_hid.mouse库还提供了其他功能mouse.move(wheel1)滚动滚轮。mouse.press(Mouse.RIGHT_BUTTON)/mouse.release(Mouse.RIGHT_BUTTON)按下/释放右键实现拖拽。mouse.click(Mouse.MIDDLE_BUTTON)中键点击。你可以轻松地将这些功能分配给开发板上的其他按钮制作一个功能完整的自定义鼠标。5. 传感器数据采集与存储打造微型数据记录仪HID模拟让板子能“输出”而嵌入式系统另一大核心是“输入”——采集数据。CircuitPython 让读取传感器和存储数据变得异常简单。我们以读取内部CPU温度并记录到文件为例打造一个微型数据记录仪。5.1 读取CPU温度微控制器运行时会产生热量芯片内部集成了温度传感器。CircuitPython 通过microcontroller模块暴露了这个传感器。import time import microcontroller while True: temp_c microcontroller.cpu.temperature temp_f temp_c * (9 / 5) 32 # 转换为华氏度 print(fCPU Temp: {temp_c:.2f} C, {temp_f:.2f} F) time.sleep(2)就这么简单microcontroller.cpu.temperature直接返回摄氏温度值。你可以通过用手触摸芯片来观察温度变化。这个功能非常适合用来监测设备的工作温度或在物联网项目中作为一项环境数据。5.2 核心挑战如何向 CIRCUITPY 磁盘写入数据这里遇到了一个 CircuitPython 的设计限制CIRCUITPY 磁盘通常由你的电脑挂载为可写模式以便你编辑代码。如果 CircuitPython 运行时也同时去写这个磁盘极有可能导致文件系统损坏数据丢失。解决方案是使用一个特殊的boot.py文件。这个文件在板子硬启动上电或按复位键时运行比code.py更早。它的作用是在启动时检查一个物理开关或引脚状态来决定将 CIRCUITPY 磁盘的写入权限分配给电脑还是 CircuitPython 程序。boot.py文件详解import board import digitalio import storage # 选择一个数字引脚作为“模式切换开关” # 对于 Feather M4 Express常用 D5 引脚 switch digitalio.DigitalInOut(board.D5) switch.direction digitalio.Direction.INPUT switch.pull digitalio.Pull.UP # 默认内部上拉引脚为高电平 # 关键命令根据引脚状态重新挂载文件系统 storage.remount(/, readonlyswitch.value)工作原理默认情况下引脚通过上拉电阻为高电平switch.value为TruereadonlyTrue对 CircuitPython 而言意味着文件系统是只读的但对你的电脑是可写的。此时你可以在电脑上编辑文件。当用一根跳线将D5引脚连接到GND时引脚被拉低switch.value变为False。此时readonlyFalse对 CircuitPython 意味着文件系统是可写的但对你的电脑则变为只读。此时你的 CircuitPython 程序如code.py才能向磁盘写入数据而电脑则无法修改磁盘内容防止了冲突。5.3 完整的数据记录仪实现有了boot.py保驾护航我们就可以在code.py里安心地写数据了。import time import board import digitalio import microcontroller # 配置状态LED led digitalio.DigitalInOut(board.LED) led.switch_to_output() try: # 以追加模式打开文件如果文件不存在则创建 with open(/temperature.txt, a) as log_file: while True: # 读取温度 temp_c microcontroller.cpu.temperature # 将温度值和时间戳写入文件 timestamp time.monotonic() # 获取自开机后的时间秒 log_line f{timestamp:.1f}, {temp_c:.2f}\n log_file.write(log_line) log_file.flush() # 立即将数据写入磁盘避免缓存丢失 # 闪烁LED指示工作状态 led.value not led.value time.sleep(10) # 每10秒记录一次 except OSError as e: # 处理错误例如文件系统不可写或已满 delay 0.5 if e.args[0] 28: # 错误码28: 文件系统已满 delay 0.25 # 磁盘满时LED闪烁更快以示警告 while True: led.value not led.value time.sleep(delay)操作流程与避坑指南部署将boot.py和上面的code.py复制到CIRCUITPY根目录。切换模式编辑模式确保D5引脚不连接GND。将板子通过USB连接到电脑。此时你可以自由修改code.py等文件。记录模式先安全弹出CIRCUITPY磁盘然后拔掉USB线。用跳线帽或杜邦线将D5引脚与GND引脚短接。最后再插上USB线给板子供电。此时板载LED应开始规律闪烁表示正在记录。电脑上能看到CIRCUITPY磁盘但无法向其中写入文件你会看到temperature.txt文件在不断变大。读取数据记录完成后先安全弹出磁盘并拔掉USB线移除D5和 GND 之间的短接线再重新插入USB。此时文件系统恢复为电脑可写你就可以用电脑打开temperature.txt用Excel或Python进行数据分析绘图了。致命陷阱提醒boot.py只在硬启动时执行一次如果你在记录模式下D5接地通过串口控制台按CtrlC然后CtrlD软复位或者直接在 Mu Editor 里保存文件触发的软复位boot.py是不会重新运行的文件系统会保持对 CircuitPython 可写的状态。此时如果你在电脑上尝试保存文件极有可能损坏整个文件系统导致所有代码和数据丢失。正确的操作永远是物理断电、改变引脚连接、再物理上电。6. 项目集成与扩展思路掌握了键盘模拟、鼠标模拟和数据采集这三项核心技能你已经可以开始创作有趣的项目了。下面分享几个我实践过的集成思路和扩展方向。6.1 项目一智能环境监控与自动报警器这个项目结合了数据采集和HID输出实现一个能“说话”的监控器。硬件Feather M4 Express 温湿度传感器如AHT20 光敏电阻 有源蜂鸣器。逻辑持续读取温度、湿度、光照数据。当温度超过阈值如35°C通过HID键盘模拟按下WinShiftSWindows截图并自动打开画图工具(Win, 输入“mspaint”, 回车)将警报信息“高温”画在图上并保存。同时蜂鸣器鸣叫。当光照低于阈值模拟按下键盘背光亮度增加键如果有或发送一封预设的邮件提醒。关键技术点需要合理规划time.sleep和状态机避免在警报触发时键盘指令发送得太快导致混乱。可以使用asyncio库来管理多个并发任务。6.2 项目二物理化流媒体播放控制器厌倦了用鼠标去点小小的播放/暂停按钮做一个专属控制器。硬件Trinket M0 或 QT Py小巧便宜 旋转编码器 几个电容触摸焊盘用铜箔胶带制作。逻辑旋转编码器顺时针旋转模拟“音量增大”(Keycode.VOLUME_INCREMENT)逆时针模拟“音量减小”(Keycode.VOLUME_DECREMENT)。按下编码器模拟“播放/暂停”(Keycode.PLAY_PAUSE)。电容触摸焊盘1触摸时模拟“下一曲”(Keycode.MEDIA_NEXT_TRACK)。电容触摸焊盘2触摸时模拟“上一曲”(Keycode.MEDIA_PREVIOUS_TRACK)。关键技术点adafruit_hid库内置了丰富的媒体键码直接调用即可。电容触摸使用touchio库非常简单。这个项目完美展示了如何用极简的硬件实现优雅的交互。6.3 性能优化与调试技巧当项目复杂后你可能会遇到性能或稳定性问题。减少time.sleep主循环中的sleep会降低响应速度。对于按钮检测可以使用中断alarm模块或更短的时间间隔配合状态去抖算法。使用asyncio进行多任务管理CircuitPython 支持asyncio。你可以创建一个任务用来轮询传感器另一个任务管理HID输出它们可以并发运行互不阻塞。串口调试是利器多使用print()输出变量状态。在复杂的鼠标移动逻辑中打印出steps(x)和steps(y)的值可以帮助你精确校准死区和速度映射曲线。电源管理如果是电池供电项目在循环中适当增加time.sleep可以大幅降低功耗。对于长时间数据记录可以考虑让单片机在记录间隙进入深度睡眠模式。7. 常见问题排查与解决方案实录在实际操作中你一定会遇到各种各样的问题。这里我把自己和学生们常踩的坑整理出来希望能帮你快速排雷。问题现象可能原因排查步骤与解决方案电脑完全无法识别CIRCUITPY磁盘1. USB线仅能供电无数据线。2. 板载UF2引导程序损坏。3. 主板USB口或驱动问题。1.换一根已知良好的USB数据线这是最常见的原因。2. 尝试双击板子上的复位按钮进入UF2引导模式有些板子LED会呈现呼吸灯效果。如果电脑出现一个名为BOOT或FEATHERBOOT的磁盘说明引导程序正常可以重新拖入CircuitPython的UF2固件文件。3. 换一个电脑USB口试试。能识别CIRCUITPY但代码不运行或报导入错误ImportError1. 库文件缺失或版本不匹配。2. 库文件放错了位置。3.code.py文件有语法错误。1. 打开串口终端如Mu Editor查看具体错误信息。如果提示No module named adafruit_hid就是库问题。2. 确认adafruit_hid.mpy等库文件在CIRCUITPY/lib/目录下且没有嵌套多层文件夹。3. 检查code.py代码特别是缩进和冒号。CircuitPython对缩进极其严格。键盘/鼠标模拟功能无效电脑无反应1. 缺少初始的time.sleep(1)。2. HID库未正确初始化。3. 代码逻辑错误未触发发送条件。1.确保在创建Keyboard()或Mouse()对象前有time.sleep(1)。2. 检查usb_hid.devices的导入和使用。3. 添加调试print语句确认程序执行到了发送按键的代码段。检查引脚电平读取是否正确按下时是否为False。鼠标光标抖动严重或移动不跟手1. 摇杆电压噪声大代码没有死区。2.pot_min/pot_max范围设置不准。3. 主循环执行太快移动步进值太小。1.必须实现死区。参考本文4.2节的steps()和条件判断逻辑。2. 实际测量摇杆极限电压校准参数。3. 可以适当增加mouse.move()的步进值如从1改为2或降低主循环频率增加time.sleep。无法向CIRCUITPY写入文件如温度日志1. 忘记部署或配置boot.py。2.boot.py中指定的切换引脚接线错误。3. 在记录模式下进行了软复位。1. 确认boot.py文件存在且内容正确特别是引脚定义与你的板子和实际接线一致。2.严格按照5.3节的操作流程先弹出磁盘、物理断电、改变引脚连接、再物理上电。3.切记在记录模式下不要通过串口进行软复位或保存文件操作程序运行一段时间后死机或无响应1. 内存泄漏在循环中不断创建对象。2. 文件系统错误频繁写入未妥善关闭文件。3. 硬件不稳定电源噪声。1. 避免在循环内import模块或创建大型对象。将对象创建移到循环外。2. 使用with open() as f:上下文管理器自动管理文件或确保file.close()被调用。写入后调用file.flush()。3. 尝试给板子供电的USB口加磁环或使用带滤波的电源模块。最后再分享一个血泪教训早期我用一个非Express板子做HID项目因为空间紧张我手动删除了lib里一些我认为“用不到”的库文件。结果项目运行起来后偶尔会随机触发一些奇怪的按键。排查了很久才发现是内存溢出导致程序跑飞错误地执行了某些数据段被电脑解释成了随机的USB数据包。所以库文件宁缺毋滥但也不要随意删除你不完全理解的库。对于复杂项目强烈建议从 Express 系列板子起步它们提供的充裕资源会让你省去很多底层优化的烦恼。希望这篇超详细的指南能帮你打开 CircuitPython HID 和传感器应用的大门。从模仿这些例子开始然后加入你自己的创意硬件编程的乐趣就在于此——让代码从屏幕里跳出来变成可以触摸和交互的实体。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2623568.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…