1. 从零开始为什么选择CircuitPython如果你之前玩过Arduino或者听说过用C语言给单片机写程序那你一定对“编译”、“烧录”、“工具链”这些词不陌生。整个过程就像是你想烤个蛋糕但得先从种小麦开始还得自己磨面粉、造烤箱。对于想快速验证一个硬件创意的开发者或者刚入门嵌入式的新手来说这个门槛实在有点高。CircuitPython的出现就是为了把“烤蛋糕”这件事变得像用微波炉加热预制菜一样简单。它本质上是一个运行在微控制器上的Python解释器。你不需要安装复杂的IDE集成开发环境不需要处理编译错误甚至不需要理解“中断”、“寄存器”这些底层概念。你只需要把开发板用USB线连上电脑电脑上会弹出一个名为CIRCUITPY的U盘你把写好的Python代码文件比如code.py拖进去代码就会自动运行。改代码直接打开文件修改、保存板子会自动重启并运行新代码。这种“即写即得”的体验让硬件编程的迭代速度提升了不止一个量级。我选择Adafruit Feather ESP32-S3作为演示平台原因有几个。首先Feather系列板型统一生态丰富有大量的“翅膀”Wing即扩展板可供选择方便项目扩展。其次ESP32-S3芯片本身性能强劲双核处理器、Wi-Fi/蓝牙、充足的GPIO和内存足以应对从简单传感器到复杂物联网设备的各种需求。最后它原生支持CircuitPython社区资源丰富遇到问题容易找到解决方案。2. 前期准备硬件与固件2.1 硬件清单与连接要点开始之前你需要准备好以下东西Adafruit Feather ESP32-S3开发板注意区分4MB Flash版本和8MB Flash版本本文后续的固件更新步骤主要针对4MB版本。一根优质的数据线这是最容易出问题的地方。务必使用数据同步线而不是只能充电的线。很多手机附带的短线就是充电线无法传输数据。如果你不确定最好找一根之前成功用于数据传输的Micro-USB或USB-C线取决于你的板子接口。一台电脑Windows、macOS或Linux均可。连接时直接将数据线一端接电脑另一端接开发板的USB口。我建议避免使用USB集线器或转接头特别是当你第一次尝试时。有些集线器或廉价的转接头供电或数据传输不稳定可能导致板子无法被正确识别或进入下载模式。注意关于供电Feather板设计非常贴心。它可以通过USB口供电也可以通过板载的JST PH接口连接锂电池供电。但绝对不要尝试一些危险操作比如不要将普通的碱性电池或镍氢电池接到电池端口这会损坏板上的锂电池充电管理芯片更不要将7.4V的航模电池接上去那会直接烧毁主板。虽然理论上你可以从3V和GND引脚接入外部3.3V电源或者从USB口的5V和GND引脚接入5V电源但这都不是推荐做法。前者可能导致使能EN引脚失效且无法为电池端口供电后者则可能在插入USB线时发生“反灌电”有损坏电脑USB口的风险。对于移动使用最安全的方式是使用一个USB充电宝。2.2 关键一步为CircuitPython 10更新TinyUF2引导程序仅4MB Flash版本这是很多人在升级到CircuitPython 10时容易忽略的关键步骤如果跳过可能会导致后续无法正常使用。原因在于CircuitPython 10为了容纳更多功能改变了在4MB Flash芯片上的存储布局。原先的布局留了两个OTA空中升级分区其中一个闲置未用。CircuitPython 10合并了这两个分区获得了更大的连续空间来存放固件本身。但这就需要一个能理解新布局的引导程序Bootloader来正确加载它。这个引导程序就是TinyUF2它负责在你双击复位按钮时让板子以一个U盘模式FTHRS3BOOT出现以便你拖入.uf2固件文件。操作流程如下备份数据这个过程会完全擦除CIRCUITPY盘里的所有内容。如果你之前已经在上面存了代码或库文件请先复制到电脑里备份。进入引导程序更新模式用数据线连接板子和电脑。找到板子上的复位按钮Reset快速双击它。此时板载的RGB LED应该会变成绿色或根据板子不同显示特定颜色。如果灯变红说明没成功多试几次掌握双击的节奏。对于ESP32-S3有时需要更精确的时机第一次按复位等LED变紫在它还是紫色时立刻再按一次。更新引导程序成功进入后电脑上会出现一个名为FTHRS3BOOT的U盘。打开它找到里面的INFO_UF2.TXT文件可以查看当前引导程序版本。你需要去Adafruit的官方指南页面找到“Factory Reset”或“UF2 Bootloader Installation/Repair”部分下载针对4MB板子的、适用于CircuitPython 10的TinyUF2引导程序文件通常是一个.uf2文件。将这个文件拖入FTHRS3BOOT盘。拖入后FTHRS3BOOT盘会消失这表示更新完成。验证再次双击复位按钮新的FTHRS3BOOT盘会出现。检查INFO_UF2.TXT确认版本号已更新到0.33.0或更高。完成这步后你的板子就准备好了迎接CircuitPython 10。这个新引导程序向下兼容也就是说你以后如果想降级回CircuitPython 9.x也无需再次更新引导程序。3. 安装与初体验让板子“活”起来3.1 下载并安装CircuitPython固件获取固件访问 circuitpython.org 找到你的板子型号Adafruit Feather ESP32-S3。务必下载标注为“稳定版”Stable的最新版本通常是版本号最高的那个.uf2文件。刷入固件确保板子处于引导程序模式即FTHRS3BOOT盘已出现。将下载好的.uf2文件直接拖入该U盘。拖入后FTHRS3BOOT盘会消失稍等片刻电脑上会出现一个新的名为CIRCUITPY的U盘。恭喜CircuitPython已经成功运行在你的板子上了这个CIRCUITPY盘就是你的代码舞台。所有操作都将在这个“磁盘”上进行。打开它你会看到一个code.py文件和一个空的lib文件夹。code.py是主板自动运行的主程序文件初始内容是一句print(Hello World!)。lib文件夹用来存放你项目需要的外部库文件比如驱动特定传感器或显示屏的库。3.2 选择合适的代码编辑器Mu vs. 其他工欲善其事必先利其器。虽然你可以用任何文本编辑器如VS Code、Sublime Text甚至记事本来编辑code.py但我强烈推荐初学者使用Mu Editor。为什么是Mu专为教育而生界面极其简洁没有复杂的功能干扰所有按钮一目了然。内置串口控制台这是最大的亮点。你不需要额外打开一个终端程序在Mu里一键就能看到板子打印的调试信息或错误报告对于排查问题至关重要。自动保存与安全弹出Mu在保存文件时会确保数据完整写入极大降低了因意外拔线导致CIRCUITPY磁盘损坏的风险。如果你用其他编辑器在Windows上必须手动“弹出”U盘在Linux上需要执行sync命令否则容易丢代码。模式匹配首次打开Mu它会让你选择模式选择“CircuitPython”即可。它能自动检测连接的板子。安装Mu直接访问 codewith.mu 下载对应你操作系统的安装包。Windows用户请注意如果之前装过旧版建议先卸载再安装新版。不使用Mu的注意事项如果你坚持使用其他编辑器请务必牢记“安全写入”原则。每次保存code.py后在Windows资源管理器中右键点击CIRCUITPY盘选择“弹出”在macOS上拖入废纸篓或使用diskutil unmount命令在Linux上打开终端执行sync命令。这是血的教训我因此丢失过好几个小时的代码。踩坑实录macOS Sonoma的写入Bug如果你用的是macOS Sonoma 14.1到14.3版本可能会遇到保存文件到CIRCUITPY盘极其缓慢甚至报错的问题。这是系统的一个Bug。解决方法是升级到macOS 14.4或更高版本。但要注意14.4版本修复Bug的代价是对1GB以下的小容量磁盘写入进行了限速所以速度可能还是不如以前。这是系统层面问题我们只能适应。4. 第一个程序深入理解LED闪烁现在让我们打开CIRCUITPY盘里的code.py用下面的代码替换原有内容。这就是经典的“Hello World”硬件版——让板载LED闪烁。import board import digitalio import time led digitalio.DigitalInOut(board.LED) led.direction digitalio.Direction.OUTPUT while True: led.value True time.sleep(0.5) led.value False time.sleep(0.5)保存文件。你会发现板子上的LED通常是红色开始以0.5秒的间隔闪烁。如果没亮别急我们先看看代码到底在做什么。4.1 代码逐行解析导入模块(import ...)board这个模块是你的硬件“地图”。它定义了板上所有引脚的名字比如board.LED就代表连接着LED的那个特定引脚。不同板子这个名称可能不同但CircuitPython帮你统一了访问方式。digitalio数字输入输出模块。你想控制一个引脚输出高电平点亮LED或低电平熄灭LED或者读取一个按钮的状态都得靠它。time时间模块最主要的功能就是sleep让程序暂停一段时间。设置LED引脚led digitalio.DigitalInOut(board.LED)这行代码创建了一个数字IO对象并告诉它我们要操作的是board.LED这个引脚。你可以把它想象成给这个引脚起了个叫led的绰号后面直接用led来操作就行。led.direction digitalio.Direction.OUTPUT设置这个引脚的方向为“输出”。因为我们要驱动LED是向它发送信号。如果是读取按钮就需要设置为INPUT。主循环(while True:)while True:创建了一个无限循环。只要板子通电里面的代码就会一遍又一遍地执行。这是嵌入式程序的标准模式因为硬件需要持续工作。led.value True将LED引脚设置为高电平在大多数板子上这会让LED点亮。time.sleep(0.5)程序休眠0.5秒。在这0.5秒里LED保持点亮状态。led.value False将LED引脚设置为低电平熄灭LED。time.sleep(0.5)再休眠0.5秒LED保持熄灭。循环回到开头LED再次点亮……如此往复。4.2 动手实验修改参数观察现象理论学习不如动手一试。试着修改代码中的参数把第一个0.5改成0.1保存。你会发现LED亮的时间变短了闪烁频率变快但灭的时间还是0.5秒所以节奏是“短亮-长灭”。再把第二个0.5也改成0.1保存。现在亮和灭都是0.1秒LED就会疯狂快闪。把两个0.1都改成1保存。LED就会慢悠悠地一秒亮、一秒灭。通过这个简单的修改你实际上已经理解了如何通过代码控制时间的尺度从而控制硬件的行为。这就是硬件编程的乐趣所在——直观的物理反馈。重要提示关于没有单色LED的板子不是所有板子都有一颗像Feather ESP32-S3这样的单色LED。比如Adafruit的KB2040、QT Py等板子它们只有一颗RGB NeoPixel LED一种智能彩灯。上面的代码对它们无效。你需要使用控制NeoPixel的库。一个简单的NeoPixel闪烁示例代码可以在Adafruit的指南页面找到。核心思想是一样的只是控制的对象从简单的数字引脚变成了需要发送特定数据协议的NeoPixel。5. 调试利器串口控制台与REPL代码运行了但你怎么知道它内部发生了什么怎么查看变量的值怎么在出错时定位问题这就需要用到CircuitPython的两大交互功能串口控制台和REPL。5.1 串口控制台你的程序输出窗口串口控制台就像一个连接到板子上的“命令行输出窗口”。所有在代码中用print()函数打印的信息都会显示在这里。更重要的是当你的代码运行出错时详细的错误信息也会打印到这里这是调试的黄金线索。在Mu中使用串口控制台确保板子已连接在Mu编辑器上方找到一排图标点击那个像“无线电波”的Serial按钮。Mu窗口下方会分出一个区域这就是串口控制台。如果里面是空的可以按CtrlD这是CircuitPython的软复位快捷键或者点击控制台区域再按CtrlD你会看到程序重新启动的输出。让我们修改一下闪烁代码加入print语句import board import digitalio import time led digitalio.DigitalInOut(board.LED) led.direction digitalio.Direction.OUTPUT while True: print(LED ON) led.value True time.sleep(0.5) print(LED OFF) led.value False time.sleep(0.5)保存后观察串口控制台你会看到“LED ON”和“LED OFF”交替出现。这证实了你的循环正在正确执行。5.2 错误排查实战故意制造一个错误来学习如何排查。把led.value True改成led.value Tru少写一个e然后保存。你会发现LED停止闪烁板子上的状态灯可能开始异常闪烁这是CircuitPython进入错误状态的提示。此时看串口控制台你会看到类似这样的信息Traceback (most recent call last): File code.py, line 10, in module NameError: name Tru is not defined这就是“回溯信息”。它告诉你Traceback (most recent call last):错误追踪开始。File code.py, line 10, in module错误发生在code.py文件的第10行。NameError: name Tru is not defined错误类型是NameError意思是“名称‘Tru’未定义”。Python不认识Tru这个变量或关键字。有了这个你就能迅速定位到第10行发现拼写错误。修复它保存一切恢复正常。这种“打印调试法”print debugging和利用错误信息的能力是每个程序员的基本功。5.3 REPL交互式Python命令行如果说串口控制台是看输出的“监视器”那么REPL就是可以直接输入命令的“键盘”。REPL代表“读取-求值-打印-循环”你可以把它理解成一个运行在板子上的即时Python命令行。进入REPL在串口控制台激活的状态下Mu里就是打开了Serial窗口按下CtrlC。这会中断当前正在运行的code.py程序。如果程序在运行你会看到“Press any key to enter the REPL. Use CTRL-D to reload.”的提示此时按任意键即可进入。如果code.py是空的或没有循环可能会直接显示Code done running.同样按任意键进入。进入后你会看到提示符。现在你可以直接输入Python命令并立即执行输入import board回车。输入import digitalio回车。输入led digitalio.DigitalInOut(board.LED)回车。输入led.direction digitalio.Direction.OUTPUT回车。输入led.value True回车——LED亮了输入led.value False回车——LED灭了。你可以在这里进行任何Python探索计算11定义函数测试新的库等等。要退出REPL并重新运行code.py按CtrlD即可。REPL在测试硬件、快速验证某个想法、或者当主程序卡死时进行干预都非常有用。6. 项目进阶与文件管理6.1 程序文件命名规则CircuitPython启动时会按顺序查找以下文件来执行code.txt-code.py-main.txt-main.py。找到第一个存在的就执行它。虽然我们一直用code.py但你需要知道这个规则。有时候你可能会不小心创建了一个main.py然后奇怪为什么改code.py没效果原因就是板子先找到了main.py并执行了它。6.2 使用库文件当你的项目需要用到外部传感器或模块时就需要用到库。库文件通常以.mpy或.py为后缀需要放置在CIRCUITPY盘下的lib文件夹内。例如你想使用一个温湿度传感器DHT22你需要去Adafruit的CircuitPython库包Bundle中找到adafruit_dht.mpy库。将这个文件复制到CIRCUITPY盘的lib文件夹里。在你的code.py中就可以通过import adafruit_dht来使用它了。Adafruit为几乎所有他们销售的传感器、显示屏、执行器都提供了CircuitPython库这是生态强大的体现。库Bundle可以在CircuitPython官网上找到定期更新。6.3 避免文件系统损坏这是一个必须重视的问题。CircuitPython在检测到CIRCUITPY盘上的文件被修改保存、创建、删除时会自动复位板子以重新运行新代码。如果在电脑向U盘写入数据的过程中保存文件还没完成拔掉USB线或按复位键就可能导致文件系统损坏。症状就是CIRCUITPY盘再也无法出现或者出现但无法读写。预防措施使用Mu编辑器它内置了安全写入机制。手动安全弹出如果使用其他编辑器在每次保存操作后务必执行系统级的“弹出”或“同步”操作。代码保护在code.py文件的最开头加入以下两行可以禁用文件修改时的自动复位但请注意这样你改了代码就需要手动复位才能生效import supervisor supervisor.runtime.autoreload False救砖指南如果不幸损坏也别慌。Feather ESP32-S3这类支持UF2的板子很难变砖。只需双击复位按钮再次进入FTHRS3BOOT模式然后重新拖入CircuitPython的.uf2固件文件即可完全恢复。这相当于重装了一遍系统CIRCUITPY盘会被格式化并恢复初始状态。所以养成定期将重要代码备份到电脑的习惯总是好的。7. 常见问题与排查技巧实录在实际操作中你肯定会遇到各种各样的问题。这里我总结了一份速查表涵盖了从开始到运行第一个程序可能遇到的大部分坑。问题现象可能原因排查步骤与解决方案电脑完全不识别板子没有弹出FTHRS3BOOT或CIRCUITPY盘。1. USB线是充电线无数据传输功能。2. USB端口或集线器故障。3. 驱动程序问题多见于旧版Windows。4. 板子未正确进入下载模式。1.换一根确认可传数据的线这是最高频的原因。2. 将板子直接插入电脑主板上的USB口绕过集线器。3. 对于Windows 7/8可能需要手动安装Adafruit的驱动程序Windows 10/11通常自动识别。4. 确保双击复位按钮的节奏正确。对于ESP32-S3尝试“按一次等灯变紫立刻再按一次”的时序。多试几次。能看到FTHRS3BOOT盘但拖入.uf2文件后没反应或报错。1. 下载的固件文件型号不对。2. 文件损坏。3. 存储空间已满极罕见。1. 去circuitpython.org官网仔细核对板子型号如Feather ESP32-S3 4MB vs 8MB下载正确的.uf2文件。2. 重新下载固件文件。3. 尝试格式化FTHRS3BOOT盘风险操作建议先看官方指南。CIRCUITPY盘出现但Mu编辑器提示“找不到CircuitPython板”。1. Mu编辑器模式设置错误。2. 板子被其他程序占用如串口监视器。1. 检查Mu编辑器右下角模式是否设置为“CircuitPython”。2. 关闭其他可能占用串口的程序如Arduino IDE的串口监视器、其他终端软件。代码保存后LED不闪烁串口控制台无输出。1. 代码有语法错误。2. 文件未以code.py或main.py命名。3. 使用了不正确的引脚名如板子没有board.LED。1.打开串口控制台Mu中按Serial查看错误信息。这是最重要的调试手段。2. 确认文件保存在CIRCUITPY根目录且名称正确。3. 查阅你的板子说明书确认LED对应的引脚名称。有些板子是board.LED有些是board.D13或board.NEOPIXEL。串口控制台一片空白按CtrlD也没反应。1. 串口连接断开。2. 板子处于深度睡眠或异常状态。3. 在Linux上modemmanager服务干扰。1. 重新插拔USB线在Mu中重新点击Serial连接。2. 尝试双击复位按钮让板子完全重启。3. 对于Linux用户在终端执行sudo apt purge modemmanager移除该服务如果你不用拨号上网的话。修改代码并保存后板子没有自动重启运行新代码。1. 在代码开头设置了supervisor.runtime.autoreload False。2. 文件系统繁忙或错误。1. 检查代码开头是否有禁用自动重载的语句注释掉或删除它。2. 安全弹出CIRCUITPY盘然后重新插拔USB线。或者在串口控制台按CtrlD手动软复位。在Windows上向CIRCUITPY盘复制文件经常失败或速度极慢。Windows的写入缓存策略导致。1.使用Mu编辑器它处理了这个问题。2. 如果使用其他编辑器每次保存后务必在资源管理器中对CIRCUITPY盘右键点击选择“弹出”。3. 可以考虑在设备管理器中为该磁盘驱动器禁用“写入缓存”但这不是通用推荐做法。掌握以上排查方法你就能解决90%的入门级问题。记住串口控制台是你的第一求助对象任何异常行为先看那里有没有输出错误信息。从双击复位按钮看到FTHRS3BOOT盘到拖入固件见到CIRCUITPY盘再到写下几行代码控制一个物理LED闪烁这个过程本身就是一个完整的“从想法到实现”的微型闭环。CircuitPython的魅力就在于它极大地压缩了这个闭环的反馈时间让你能更专注于逻辑和创意本身而不是纠缠于工具链和环境配置。当你熟悉了这套流程接下来就可以尽情探索各种传感器、显示屏、网络连接去构建更复杂的项目了。硬件世界的大门已经通过这几行简单的Python代码向你敞开。