树莓派项目Matplotlib动态绘图更新异常问题求助
解决树莓派Matplotlib实时动态绘图问题
嘿,我一看你的代码就知道问题出在哪了——你每次循环都调用plt.show(),这玩意儿会阻塞程序,非得等你关掉窗口才会继续跑下一次循环,而且每次plt.plot()都会在图上叠加新的线条,根本不是实时更新的效果。咱们改改就能实现终端打数据、窗口实时更图的需求,看下面的方案:
关键修改点
- 开启Matplotlib的交互式模式(
plt.ion()),让绘图窗口保持打开且不阻塞程序运行 - 提前初始化画布、坐标轴和需要绘制的线条,循环里只更新数据而不是重新绘图
- 用
canvas.draw()/canvas.flush_events()来刷新画面,替代重复调用plt.show()
修改后的完整代码
import matplotlib.pyplot as plt from time import sleep from Adafruit_CCS811 import Adafruit_CCS811 # 初始化传感器 ccs = Adafruit_CCS811() while not ccs.available(): pass temp = (ccs.calculateTemperature() / 3.2) - 32.0 ccs.tempOffset = temp - 25.0 # 开启Matplotlib交互式模式 plt.ion() # 创建画布和坐标轴 fig, ax = plt.subplots(figsize=(8, 5)) # 初始化三条数据线条,先给空数据,后续更新 co2_line, = ax.plot([], [], label='CO2 (ppm)') tvoc_line, = ax.plot([], [], label='TVOC') temp_line, = ax.plot([], [], label='Temperature (°C)') # 设置绘图样式 ax.set_title('Real-time Sensor Data') ax.set_xlabel('Time (s)') ax.set_ylabel('Value') ax.legend() ax.grid(True) # 初始化时间序列和数据存储列表 time_points = [] co2_data = [] tvoc_data = [] temp_data = [] current_time = 0 try: while True: if ccs.available(): temp = ccs.calculateTemperature() if not ccs.readData(): # 获取当前传感器数据 co2 = ccs.geteCO2() tvoc = ccs.getTVOC() # 打印到终端 print(f"CO2: {co2} ppm, TVOC: {tvoc}, temp: {temp:.1f}") # 更新数据列表 time_points.append(current_time) co2_data.append(co2) tvoc_data.append(tvoc) temp_data.append(temp) # 更新三条线条的数据 co2_line.set_data(time_points, co2_data) tvoc_line.set_data(time_points, tvoc_data) temp_line.set_data(time_points, temp_data) # 自动调整坐标轴范围,避免数据超出视野 ax.relim() ax.autoscale_view() # 刷新画布 fig.canvas.draw() fig.canvas.flush_events() # 时间递增(每2秒一次循环,所以加2) current_time += 2 else: print("ERROR!") break sleep(2) except KeyboardInterrupt: # 捕获Ctrl+C,关闭绘图窗口 plt.close('all') print("程序已终止")
代码解释
- 交互式模式:
plt.ion()让Matplotlib进入交互模式,窗口打开后不会阻塞后续代码执行,这是实时绘图的核心。 - 复用线条对象:一开始就创建
co2_line、tvoc_line这些线条对象,循环里只调用set_data()更新它们的数据源,而不是每次都用plt.plot()画新线,这样不会产生线条叠加的问题。 - 画布刷新:
fig.canvas.draw()重绘画布,fig.canvas.flush_events()处理窗口的事件(比如鼠标操作),确保画面实时更新。 - 异常处理:加上
KeyboardInterrupt捕获,方便你用Ctrl+C终止程序时能正常关闭绘图窗口。
这样改完之后,你运行代码就能看到一个持续更新的绘图窗口,同时终端也会实时打印传感器数据,不用再关窗口才能更新啦!
内容的提问来源于stack exchange,提问作者Fakiye Oladipupo
相关产品推荐
相关产品推荐

