树莓派Pico实现LCD显示传感器数据及SD卡记录功能求助
问题分析与解决建议
1. 修复SD卡功能缺失问题
原代码仅导入SD卡相关库,但未完成初始化与挂载,这是无法记录数据的核心原因。需添加SD卡初始化逻辑,同时优化SPI参数提升稳定性:
# 初始化SD卡 sd = sdcard.SDCard(spi, CS) # 挂载SD卡文件系统 vfs = uos.VfsFat(sd) uos.mount(vfs, "/sd")
建议将SPI波特率调整为10000000(10MHz),避免低速导致的读写超时;同时确认硬件接线:CS、SCK、MOSI、MISO引脚与SD卡模块对应无误。
2. 修复LCD显示错误
- 参数传递错误:
lcd.putstr()仅接受字符串参数,原代码直接传入多个变量会报错,需将数据格式化为字符串:lcd_str = f"{n:4d} {motion:d} {voltage:.2f} {temperature:.1f} {RoomLit:d}" lcd.putstr(lcd_str) - clear方法误用:
lcd.clear(0,1)不是正确调用方式,若仅需刷新第二行,可移动光标到行首后用空格覆盖原有内容;若需清屏,直接调用lcd.clear()后重新写入标题行。 - 变量名拼写错误:
n=n+timeinterval中的timeinterval应为timeintervals,否则会抛出未定义错误。
3. 修复传感器数据覆盖问题
原代码中MQ2传感器的voltage变量被温度传感器的voltage覆盖,导致MQ2数据丢失,需重命名变量区分:
# MQ2电压读取 mq2 = machine.ADC(26) conversion_factor = 3.3 / 65535 mq2_voltage = mq2.read_u16() * conversion_factor # 温度传感器读取 sensor = machine.ADC(4) reading = sensor.read_u16() temp_voltage = reading * conversion_factor temperature = 27 - (temp_voltage - 0.706) / 0.001721 temperature = temperature * 1.8 + 32
4. 实现SD卡数据记录功能
每次采集数据后,以追加模式写入SD卡日志文件,为避免断电丢失数据,需调用flush()立即写入:
# 初始化时打开日志文件 log_file = open("/sd/sensor_log.txt", "a") # 首次运行写入表头 log_file.seek(0, 2) if log_file.tell() == 0: log_file.write("time(s),motion,mq2_voltage,temperature,light\n") log_file.flush() # 循环内写入数据 log_line = f"{n},{motion},{mq2_voltage:.2f},{temperature:.1f},{RoomLit}\n" log_file.write(log_line) log_file.flush()
5. 长期运行稳定性优化
- 添加异常捕获:针对SD卡读写、LCD通信异常做捕获处理,避免程序崩溃:
try: # 数据采集、显示、写入逻辑 except OSError as e: print(f"SD卡错误: {e}") lcd.clear() lcd.putstr("SD Card Error!") sleep(2) - 使用硬件I2C:若引脚允许,替换SoftI2C为硬件I2C(
machine.I2C(0, sda=Pin(0), scl=Pin(1))),提升LCD通信稳定性。 - 降低LCD刷新负载:无需每次循环清屏,仅刷新数据行即可。
完整修正示例代码
from machine import Pin, SoftI2C, ADC, SPI import utime from pico_i2c_lcd import I2cLcd import sdcard import uos from time import sleep # LCD初始化 I2C_ADDR = 0x27 I2C_NUM_ROWS = 2 I2C_NUM_COLS = 20 i2c = SoftI2C(sda=Pin(4), scl=Pin(5), freq=400000) lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS) # SD卡初始化 CS = Pin(9, Pin.OUT) spi = SPI(1, baudrate=10000000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(10), mosi=Pin(11), miso=Pin(8)) sd = sdcard.SDCard(spi, CS) vfs = uos.VfsFat(sd) uos.mount(vfs, "/sd") # 传感器初始化 pir_sensor = Pin(28, Pin.IN) mq2 = ADC(26) temp_sensor = ADC(4) ldr = ADC(27) conversion_factor = 3.3 / 65535 # 日志文件初始化 log_file = None try: log_file = open("/sd/sensor_log.txt", "a") log_file.seek(0, 2) if log_file.tell() == 0: log_file.write("time(s),motion,mq2_voltage,temperature,light\n") log_file.flush() except OSError as e: print(f"SD卡初始化失败: {e}") # 初始化变量与LCD标题 n = 0 time_intervals = 3 lcd.clear() lcd.putstr("time motion mq2 temp light") while True: try: # 读取传感器数据 motion = 1 if pir_sensor.value() == 1 else 0 mq2_voltage = mq2.read_u16() * conversion_factor temp_reading = temp_sensor.read_u16() temp_voltage = temp_reading * conversion_factor temperature = 27 - (temp_voltage - 0.706) / 0.001721 temperature = temperature * 1.8 + 32 ldr_value = ldr.read_u16() room_lit = 1 if ldr_value < 20000 else 0 # 串口打印 print(f"{n:4d} {motion:d} {mq2_voltage:.2f} {temperature:.1f} {room_lit:d}") # LCD刷新第二行 lcd.move_to(0, 1) lcd_str = f"{n:4d} {motion:d} {mq2_voltage:.2f} {temperature:.1f} {room_lit:d}" lcd.putstr(lcd_str.ljust(I2C_NUM_COLS)) # SD卡写入 if log_file: log_line = f"{n},{motion},{mq2_voltage:.2f},{temperature:.1f},{room_lit}\n" log_file.write(log_line) log_file.flush() n += time_intervals sleep(time_intervals) except OSError as e: print(f"SD卡错误: {e}") lcd.clear() lcd.putstr("SD Card Error!") sleep(2) lcd.clear() lcd.putstr("time motion mq2 temp light") except Exception as e: print(f"系统错误: {e}") sleep(1)
内容的提问来源于stack exchange,提问作者Tyler Fleming
相关产品推荐
相关产品推荐

