1. 项目概述从芯片温度到数据洞察在嵌入式项目里给设备“把脉”是基本功。CPU温度这个看似简单的数据点其实是窥探硬件运行状态的绝佳窗口。它不仅能告诉你芯片是不是在“发烧”更能间接反映环境变化、负载情况甚至是散热设计的有效性。以前做这类监控往往得外挂一个温度传感器再折腾ADC采样和校准流程繁琐。直到我发现很多现代微控制器比如Adafruit常用的SAMD21系列其CPU内部就集成了温度传感器并且CircuitPython已经把它做成了一个开箱即用的属性。这个项目的核心就是绕开复杂的硬件电路直接利用microcontroller.cpu.temperature这个“内置仪表”把读取到的温度数据以文本日志的形式实时记录到开发板自带的闪存文件系统中。整个过程你只需要几行Python代码无需焊接无需额外的元器件真正体现了CircuitPython“快速原型”的理念。它非常适合用于长期部署的设备健康监测、环境温度趋势分析需注意CPU温度与环境温度的差异和滞后性或是作为学习嵌入式数据采集与文件IO的入门实践。2. 核心思路与方案选型解析2.1 为什么选择CircuitPython与内置传感器这个方案的核心优势在于“极简”。传统MCU开发无论是用Arduino C还是裸机C读取内部温度传感器都需要直接操作芯片的寄存器涉及复杂的模数转换、校准系数计算对新手极不友好。CircuitPython的microcontroller模块将这些底层细节全部封装提供了一个直接的.temperature属性返回的就是摄氏度浮点数极大地降低了技术门槛。选择文件系统记录而非无线传输或外接SD卡是基于场景的权衡。对于很多低功耗、离线或原型验证阶段的项目首先需要的是可靠、简单的数据落地方案。开发板内置的闪存通常有几MB虽然空间有限但记录温度这类小数据绰绰有余。直接写入文件系统数据立即可通过USB在电脑上查看流程闭环调试方便。这个方案奠定了数据流的基础感知CPU温度 - 处理可选单位转换 - 存储本地文件。2.2 权限管理一个关键的设计挑战这里遇到一个嵌入式系统里经典的矛盾开发便利性与运行时安全性的冲突。CircuitPython设备连接电脑后其内部存储会作为一个U盘USB Mass Storage挂载方便我们直接拖拽修改code.py等文件。但如果在程序运行code.py时也允许Python代码向同一个文件系统写入数据就会产生访问冲突可能导致数据损坏。因此CircuitPython默认将文件系统设置为“只读”模式供代码访问以保证USB侧可写。我们的日志程序需要写文件就必须改变这个默认行为。这就是boot.py和storage模块出场的原因。boot.py在系统启动、USB连接建立之前执行在这里我们可以用storage.remount(“/”, False)将根目录重新挂载为可写。但这样一来USB侧就失去了写入权限你无法再通过电脑直接编辑代码了。为了解决这个两难问题原教程给出了一个巧妙的硬件交互方案通过一个物理开关或跳线来动态决定启动时的挂载模式。具体来说在boot.py中检测某个GPIO引脚如D0的电平。如果该引脚被接地拉低则启动为“代码可写”模式用于数据记录如果该引脚悬空或拉高则保持默认的“USB可写”模式方便代码更新。这种设计将控制权交给了硬件状态非常符合嵌入式开发“硬软结合”的思维。3. 硬件准备与软件环境搭建3.1 硬件选型与连接本项目对硬件要求极低。核心是一块支持CircuitPython且CPU内置温度传感器的开发板。Adafruit Gemma M0、Trinket M0、Feather M0系列以及功能更丰富的Circuit Playground Express、Metro M4等只要是基于SAMD21Cortex-M0或SAMD51Cortex-M4F等系列芯片的板子通常都支持。购买前最好查阅官方文档确认microcontroller.cpu.temperature属性可用。对于实现“选择性挂载”功能你需要准备一个物理开关或一根跳线。以Gemma M0为例找一根杜邦线或直接用金属镊子/导线。将开发板的D0引脚或你代码中定义的其他引脚与GND地引脚短接。 这个短接动作就是在告诉boot.py“这次启动请允许我的代码写入文件系统”。当你需要更新代码时断开这个短接即可。注意Circuit Playground Express板载了一个滑动开关其电路已经连接到了D7引脚。因此对于CPX你无需额外飞线直接使用这个开关即可在代码中将检测的引脚改为board.D7。3.2 CircuitPython固件更新与库确认确保你的开发板运行的是CircuitPython 2.0.0或更高版本因为storage模块和microcontroller.cpu.temperature属性是从该版本引入的。更新固件是第一步访问CircuitPython官网找到你的板型对应的最新.uf2固件文件。将板子通过USB连接电脑并快速双击复位按钮使其进入BOOTLOADER模式此时电脑会出现一个名为CPLAYBOOT、FEATHERBOOT等的U盘。将下载的.uf2文件拖入该U盘。盘符会自动弹出稍等片刻板子重启后就会出现一个新的名为CIRCUITPY的U盘这表明CircuitPython固件已刷写成功。固件本身已包含microcontroller、storage、board、digitalio等核心模块无需额外安装库文件这为我们省去了很多依赖管理的麻烦。4. 核心代码实现与分步详解4.1 创建动态挂载控制的boot.py这个文件是系统启动的钥匙它只执行一次。我们将实现通过硬件引脚状态决定文件系统权限的逻辑。# SPDX-FileCopyrightText: 2017 Limor Fried for Adafruit Industries # SPDX-License-Identifier: MIT import board import digitalio import storage # 1. 初始化硬件开关引脚 # 这里以D0为例如果你用CPX的滑动开关请改为 board.D7 switch_pin board.D0 switch digitalio.DigitalInOut(switch_pin) # 2. 配置引脚为输入模式并启用内部上拉电阻 switch.direction digitalio.Direction.INPUT switch.pull digitalio.Pull.UP # 默认内部上拉到高电平 # 3. 根据引脚电平决定挂载模式 # switch.value 在引脚被拉低接地时为 False悬空/拉高时为 True # 我们需要在引脚接地False时让代码可写readonlyFalse storage.remount(/, readonlyswitch.value)代码解读与实操要点digitalio.Pull.UP启用内部上拉电阻至关重要。它确保在引脚悬空时其电平能被稳定地拉至高电平逻辑1或True避免因静电干扰产生误判。只有当用导线明确将引脚与GND连接时电平才会被拉低至False。storage.remount(“/“, readonlyswitch.value)这是权限切换的核心。readonly参数为True时代码只能读不能写但USB可写方便我们更新程序。为False时代码可读写USB则变为只读。我们将引脚电平switch.value直接赋值给它实现了硬件控制逻辑。重要警告写完boot.py并保存后你必须先弹出EjectCIRCUITPYU盘再物理按下板子上的复位按钮boot.py才会在新的一次完整上电启动流程中执行。仅在REPL中按CtrlD软复位是无效的。4.2 主程序code.py温度记录与状态指示这是项目的主循环负责持续读取温度并写入文件同时通过LED提供状态反馈。# SPDX-FileCopyrightText: 2017 Limor Fried for Adafruit Industries # SPDX-License-Identifier: MIT import time import board import digitalio import microcontroller # 1. 初始化状态指示灯LED # 大部分板子的板载LED连接在D13引脚 led digitalio.DigitalInOut(board.D13) led.switch_to_output() try: # 2. 以追加模式打开日志文件 with open(/temperature_log.txt, a) as log_file: while True: # 3. 读取CPU温度单位摄氏度 temp_c microcontroller.cpu.temperature # 可选转换为华氏度 # temp_f (temp_c * 9 / 5) 32 # log_file.write(‘{:.2f}\n’.format(temp_f)) # 4. 格式化并写入数据 # 使用 {0:f} 确保写入的是浮点数格式避免科学计数法 log_file.write(‘{0:f}\n’.format(temp_c)) # 立即刷新缓冲区确保数据写入物理存储避免断电丢失 log_file.flush() # 5. 翻转LED状态指示一次写入完成 led.value not led.value # 6. 设置采样间隔单位秒 time.sleep(1) except OSError as e: # 7. 异常处理处理文件写入失败的情况 blink_delay 0.5 # 默认错误闪烁频率1Hz (亮0.5s, 灭0.5s) # 错误码 28: 设备空间不足 if e.args[0] 28: blink_delay 0.25 # 空间不足时快速闪烁2Hz # 在实际项目中这里可以尝试删除旧文件或停止记录 # 错误码 30: 文件系统为只读可能boot.py未正确设置或D0未接地 # elif e.args[0] 30: # blink_delay 1.0 # 只读错误慢闪0.5Hz # # 可以添加更明确的错误指示如特定颜色RGB灯 # 进入错误指示循环 while True: led.value not led.value time.sleep(blink_delay)代码深度解析与避坑指南文件打开模式使用“a“(append) 模式而非“w“(write)。“w“模式每次打开都会清空文件原有内容只适合单次运行。而“a“模式会在文件末尾追加数据非常适合长期日志记录即使设备断电重启新的数据也会接在旧数据之后。flush()的重要性在嵌入式系统中为了延长Flash寿命和提升性能写入操作经常先缓存在内存中。log_file.flush()方法强制将缓冲区数据立即写入物理存储。如果不调用flush()在突然断电的情况下最近几秒的数据可能会丢失。对于关键数据记录这是一个必要的安全措施。错误处理的艺术try-except块是生产级代码的必备。我们主要捕获OSError。除了教程提到的错误码28空间不足错误码30同样关键它表示“只读文件系统错误”。如果你的程序一运行就进入错误闪烁且闪烁频率是默认的1Hz而非快速的2Hz很大概率就是错误码30即boot.py的挂载模式没有切换成功代码没有写入权限。此时应检查boot.py文件是否存在且语法正确。是否已通过“弹出U盘 - 物理复位”的流程重启。硬件上D0引脚是否已可靠接地。采样率与功耗权衡time.sleep(1)表示每秒记录一次。对于温度这种变化相对缓慢的量这个频率通常足够。如果你想降低功耗可以增大休眠间隔比如time.sleep(10)每10秒一次。但要注意过于频繁的写操作如sleep(0.1)会加速Flash磨损且温度读数本身也有一定的响应时间过高频率无意义。5. 系统部署、数据获取与可视化5.1 完整工作流部署硬件连接用导线将板子的D0或你指定的引脚与GND短接。文件部署在电脑上打开CIRCUITPY盘。首先创建或编辑boot.py写入4.1节的代码。然后创建code.py写入4.2节的代码。启动记录安全弹出CIRCUITPYU盘然后按下板子上的物理复位按钮。此时板载LED应开始以1秒为周期稳定闪烁表明程序正在正常运行并记录数据。停止与数据读取当需要停止记录并读取数据时首先断开D0与GND的短接线然后再次物理复位板子。这次启动由于boot.py检测到D0为高电平文件系统会以“USB可写”模式挂载。此时将板子连接电脑打开CIRCUITPY盘就能直接看到并打开temperature_log.txt文件里面是按行存储的温度值。5.2 数据处理与简单可视化获取到的temperature_log.txt是纯文本文件每一行一个温度值摄氏度。你可以用任何文本编辑器或脚本语言处理。使用Python进行简单分析import matplotlib.pyplot as plt # 读取数据 with open(‘temperature_log.txt‘, ‘r‘) as f: # 过滤空行并转换为浮点数列表 data [float(line.strip()) for line in f if line.strip()] # 基本统计 print(f“数据点数: {len(data)}“) print(f“平均温度: {sum(data)/len(data):.2f} °C“) print(f“最高温度: {max(data):.2f} °C“) print(f“最低温度: {min(data):.2f} °C“) # 绘制趋势图 plt.figure(figsize(10, 5)) plt.plot(data) plt.title(‘CPU Temperature Log‘) plt.xlabel(‘Sample Number‘) plt.ylabel(‘Temperature (°C)‘) plt.grid(True) plt.tight_layout() plt.show()这段脚本能帮你快速计算温度的平均值、极值并绘制出温度随时间采样序列变化的曲线图非常直观。5.3 项目扩展思路基础功能实现后你可以从多个维度扩展这个项目多传感器融合结合板载或外接的光照、湿度传感器如I2C接口的BME280在日志中同时记录多条数据线用逗号分隔形成CSV格式。时间戳记录CircuitPython的time模块可以获取自上次启动以来的相对时间time.monotonic()。虽然不能提供真实世界时间但可以记录采样间隔。如果需要绝对时间可以考虑外接一个便宜的RTC实时时钟模块。条件触发记录修改循环逻辑仅在温度超过某个阈值如temp_c 60时才进行记录和LED报警实现简单的过热保护监测。低功耗优化对于电池供电场景可以将主循环中的time.sleep()替换为microcontroller.cpu.sleep()等更深度的休眠指令并在休眠期间完全关闭外设仅依靠内部定时器唤醒大幅降低待机功耗。数据导出自动化编写一个电脑端的Python脚本当设备以“USB可写”模式连接时自动将temperature_log.txt文件复制到电脑指定位置并清空板子上的旧文件实现半自动化的数据收集。这个项目麻雀虽小五脏俱全涵盖了嵌入式开发中传感器数据采集、文件I/O操作、硬件交互、异常处理等多个核心环节。通过动手实践你能深刻理解软硬件协同的工作原理为后续更复杂的物联网应用打下坚实的基础。
利用CircuitPython内置传感器实现CPU温度监控与本地日志记录
1. 项目概述从芯片温度到数据洞察在嵌入式项目里给设备“把脉”是基本功。CPU温度这个看似简单的数据点其实是窥探硬件运行状态的绝佳窗口。它不仅能告诉你芯片是不是在“发烧”更能间接反映环境变化、负载情况甚至是散热设计的有效性。以前做这类监控往往得外挂一个温度传感器再折腾ADC采样和校准流程繁琐。直到我发现很多现代微控制器比如Adafruit常用的SAMD21系列其CPU内部就集成了温度传感器并且CircuitPython已经把它做成了一个开箱即用的属性。这个项目的核心就是绕开复杂的硬件电路直接利用microcontroller.cpu.temperature这个“内置仪表”把读取到的温度数据以文本日志的形式实时记录到开发板自带的闪存文件系统中。整个过程你只需要几行Python代码无需焊接无需额外的元器件真正体现了CircuitPython“快速原型”的理念。它非常适合用于长期部署的设备健康监测、环境温度趋势分析需注意CPU温度与环境温度的差异和滞后性或是作为学习嵌入式数据采集与文件IO的入门实践。2. 核心思路与方案选型解析2.1 为什么选择CircuitPython与内置传感器这个方案的核心优势在于“极简”。传统MCU开发无论是用Arduino C还是裸机C读取内部温度传感器都需要直接操作芯片的寄存器涉及复杂的模数转换、校准系数计算对新手极不友好。CircuitPython的microcontroller模块将这些底层细节全部封装提供了一个直接的.temperature属性返回的就是摄氏度浮点数极大地降低了技术门槛。选择文件系统记录而非无线传输或外接SD卡是基于场景的权衡。对于很多低功耗、离线或原型验证阶段的项目首先需要的是可靠、简单的数据落地方案。开发板内置的闪存通常有几MB虽然空间有限但记录温度这类小数据绰绰有余。直接写入文件系统数据立即可通过USB在电脑上查看流程闭环调试方便。这个方案奠定了数据流的基础感知CPU温度 - 处理可选单位转换 - 存储本地文件。2.2 权限管理一个关键的设计挑战这里遇到一个嵌入式系统里经典的矛盾开发便利性与运行时安全性的冲突。CircuitPython设备连接电脑后其内部存储会作为一个U盘USB Mass Storage挂载方便我们直接拖拽修改code.py等文件。但如果在程序运行code.py时也允许Python代码向同一个文件系统写入数据就会产生访问冲突可能导致数据损坏。因此CircuitPython默认将文件系统设置为“只读”模式供代码访问以保证USB侧可写。我们的日志程序需要写文件就必须改变这个默认行为。这就是boot.py和storage模块出场的原因。boot.py在系统启动、USB连接建立之前执行在这里我们可以用storage.remount(“/”, False)将根目录重新挂载为可写。但这样一来USB侧就失去了写入权限你无法再通过电脑直接编辑代码了。为了解决这个两难问题原教程给出了一个巧妙的硬件交互方案通过一个物理开关或跳线来动态决定启动时的挂载模式。具体来说在boot.py中检测某个GPIO引脚如D0的电平。如果该引脚被接地拉低则启动为“代码可写”模式用于数据记录如果该引脚悬空或拉高则保持默认的“USB可写”模式方便代码更新。这种设计将控制权交给了硬件状态非常符合嵌入式开发“硬软结合”的思维。3. 硬件准备与软件环境搭建3.1 硬件选型与连接本项目对硬件要求极低。核心是一块支持CircuitPython且CPU内置温度传感器的开发板。Adafruit Gemma M0、Trinket M0、Feather M0系列以及功能更丰富的Circuit Playground Express、Metro M4等只要是基于SAMD21Cortex-M0或SAMD51Cortex-M4F等系列芯片的板子通常都支持。购买前最好查阅官方文档确认microcontroller.cpu.temperature属性可用。对于实现“选择性挂载”功能你需要准备一个物理开关或一根跳线。以Gemma M0为例找一根杜邦线或直接用金属镊子/导线。将开发板的D0引脚或你代码中定义的其他引脚与GND地引脚短接。 这个短接动作就是在告诉boot.py“这次启动请允许我的代码写入文件系统”。当你需要更新代码时断开这个短接即可。注意Circuit Playground Express板载了一个滑动开关其电路已经连接到了D7引脚。因此对于CPX你无需额外飞线直接使用这个开关即可在代码中将检测的引脚改为board.D7。3.2 CircuitPython固件更新与库确认确保你的开发板运行的是CircuitPython 2.0.0或更高版本因为storage模块和microcontroller.cpu.temperature属性是从该版本引入的。更新固件是第一步访问CircuitPython官网找到你的板型对应的最新.uf2固件文件。将板子通过USB连接电脑并快速双击复位按钮使其进入BOOTLOADER模式此时电脑会出现一个名为CPLAYBOOT、FEATHERBOOT等的U盘。将下载的.uf2文件拖入该U盘。盘符会自动弹出稍等片刻板子重启后就会出现一个新的名为CIRCUITPY的U盘这表明CircuitPython固件已刷写成功。固件本身已包含microcontroller、storage、board、digitalio等核心模块无需额外安装库文件这为我们省去了很多依赖管理的麻烦。4. 核心代码实现与分步详解4.1 创建动态挂载控制的boot.py这个文件是系统启动的钥匙它只执行一次。我们将实现通过硬件引脚状态决定文件系统权限的逻辑。# SPDX-FileCopyrightText: 2017 Limor Fried for Adafruit Industries # SPDX-License-Identifier: MIT import board import digitalio import storage # 1. 初始化硬件开关引脚 # 这里以D0为例如果你用CPX的滑动开关请改为 board.D7 switch_pin board.D0 switch digitalio.DigitalInOut(switch_pin) # 2. 配置引脚为输入模式并启用内部上拉电阻 switch.direction digitalio.Direction.INPUT switch.pull digitalio.Pull.UP # 默认内部上拉到高电平 # 3. 根据引脚电平决定挂载模式 # switch.value 在引脚被拉低接地时为 False悬空/拉高时为 True # 我们需要在引脚接地False时让代码可写readonlyFalse storage.remount(/, readonlyswitch.value)代码解读与实操要点digitalio.Pull.UP启用内部上拉电阻至关重要。它确保在引脚悬空时其电平能被稳定地拉至高电平逻辑1或True避免因静电干扰产生误判。只有当用导线明确将引脚与GND连接时电平才会被拉低至False。storage.remount(“/“, readonlyswitch.value)这是权限切换的核心。readonly参数为True时代码只能读不能写但USB可写方便我们更新程序。为False时代码可读写USB则变为只读。我们将引脚电平switch.value直接赋值给它实现了硬件控制逻辑。重要警告写完boot.py并保存后你必须先弹出EjectCIRCUITPYU盘再物理按下板子上的复位按钮boot.py才会在新的一次完整上电启动流程中执行。仅在REPL中按CtrlD软复位是无效的。4.2 主程序code.py温度记录与状态指示这是项目的主循环负责持续读取温度并写入文件同时通过LED提供状态反馈。# SPDX-FileCopyrightText: 2017 Limor Fried for Adafruit Industries # SPDX-License-Identifier: MIT import time import board import digitalio import microcontroller # 1. 初始化状态指示灯LED # 大部分板子的板载LED连接在D13引脚 led digitalio.DigitalInOut(board.D13) led.switch_to_output() try: # 2. 以追加模式打开日志文件 with open(/temperature_log.txt, a) as log_file: while True: # 3. 读取CPU温度单位摄氏度 temp_c microcontroller.cpu.temperature # 可选转换为华氏度 # temp_f (temp_c * 9 / 5) 32 # log_file.write(‘{:.2f}\n’.format(temp_f)) # 4. 格式化并写入数据 # 使用 {0:f} 确保写入的是浮点数格式避免科学计数法 log_file.write(‘{0:f}\n’.format(temp_c)) # 立即刷新缓冲区确保数据写入物理存储避免断电丢失 log_file.flush() # 5. 翻转LED状态指示一次写入完成 led.value not led.value # 6. 设置采样间隔单位秒 time.sleep(1) except OSError as e: # 7. 异常处理处理文件写入失败的情况 blink_delay 0.5 # 默认错误闪烁频率1Hz (亮0.5s, 灭0.5s) # 错误码 28: 设备空间不足 if e.args[0] 28: blink_delay 0.25 # 空间不足时快速闪烁2Hz # 在实际项目中这里可以尝试删除旧文件或停止记录 # 错误码 30: 文件系统为只读可能boot.py未正确设置或D0未接地 # elif e.args[0] 30: # blink_delay 1.0 # 只读错误慢闪0.5Hz # # 可以添加更明确的错误指示如特定颜色RGB灯 # 进入错误指示循环 while True: led.value not led.value time.sleep(blink_delay)代码深度解析与避坑指南文件打开模式使用“a“(append) 模式而非“w“(write)。“w“模式每次打开都会清空文件原有内容只适合单次运行。而“a“模式会在文件末尾追加数据非常适合长期日志记录即使设备断电重启新的数据也会接在旧数据之后。flush()的重要性在嵌入式系统中为了延长Flash寿命和提升性能写入操作经常先缓存在内存中。log_file.flush()方法强制将缓冲区数据立即写入物理存储。如果不调用flush()在突然断电的情况下最近几秒的数据可能会丢失。对于关键数据记录这是一个必要的安全措施。错误处理的艺术try-except块是生产级代码的必备。我们主要捕获OSError。除了教程提到的错误码28空间不足错误码30同样关键它表示“只读文件系统错误”。如果你的程序一运行就进入错误闪烁且闪烁频率是默认的1Hz而非快速的2Hz很大概率就是错误码30即boot.py的挂载模式没有切换成功代码没有写入权限。此时应检查boot.py文件是否存在且语法正确。是否已通过“弹出U盘 - 物理复位”的流程重启。硬件上D0引脚是否已可靠接地。采样率与功耗权衡time.sleep(1)表示每秒记录一次。对于温度这种变化相对缓慢的量这个频率通常足够。如果你想降低功耗可以增大休眠间隔比如time.sleep(10)每10秒一次。但要注意过于频繁的写操作如sleep(0.1)会加速Flash磨损且温度读数本身也有一定的响应时间过高频率无意义。5. 系统部署、数据获取与可视化5.1 完整工作流部署硬件连接用导线将板子的D0或你指定的引脚与GND短接。文件部署在电脑上打开CIRCUITPY盘。首先创建或编辑boot.py写入4.1节的代码。然后创建code.py写入4.2节的代码。启动记录安全弹出CIRCUITPYU盘然后按下板子上的物理复位按钮。此时板载LED应开始以1秒为周期稳定闪烁表明程序正在正常运行并记录数据。停止与数据读取当需要停止记录并读取数据时首先断开D0与GND的短接线然后再次物理复位板子。这次启动由于boot.py检测到D0为高电平文件系统会以“USB可写”模式挂载。此时将板子连接电脑打开CIRCUITPY盘就能直接看到并打开temperature_log.txt文件里面是按行存储的温度值。5.2 数据处理与简单可视化获取到的temperature_log.txt是纯文本文件每一行一个温度值摄氏度。你可以用任何文本编辑器或脚本语言处理。使用Python进行简单分析import matplotlib.pyplot as plt # 读取数据 with open(‘temperature_log.txt‘, ‘r‘) as f: # 过滤空行并转换为浮点数列表 data [float(line.strip()) for line in f if line.strip()] # 基本统计 print(f“数据点数: {len(data)}“) print(f“平均温度: {sum(data)/len(data):.2f} °C“) print(f“最高温度: {max(data):.2f} °C“) print(f“最低温度: {min(data):.2f} °C“) # 绘制趋势图 plt.figure(figsize(10, 5)) plt.plot(data) plt.title(‘CPU Temperature Log‘) plt.xlabel(‘Sample Number‘) plt.ylabel(‘Temperature (°C)‘) plt.grid(True) plt.tight_layout() plt.show()这段脚本能帮你快速计算温度的平均值、极值并绘制出温度随时间采样序列变化的曲线图非常直观。5.3 项目扩展思路基础功能实现后你可以从多个维度扩展这个项目多传感器融合结合板载或外接的光照、湿度传感器如I2C接口的BME280在日志中同时记录多条数据线用逗号分隔形成CSV格式。时间戳记录CircuitPython的time模块可以获取自上次启动以来的相对时间time.monotonic()。虽然不能提供真实世界时间但可以记录采样间隔。如果需要绝对时间可以考虑外接一个便宜的RTC实时时钟模块。条件触发记录修改循环逻辑仅在温度超过某个阈值如temp_c 60时才进行记录和LED报警实现简单的过热保护监测。低功耗优化对于电池供电场景可以将主循环中的time.sleep()替换为microcontroller.cpu.sleep()等更深度的休眠指令并在休眠期间完全关闭外设仅依靠内部定时器唤醒大幅降低待机功耗。数据导出自动化编写一个电脑端的Python脚本当设备以“USB可写”模式连接时自动将temperature_log.txt文件复制到电脑指定位置并清空板子上的旧文件实现半自动化的数据收集。这个项目麻雀虽小五脏俱全涵盖了嵌入式开发中传感器数据采集、文件I/O操作、硬件交互、异常处理等多个核心环节。通过动手实践你能深刻理解软硬件协同的工作原理为后续更复杂的物联网应用打下坚实的基础。