树莓派Pico CLI开发实战:用ampy实现高效自动化部署

发布时间:2026/6/14 21:00:07

树莓派Pico CLI开发实战:用ampy实现高效自动化部署 1. 项目概述为什么选择CLI来操作树莓派Pico如果你和我一样是从玩Arduino或者用Thonny这类图形化IDE开始接触树莓派Pico的那么第一次听说“用命令行来操作它”时可能会觉得有点多此一举。毕竟Thonny点几下就能上传代码、看到REPL交互界面不是挺方便的吗但当你开始做更复杂的项目比如需要批量部署十几个传感器节点或者想把Pico集成到一个自动化的CI/CD持续集成/持续部署流程里时图形界面的局限性就暴露出来了。你不能指望每次更新代码都手动点一遍“保存”和“运行”更没法写个脚本让它自动完成。这就是命令行界面CLI工具的价值所在。它把与Pico的交互变成了一系列可以脚本化、自动化的命令。adafruit-ampy就是这样一个专为MicroPython设计的“瑞士军刀”。它的核心原理其实不复杂Pico通过USB虚拟出一个串行通信端口COM口ampy工具通过这个端口使用一套简单的协议类似于古老的XMODEM但更轻量与Pico板载的MicroPython解释器进行“对话”。这个对话可以是指令“把电脑上这个文件传过去”、“执行一下那段代码”、“告诉我板子上现在有哪些文件”。我选择CLI工作流主要基于三个实际痛点效率、自动化和环境一致性。在服务器后台或者无头Headless模式下开发时你根本没有图形界面可用在反复调试某个脚本时用命令行一键上传并运行比在IDE里切换窗口快得多在团队协作中一个ampy命令脚本能确保每个人部署的环境和步骤完全一致避免了“在我电脑上是好的”这类问题。所以这篇内容适合所有已经对Pico和MicroPython有基本了解希望提升开发效率、实现工作流自动化或者正在寻找一种更“极客”、更贴近生产环境部署方式的开发者。我们将深入adafruit-ampy的每一个细节不止于简单的命令罗列更会分享我在实际项目中踩过的坑和总结出的技巧。2. 环境准备与工具链深度解析在敲下第一个ampy命令之前扎实的环境准备是成功的一半。这一步的细节直接决定了后续操作是顺畅还是充满“玄学”报错。2.1 核心工具adafruit-ampy 的安装与版本选择官方推荐用pip install adafruit-ampy安装这当然没错。但这里有几个关键细节决定了你的体验。首先强烈建议使用虚拟环境。Python的包依赖管理是个老生常谈的问题。如果你系统里还运行着其他用到了pyserial库的项目版本冲突可能导致ampy连接不稳定。我的做法是为嵌入式开发单独创建一个虚拟环境# 创建并进入一个名为‘pico_dev’的虚拟环境 python -m venv pico_dev source pico_dev/bin/activate # Linux/macOS # 或 pico_dev\Scripts\activate # Windows # 然后在虚拟环境中安装 pip install adafruit-ampy其次注意ampy的版本。截至我写这篇文章时PyPI上的主要版本是1.x系列。但社区也有一个活跃的维护分支。你可以通过pip list | findstr ampy(Windows) 或pip list | grep ampy(Linux/macOS) 来查看安装的版本。如果遇到连接问题可以尝试安装开发版pip install githttps://github.com/adafruit/ampy.git。我个人的经验是1.0.7版本在大多数场景下非常稳定。注意adafruit-ampy依赖于pyserial库来操作串口。安装ampy时会自动安装它。如果后续遇到权限问题或端口占用多半是pyserial层面的事情。2.2 系统级准备串口驱动与权限这是新手最容易卡住的地方尤其是在Linux和macOS上。Windows系统通常最省心。将Pico插入USB口系统会自动识别为“USB串行设备”并在设备管理器的“端口COM和LPT”下分配一个COM号如COM3。你需要记下这个数字。如果没出现可能需要手动安装树莓派基金会提供的Pico驱动但Win10及以上系统通常免驱。macOS系统系统会将其识别为/dev/tty.usbmodemXXXX或/dev/tty.usbserial-XXXX设备。你需要有访问该设备的权限。通常你需要将你的用户添加到dialout或uucp组。更简单但安全性稍低的方法是临时修改权限sudo chmod 666 /dev/tty.usbmodemXXXX或者一劳永逸的方法是创建一个udev规则Linux方法也适用但对于个人开发每次上电后执行一次上述命令也能接受。Linux系统如Ubuntu情况类似。设备通常为/dev/ttyACM0或/dev/ttyUSB0。同样面临权限问题。将用户加入dialout组是最佳实践sudo usermod -a -G dialout $USER执行此命令后必须注销并重新登录用户组变更才会生效。之后你就能正常访问/dev/ttyACM0了。2.3 硬件准备Pico的MicroPython固件与启动模式adafruit-ampy工作的前提是你的Pico正在运行MicroPython固件并且处于正常的运行模式而不是USB大容量存储设备模式。确保固件正确如果你刚拿到一块新的Pico需要先刷入MicroPython固件。去树莓派基金会官网下载最新的.uf2固件文件。按住Pico上的BOOTSEL按钮不放插入USB线此时电脑会识别出一个名为RPI-RP2的U盘。将下载的.uf2文件拖入这个U盘Pico会自动重启并运行MicroPython。区分两种模式运行模式Pico正常启动后USB口用于串行通信REPL和文件传输。这是ampy工作的模式。BOOTSEL模式按住BOOTSEL按钮上电进入U盘模式用于刷固件。ampy在此模式下无法工作。一个快速检查方法是打开任何串口终端工具如putty,screen,minicom连接Pico的串口波特率设为115200。如果按回车出现的MicroPython REPL提示符说明它处于正确的运行模式。如果没反应或者显示乱码很可能还在BOOTSEL模式或者串口参数不对。3. 核心操作ampy命令详解与实战技巧安装好环境确认了端口我们就可以开始和Pico“对话”了。ampy的命令结构很清晰ampy --port PORT [--baud BAUDRATE] COMMAND [ARGS]。下面我们拆解每一个核心命令并附上我积累的实战技巧。3.1 端口连接与基础查询首先我们得告诉ampy我们的Pico在哪里。假设我的Pico在Linux上是/dev/ttyACM0。列出板载文件系统ampy --port /dev/ttyACM0 ls这个命令相当于在Pico的MicroPython里执行import os; os.listdir()。首次运行一个刷好固件的新Pico你可能会看到boot.py文件。这是MicroPython启动时自动运行的系统文件。技巧1使用环境变量简化命令每次输入长端口号很麻烦。可以设置一个环境变量export AMPY_PORT/dev/ttyACM0 # Linux/macOS添加到~/.bashrc或~/.zshrc永久生效 # 或 set AMPY_PORTCOM3 # Windows命令提示符 # 或 $env:AMPY_PORTCOM3 # Windows PowerShell设置后命令简化为ampy ls极大提升效率。获取更详细的文件信息ampy ls只显示文件名。如果你想看文件大小对于资源受限的Pico管理空间很重要可以使用ampy --port /dev/ttyACM0 ls -l这会在文件名后显示字节大小。注意Pico的内部闪存大约2MB可用空间约1.3MB监控文件大小是个好习惯。3.2 文件传输上传、下载与删除这是最常用的功能细节也最多。上传文件到Picoampy --port /dev/ttyACM0 put my_local_script.py /remote_name.pymy_local_script.py你电脑上的本地文件路径。/remote_name.py要保存到Pico上的路径和文件名。开头的/代表根目录可以省略ampy默认上传到根目录。你也可以指定子目录如/lib/my_module.py但前提是/lib目录必须已存在。踩坑记录1文件覆盖与编码ampy put会静默覆盖Pico上的同名文件没有确认提示上传前最好先用ampy ls确认一下。 另外确保你的本地Python文件是UTF-8无BOM格式编码。如果文件中有中文注释或字符串使用Windows记事本保存的默认ANSI或UTF-8 BOM格式可能会导致Pico执行时报语法错误。建议使用VS Code、Notepad等编辑器明确设置编码为UTF-8。从Pico下载文件ampy --port /dev/ttyACM0 get boot.py local_boot_backup.py这个命令在你想备份Pico上的脚本或者查看Pico运行时生成的数据文件比如传感器日志时非常有用。删除Pico上的文件ampy --port /dev/ttyACM0 rm old_script.py警告删除操作不可逆Pico没有回收站。尤其不要轻易删除boot.py除非你知道自己在做什么。boot.py是启动脚本删除后虽然MicroPython仍能运行但自定义的启动初始化就没了。技巧2使用通配符不行但可以变通ampy本身不支持rm *.py这样的通配符操作。如果你需要清理大量文件一个办法是在本地写一个简单的Python脚本利用ampy的Python APIfrom ampy.pyboard import Pyboard来实现先ls获取文件列表再循环删除匹配项。这体现了CLI工具可编程的优势。3.3 代码执行run命令的机制与局限ampy run是另一个核心功能但它的工作原理和很多人想的不一样。ampy --port /dev/ttyACM0 run blink.py这条命令并不是像在电脑上执行python blink.py那样启动一个独立的进程来运行脚本。它的实际过程是将blink.py文件的内容读取到内存。通过串口将文件内容以文本形式发送到Pico的REPL交互式解释器。相当于在Pico的提示符下逐行粘贴并执行了整个脚本。这意味着什么执行是“一次性”的脚本运行结束后其中定义的函数、变量虽然可能存在于当前REPL会话的内存中但脚本进程本身结束了。对于blink.py这种包含无限循环while True:的脚本ampy run会阻塞直到你按CtrlC中断串口连接这也会打断Pico上的循环。所以它不适合运行需要长期后台运行的任务。最佳用途快速测试写了一个小函数想立刻测试一下效果。执行初始化脚本运行一个设置Wi-Fi连接、创建网络套接字的脚本。触发一次性任务读取一次传感器数据并打印出来。如何运行“后台”程序如果你想让一个脚本如一个Web服务器、一个数据记录器在Pico上持续运行正确做法是将主脚本命名为main.py并使用ampy put main.py上传。重启Pico拔插USB或软重启。MicroPython启动后会自动执行main.py文件中的代码并且会一直运行下去。此时你仍然可以通过ampy run another_script.py来执行其他辅助脚本与正在运行的main.py并行前提是代码逻辑不冲突。3.4 目录管理创建与删除MicroPython支持简单的目录结构。创建目录ampy --port /dev/ttyACM0 mkdir /lib ampy --port /dev/ttyACM0 mkdir /data/logs可以创建多级目录。删除目录ampy --port /dev/ttyACM0 rmdir /data/logs重要ampy rmdir只能删除空目录。如果目录里有文件需要先递归删除所有文件。ampy没有提供递归删除的命令这需要自己写脚本实现同样是利用Python API。递归删除目录的示例脚本思路# 本地电脑上运行的Python脚本例如 delete_dir.py import os from ampy.pyboard import Pyboard board Pyboard(/dev/ttyACM0, 115200) # 使用ampy底层API def recursive_rmdir(board, path): # 1. 列出目录下所有项 items board.fs_ls(path) for item in items: full_path path / item if path ! / else / item # 2. 判断是文件还是目录这里需要根据ampy返回格式解析 # 假设我们通过某种方式判断item是目录例如以‘/’结尾但ampy ls不返回斜杠 # 实际上更可靠的方法是尝试作为文件删除如果失败再作为目录处理。 # 由于ampy API限制实现完整的递归删除较为复杂通常建议在Pico端用MicroPython脚本清理。 pass # 3. 删除空目录 board.fs_rmdir(path) # 更实用的建议在Pico上写一个清理脚本鉴于复杂性对于复杂的文件清理我通常会在Pico上写一个MicroPython脚本通过ampy run cleanup.py来执行删除操作。4. 高级应用与自动化脚本编写掌握了基础命令我们就可以将它们组合起来实现自动化这才是CLI的威力所在。4.1 编写部署脚本Shell/Batch假设我有一个项目包含主程序main.py、一个库文件lib/sensor.py和一个配置文件config.json。我可以写一个部署脚本deploy.sh(Linux/macOS) 或deploy.bat(Windows)#!/bin/bash # deploy.sh PORT${1:-/dev/ttyACM0} # 允许通过参数指定端口默认/dev/ttyACM0 echo Deploying to Pico on port $PORT # 1. 创建库目录如果不存在ampy mkdir如果目录已存在会报错可以忽略 ampy --port $PORT mkdir /lib 2/dev/null || true # 2. 上传库文件 echo Uploading library files... ampy --port $PORT put lib/sensor.py /lib/sensor.py # 3. 上传配置和主程序 echo Uploading main program and config... ampy --port $PORT put config.json ampy --port $PORT put main.py # 4. 软重启Pico使新的main.py生效 echo Resetting Pico... ampy --port $PORT reset # 注意ampy reset命令可能因版本/固件不同而表现不一 echo Deployment complete.在Windows批处理中逻辑类似只是语法不同。通过脚本一键完成整个项目的部署。4.2 集成到CI/CD流程在GitLab CI或GitHub Actions中你可以配置一个自动化任务每当代码推送到主分支时自动将最新固件部署到连接在服务器上的Pico硬件进行集成测试。一个简化的GitHub Actions工作流示例.github/workflows/deploy.yml片段jobs: deploy-pico: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Setup Python uses: actions/setup-pythonv4 with: python-version: 3.10 - name: Install ampy run: pip install adafruit-ampy - name: Deploy to Pico run: | # 假设Pico已连接到运行器的USB口端口可通过环境变量获得 ampy --port ${{ secrets.PICO_PORT }} put src/main.py /main.py ampy --port ${{ secrets.PICO_PORT }} run tests/run_tests.py这里PICO_PORT作为加密机密存储在仓库设置中。这实现了真正的自动化硬件在环测试。4.3 使用Python API进行更精细控制adafruit-ampy也提供了Python编程接口适合在更复杂的Python脚本中调用。例如你想在上传文件前先检查Pico的剩余空间# local_script.py from ampy.pyboard import Pyboard import os port /dev/ttyACM0 board Pyboard(port) # 获取文件系统信息需要Pico端有特定脚本支持非标准功能 # 更通用的做法是尝试写入一个临时文件来探测空间 test_content bx * 100 try: # 注意Pyboard API的使用方式可能与命令行略有不同 # 这里仅为示意实际请参考ampy源码 board.fs_put(test_space, test_content) board.fs_rm(test_space) print(Space seems OK.) except Exception as e: print(fPossible space issue: {e}) # 使用board对象进行文件操作 with open(local_main.py, r) as f: code f.read() board.exec_(with open(main.py, w) as f: f.write(r{}).format(code)) # 注意转义 board.close()直接使用API给了你最大的灵活性但需要对ampy的源码和MicroPython的交互协议有更深了解。5. 故障排查与常见问题实录即使准备得再充分在实际操作中还是会遇到各种问题。下面是我总结的“排错手册”。5.1 连接类问题问题ampy --port COM3 ls报错Could not enter raw repl或Failed to access /dev/ttyACM0。排查思路1端口是否正确Windows检查设备管理器的端口号是否变化。拔插一次Pico看COM号是否改变。Linux/macOS拔插前后分别执行ls /dev/tty*观察哪个设备出现或消失。技巧一个可靠的命令是ampy --list-ports某些版本支持或使用Python的python -m serial.tools.list_ports来列出所有可用串口。排查思路2权限是否足够Linux/macOS确保当前用户有读写权限。用ls -l /dev/ttyACM0查看如果属于root:root则需要按2.2节的方法修改权限或用户组。排查思路3端口是否被占用你是否同时打开了Thonny、Putty或其他串口终端连接着同一个Pico关闭所有可能占用该串口的程序。Windows上可以用netstat -ano | findstr COM3查找占用端口的进程。排查思路4Pico是否处于正确模式确保Pico处于运行模式REPL模式而不是BOOTSEL模式。用串口终端连接看是否有提示符。问题连接时断时续或执行命令超时。可能原因1USB线或USB口供电不稳。换一根质量好的USB数据线并连接到电脑主板后置USB口避免使用前端扩展坞或劣质延长线。可能原因2波特率不匹配。虽然MicroPython REPL默认115200但某些固件或配置可能不同。尝试指定波特率ampy --port /dev/ttyACM0 --baud 115200 ls。也可以尝试常见的9600、57600等。可能原因3Pico上运行的程序阻塞了REPL。如果main.py里有一个死循环且没有释放CPU如while True: pass可能会影响ampy通过REPL通信。尝试在Pico上按CtrlC中断当前程序回到空闲的提示符。5.2 文件操作类问题问题ampy put上传成功但文件在Pico上显示为空或执行出错。原因1文件编码问题。如前所述务必使用UTF-8无BOM编码保存文件。原因2文件路径或名称包含特殊字符或中文。MicroPython对文件路径支持有限尽量使用英文、数字和下划线。原因3上传过程中串口干扰。尝试降低波特率如--baud 9600上传大文件。问题ampy run一个脚本没有任何输出就结束了。原因脚本可能执行得很快或者没有print语句。ampy run默认只捕获和显示脚本输出到标准输出stdout的内容。如果脚本只有函数定义或变量赋值没有打印自然看不到输出。可以在脚本末尾加一句print(Script finished)来确认。调试技巧对于复杂脚本先用ampy put上传然后用ampy run -n如果版本支持-n不进入交互模式或直接通过串口终端手动import执行可以更好地看到错误信息。5.3 资源与性能问题问题Pico提示OSError: [Errno 28] ENOSPC或存储空间不足。分析Pico的可用闪存空间约1.3MB。boot.py、main.py、库文件、数据文件都会占用空间。解决使用ampy ls -l查看各文件大小。删除不必要的文件ampy rm old_file.py。优化代码移除未使用的库压缩字符串常量。如果项目文件确实很大考虑使用外接SPI Flash芯片或SD卡来扩展存储。问题使用ampy频繁操作后Pico变得无响应。分析可能是文件系统损坏或者某个操作如写入时断电导致状态异常。解决最彻底的方法是重新刷写MicroPython固件。这会清空所有文件恢复出厂状态。尝试在Pico的REPL中执行import os; os.fsformat()来格式化文件系统危险会丢失所有数据。5.4 命令与版本差异不同版本的adafruit-ampy命令可能略有差异。例如早期版本可能没有reset命令或者run命令的参数不同。一个良好的习惯是使用ampy --help查看你当前安装版本的具体帮助信息。当你在网上看到某个教程的命令不 work 时第一反应应该是检查版本差异。最后分享一个我个人的小习惯在开始一个重要的部署或测试序列前我总是先用ampy ls快速检查一下连接是否通畅这就像一个“心跳检测”能提前避免很多后续的莫名错误。CLI工具的魅力就在于一旦你熟悉了这些命令和它们背后的逻辑你就能像指挥乐队一样高效、精准地管理你的嵌入式设备阵列。

相关新闻