MicroPython环境下ESP32如何获取开机/程序启动后的运行时长
MicroPython ESP32运行时长统计方案
核心实现(无需额外依赖,优先使用)
不需要依赖datetime模块,也不用受Thonny同步主机时间的干扰,直接使用MicroPython内置utime模块的硬件滴答接口即可实现精准的开机运行时长统计,计数基准为芯片上电复位时刻,完全独立于RTC时间,不受Thonny同步时间操作影响。
注意不要使用utime.time()、utime.localtime()这类返回绝对RTC时间的接口,Thonny连接设备时会默认将电脑时间同步到ESP32的RTC域,这就是观察到时间元组来自电脑的原因。
在程序最起始位置加入以下代码,即可获取精度1毫秒的运行时长:
import utime # 程序启动第一时间记录初始滴答值,作为0秒基准 _start_ms = utime.ticks_ms() def get_uptime_seconds() -> float: """返回程序启动到当前的运行时长,单位:秒""" return utime.ticks_diff(utime.ticks_ms(), _start_ms) / 1000
关键说明:必须使用utime.ticks_diff()计算时间差,禁止直接对两个ticks值做算术减法。ticks_ms()为32位循环计数,约每49天溢出一次,ticks_diff()是官方内置的溢出安全差值计算接口,可保证任意时间点返回的时间差准确无误。
后续业务需求适配
针对屏幕显示、串口输出、日志存储需求,可直接用以下代码实现,不会阻塞ESPWebServer主逻辑:
时长格式转换
将秒数转换为通用的时:分:秒格式,适配屏幕显示和日志输出:
def format_uptime(total_sec: float) -> str: hours = int(total_sec // 3600) minutes = int((total_sec % 3600) // 60) seconds = int(total_sec % 60) return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
串口/屏幕输出
直接调用函数取值即可:
# 串口输出 print(f"设备运行时长:{format_uptime(get_uptime_seconds())}") # TFT屏幕显示直接把format_uptime的返回值传给屏幕文本绘制接口即可
每分钟写入本地日志
在主循环中加入非阻塞判断,避免用长延时影响Web服务运行:
last_log_min = -1 # 放入主循环 current_uptime = get_uptime_seconds() current_min = int(current_uptime // 60) if current_min != last_log_min: # 追加写入日志文件 with open("uptime_record.txt", "a", encoding="utf-8") as f: f.write(f"{format_uptime(current_uptime)}\n") last_log_min = current_min # 执行原有WebServer逻辑,加短延时避免占用过高 utime.sleep_ms(10)
本地可用的轻量udatetime模块
如果需要兼容datetime类的调用接口,可将以下代码保存为udatetime.py上传到ESP32本地文件系统,直接import即可使用,无需固件内置datetime支持,文件体积不到1KB:
# udatetime.py import utime _start_tick = utime.ticks_ms() class datetime: @staticmethod def now() -> tuple: """返回当前RTC时间元组 (年,月,日,时,分,秒)""" year, month, day, hour, minute, second, *_ = utime.localtime() return (year, month, day, hour, minute, second) @staticmethod def uptime() -> float: """返回程序启动后的运行时长,单位:秒""" return utime.ticks_diff(utime.ticks_ms(), _start_tick) / 1000
调用示例:
import udatetime print(udatetime.datetime.uptime())
其他问题说明
- 遇到的help函数异常是所用2022-02-12 dirty版本固件的已知bug,仅
help('modules')可用不影响业务逻辑运行,如需正常使用help可升级到v1.19及以上正式版MicroPython固件。 - 板载电池电压读取无需移植官方Arduino封装,T-Display的电池分压接在GPIO34引脚,可直接通过ADC读取换算:
锂电池正常电压区间为3.0V(欠压)~4.2V(满电),可根据实际测试的电压对应电量设置关机阈值。from machine import ADC bat_adc = ADC(34) bat_adc.atten(ADC.ATTN_11DB) def get_bat_voltage() -> float: return bat_adc.read_uv() / 1000000 * 2 # 分压比为1/2,乘以2得到实际电压
内容的提问来源于stack exchange,提问作者James V. Fields
相关产品推荐
相关产品推荐

