树莓派4使用Python spidev与MCP3008时出现Segmentation fault错误
解决Segmentation Fault及脚本启动问题
你的代码存在几个关键错误,这些是导致段错误和无法启动的核心原因,以下是逐一修正方案:
1. 修复SPI传输函数调用错误
spidev.SpiDev.xfer()的参数应为字节列表,而非三个独立整数。MCP3008的正确读取逻辑是发送包含3个字节的指令:
- 第一个字节:
1(起始位) - 第二个字节:
(8 + 通道号) << 4(通道选择,比如通道0对应128、通道3对应176) - 第三个字节:
0(填充位,用于接收数据)
错误写法:
answerV = spi.xfer(1,128,0) answerC = spi.xfer(1,176,0)
正确写法:
answerV = spi.xfer([1, 128, 0]) answerC = spi.xfer([1, 176, 0])
2. 修复函数缩进错误
get_voltage()中的return voltage_measurement缩进错误(位于函数外部),会触发语法错误,需缩进至函数内部:
修正后:
def get_voltage(): answerV = spi.xfer([1, 128, 0]) if 0 <= answerV[1] <= 3: voltage_measurement = ((((answerV[1] * 256) + answerV[2]) * 0.00322) * 90) // 40 print(voltage_measurement, " V") return voltage_measurement
3. 修复变量未定义问题
get_current()中,若第一个if条件不满足,current_measurement会未定义就返回,需提前初始化默认值:
def get_current(): current_measurement = 0 # 初始化默认值 answerC = spi.xfer([1, 176, 0]) if 0 <= answerC[1] <= 3: current_measurement = ((answerC[1] * 256) + answerC[2]) * 0.00322 * 0.066 print(current_measurement, " A") if ((answerC[1] * 256) + answerC[2]) * 0.00322 == 2: current_measurement = 0 return current_measurement
- 主循环中
p变量未定义,需先调用get_power()计算功率:
while True: tm = get_time() i = get_current() v = get_voltage() p = get_power(v, i) # 新增该行 writer.writerow([tm, v, i, p]) time.sleep(1)
4. 优化文件写入逻辑
直接open("data.csv", "w")可能导致数据缓冲无法及时写入,建议用with语句管理文件,确保正确打开/关闭,同时手动触发刷新:
# 替换原writer初始化及主循环代码 with open("data.csv", "w", newline='') as f: writer = csv.writer(f) writer.writerow(["time", "voltage", "current", "power"]) while True: tm = get_time() i = get_current() v = get_voltage() p = get_power(v, i) writer.writerow([tm, v, i, p]) f.flush() # 确保数据立即写入文件 time.sleep(1)
5. 调整SPI速度(可选)
MCP3008支持最高1MHz的SPI速度,原代码5000Hz过低,可调整为更合理的值:
spi.max_speed_hz = 100000 # 100kHz,兼顾稳定性和速度
完整修正后的代码
import spidev import time import csv import datetime as dt spi = spidev.SpiDev() spi.open(0, 1) spi.max_speed_hz = 100000 def get_time(): tm = dt.datetime.now().strftime("%d.%m.%Y-%H:%M") return tm def get_voltage(): voltage_measurement = 0 answerV = spi.xfer([1, 128, 0]) if 0 <= answerV[1] <= 3: voltage_measurement = ((((answerV[1] * 256) + answerV[2]) * 0.00322) * 90) // 40 print(voltage_measurement, " V") return voltage_measurement def get_current(): current_measurement = 0 answerC = spi.xfer([1, 176, 0]) if 0 <= answerC[1] <= 3: current_measurement = ((answerC[1] * 256) + answerC[2]) * 0.00322 * 0.066 print(current_measurement, " A") # 替换浮点数精确比较,改用范围判断避免精度问题 raw_voltage = ((answerC[1] * 256) + answerC[2]) * 0.00322 if abs(raw_voltage - 2) < 0.01: current_measurement = 0 return current_measurement def get_power(v, i): return v * i with open("data.csv", "w", newline='') as f: writer = csv.writer(f) writer.writerow(["time", "voltage", "current", "power"]) while True: tm = get_time() i = get_current() v = get_voltage() p = get_power(v, i) writer.writerow([tm, v, i, p]) f.flush() time.sleep(1)
注:原代码中浮点数==2的判断可能因精度问题失效,改用范围判断更可靠。
内容的提问来源于stack exchange,提问作者moknavi
相关产品推荐
相关产品推荐

