如何精准记录传感器的进入与离开触发点?现有代码重复生成记录对的问题求助
如何精准记录传感器的进入与离开触发点?现有代码重复生成记录对的问题求助
嘿,我看了你的问题和代码,立刻就明白你遇到的麻烦了——你的外层大while循环一直在高频迭代,每次循环都会重新检查传感器状态,但原逻辑没做状态跟踪,导致传感器持续触发时,每一次外层循环都会重复写入“进入”记录;紧接着内部循环可能因为传感器瞬间波动或者循环执行太快,又写入“离开”记录,结果就生成了一堆重复的记录对。
问题根源拆解
你原来的逻辑存在两个核心问题:
- 重复触发记录:只要传感器保持触发状态(输出0),外层循环每跑一次就会触发进入记录,退出内部循环后又立刻回到外层检测到0,重复整个流程,导致大量重复的进入/离开日志。
- 传感器阻塞:当代码卡在某个传感器的内部while循环时,另一个传感器的状态变化完全无法被检测到,会错过关键记录。
解决方案:添加状态跟踪标记
核心思路是只在传感器状态发生切换时记录日志,我们给每个传感器加一个状态标记,记录它当前是“已触发”还是“未触发”:
- 当状态从「未触发」→「触发」时,写入进入日志
- 当状态从「触发」→「未触发」时,写入离开日志
修改后的代码示例
首先在循环外初始化状态标记:
# 初始化传感器状态:False=未触发,True=正在触发中 centre_port_active = False reward_port_active = False
然后替换原来的外层循环逻辑:
while time.time() - timeBefore < trialDuration - rewardSize: # trialDuration-rewardSize = 20-1 = 19 seconds; time.time()-timeBefore = elapsed time since reward delivery print('in outer loop') # 先读取当前两个传感器的状态 centre_sensor_state = GPIO.input(sensorPins[2]) reward_sensor_state = GPIO.input(sensorPins[0]) # 处理中心传感器(记录2=进入,20=离开) if centre_sensor_state == 0: if not centre_port_active: # 状态切换为触发,记录进入 print('detected centre') centrePortFlag = True writer.writerow([trialNum, 2, time.time() - startTime]) centre_port_active = True else: if centre_port_active: # 状态切换为未触发,记录离开 print('centre left') writer.writerow([trialNum, 20, time.time() - startTime]) centre_port_active = False # 处理奖励端口传感器(记录0=进入,10=离开) if reward_sensor_state == 0: if not reward_port_active: # 状态切换为触发,记录进入 print('detected reward') rewardPortFlag = True writer.writerow([trialNum, 0, time.time() - startTime]) reward_port_active = True else: if reward_port_active: # 状态切换为未触发,记录离开 print('reward left') writer.writerow([trialNum, 10, time.time() - startTime]) reward_port_active = False
为什么这个修改有效?
- 状态标记确保只有状态发生变化时才写入日志,不会因为循环反复检测同一状态而重复记录。
- 去掉了阻塞式的内部while循环,现在两个传感器的状态都能被实时检测,不会出现一个传感器阻塞另一个的情况。
额外优化:传感器防抖(可选)
如果你的传感器存在抖动(比如瞬间输出1又回到0),可以加一个防抖函数,通过多次采样取稳定状态避免误触发:
import time def get_stable_sensor_state(pin, sample_count=3, sample_delay=0.001): # 多次读取传感器状态,取出现次数多的结果 states = [] for _ in range(sample_count): states.append(GPIO.input(pin)) time.sleep(sample_delay) return 0 if states.count(0) > states.count(1) else 1 # 使用时替换原GPIO.input调用 centre_sensor_state = get_stable_sensor_state(sensorPins[2]) reward_sensor_state = get_stable_sensor_state(sensorPins[0])
备注:内容来源于stack exchange,提问作者432111
相关产品推荐
相关产品推荐

