使用Python Turtle显示盖革计数器剂量值时遇类型错误求助
解决
TypeError: unsupported operand type(s) for /: 'NoneType' and 'int'问题 这个错误的核心原因很直白:你的read_sev()函数没有返回任何值,当你执行sev=read_sev()时,sev被默认赋值为None——这是Python中函数没有return语句时的默认返回值。之后在draw_gauge里尝试用None和整数40做除法,自然会触发类型错误。
修复步骤
1. 给read_sev()添加返回语句
修改这个函数,让它返回处理后的希沃特数值,同时增加异常处理避免串口数据异常导致程序崩溃:
def read_sev(): try: sev = ser.readline() # 优化数据处理:先解码再去除多余字符,避免硬编码截取长度 sev_clean = sev.decode("utf-8").strip() # 转换为浮点型 sev_value = float(sev_clean) return sev_value except (UnicodeDecodeError, ValueError, serial.SerialException) as e: # 处理可能的异常:比如串口数据乱码、无法转成浮点数、串口断开 print(f"读取数据出错: {e}") ser.flushInput() # 清空串口缓存里的无效数据 return 0.0 # 返回一个默认值,保证程序能继续运行
2. 额外优化:修复表盘刻度的逻辑问题
你当前的刻度绘制代码有个小bug:循环40次每次右转50度,总共会转2000度,这会导致刻度重叠混乱。如果你的最大量程是40 Sv,那么360度对应40 Sv,每个刻度应该间隔9度(360/40),修改刻度绘制部分:
pen.penup() pen.goto(0,0) pen.setheading(90) for _ in range(40): pen.fd(190) pen.pendown() pen.fd(20) pen.penup() pen.goto(0,0) pen.rt(9) # 替换原来的50度,每个刻度间隔9度
完整修改后的代码
#!/usr/bin/python3 import turtle import serial import time wn = turtle.Screen() wn.bgcolor("black") wn.setup(width=600, height=600) wn.title("Geiger Counter") wn.tracer(0) # 初始化串口,明确指定波特率(和Arduino程序设置一致,比如9600) ser = serial.Serial('/dev/ttyACM1', 9600) ser.flushInput() # 读取希沃特值的函数,添加返回和异常处理 def read_sev(): try: sev = ser.readline() sev_clean = sev.decode("utf-8").strip() sev_value = float(sev_clean) return sev_value except (UnicodeDecodeError, ValueError, serial.SerialException) as e: print(f"读取数据出错: {e}") ser.flushInput() return 0.0 # 初始化绘图笔 pen = turtle.Turtle() pen.hideturtle() pen.speed(0) pen.pensize(3) # 绘制表盘和指针 def draw_gauge(sev, pen): # 绘制外圈 pen.up() pen.goto(0,210) pen.setheading(180) pen.color("green") pen.pendown() pen.circle(210) # 绘制刻度(修复角度间隔) pen.penup() pen.goto(0,0) pen.setheading(90) for _ in range(40): pen.fd(190) pen.pendown() pen.fd(20) pen.penup() pen.goto(0,0) pen.rt(9) # 绘制指针 pen.penup() pen.goto(0,0) pen.color("white") pen.setheading(90) # 限制数值在0-40之间,避免指针超出表盘 clamped_sev = max(0.0, min(sev, 40.0)) angle = (clamped_sev / 40) * 360 pen.rt(angle) pen.pendown() pen.fd(200) while True: sev = read_sev() draw_gauge(sev, pen) wn.update() time.sleep(1) pen.clear() wn.mainloop()
额外说明
- 串口初始化时必须指定波特率,要和Arduino程序里的设置完全一致,否则会出现数据乱码。
- 新增的异常处理是为了避免偶尔的串口数据异常导致程序直接崩溃,提升运行稳定性。
clamped_sev的作用是防止读取到超过40 Sv的数值时,指针转出表盘范围。
内容的提问来源于stack exchange,提问作者Renato Gallo
相关产品推荐
相关产品推荐

