我已经为这个问题痛苦了好几个星期,并且终于屈服于寻求帮助。
问题陈述:“add_event_detect”被触发并多次调用其自己的(AND其他)回调函数,即使绑定的GPIO引脚未变为高电平。就好像软件有自己的生命。当我按下LIGHT按钮时,TIMER和MOTOR事件被多次触发 - 我无法理解为什么。
我试过了:
只有在回调中添加计时器条件才能阻止回调多次运行,但这并不能解决问题的路由原因。我需要在第一时间停止执行回调。
电路看起来像这样。
重要的代码元素如下所示。 (我删除了相当多的不相关代码,可能很难追踪程序的全部流程,但关键元素就在那里。
aPins = [24]
pinLightOut = 23
pinMotorToggle = 20
pinLight = 16
pinTimer = 21
GPIO.setmode(GPIO.BCM)
# Set the relay pins to high (220v circuits are off)
GPIO.setup (aPins, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup (pinLightOut , GPIO.OUT, initial = GPIO.HIGH)
GPIO.setup (pinLight , GPIO.IN, pull_up_down = GPIO.PUD_OFF)
GPIO.setup (pinMotorToggle , GPIO.IN, pull_up_down = GPIO.PUD_OFF)
GPIO.setup (pinTimer , GPIO.IN, pull_up_down = GPIO.PUD_OFF)
outLEDPower = 26
outLEDSchedule = 19
outLEDBypass = 13
outLEDMotorOn = 6
outLEDLight = 5
aLED = [outLEDSchedule, outLEDMotorOn, outLEDBypass, outLEDLight, outLEDPower]
GPIO.setup (aLED, GPIO.OUT)
GPIO.output (aLED, GPIO.LOW)
GPIO.output(outLEDPower, GPIO.HIGH) # The power light is on by default
GPIO.output(outLEDSchedule, gTimerActive) # The timer is active at start up by default
# Setup the GPIO callbacks for an event detected.
GPIO.add_event_detect (pinTimer, GPIO.FALLING, callback=Timer_Switch, bouncetime= 1000)
GPIO.add_event_detect (pinMotorToggle, GPIO.FALLING, callback=Start_Switch, bouncetime = 1000)
GPIO.add_event_detect (pinLight, GPIO.FALLING, callback=Light_Switch, bouncetime = 1000)
def Start_Switch (c1):
global gStartSwitch, gTimerActive, gStartSwitchLED, LastThreadTime
# This condition is to make up for the bouncetime that does not appear to work.
if time.time() - LastThreadTime > 2:
# NB to reset this time variable otherwise more callbacks are initiated
LastThreadTime = time.time()
if not gTimerActive:
gStartSwitch = True
gStartSwitchLED = not gStartSwitchLED
GPIO.output (outLEDBypass, gStartSwitchLED)
else:
print "Cannot start motor while timer is running"
def Timer_Switch (c4):
global gTimerActive, gStopBecauseTimerToggle, LastThreadTime
if time.time() - LastThreadTime > 2:
LastThreadTime = time.time()
print "Timer Switch Pressed on channel : " + str(c4)
if gTimerActive == True:
GPIO.output (outLEDSchedule, GPIO.LOW)
gTimerActive = False
else:
GPIO.output (outLEDSchedule, GPIO.HIGH)
gTimerActive = True
gStopBecauseTimerToggle = True
def Light_Switch (c4):
global LastThreadTime, gLightActive
if time.time() - LastThreadTime > 2:
LastThreadTime = time.time()
print "Light Switch pressed on channel : " + str(c4)
if not gLightActive:
GPIO.output(pinLightOut, GPIO.LOW)
GPIO.output (outLEDLight, GPIO.HIGH)
gLightActive = True
else :
GPIO.output(pinLightOut, GPIO.HIGH)
GPIO.output (outLEDLight, GPIO.LOW)
gLightActive = False
def MotorActivate (vZone, vDuration):
global gTimerActive, gStartSwitch, gMotorActive, gZone, gTimeLeft, gStopMotor, gStopBecauseTimerToggle, gStartSwitchLED
if vZone <= len(aPins):
timeCount = 0
MotorTimeEnd = time.time() + vDuration
TimeNow = time.time()
vTimeLast = 0
gTimeLeft = str(vDuration)
gZone = str(vZone)
GPIO.output (aPins [vZone-1], GPIO.LOW)
GPIO.output (outLEDMotorOn, GPIO.HIGH)
gMotorActive = True
while time.time() <= MotorTimeEnd and not gStartSwitch and not gStopBecauseTimerToggle:
if time.time() - vTimeLast >= 1:
gTimeLeft = str(round(MotorTimeEnd - time.time(),0))
vTimeLast = time.time()
GPIO.output (aPins [vZone-1], GPIO.HIGH)
GPIO.output (outLEDMotorOn, GPIO.LOW)
GPIO.output (outLEDBypass, GPIO.LOW)
gStartSwitchLED = False
gMotorActive = False
#########################################################################################
# Main Body of program below
#########################################################################################
try:
while 1>0:
if gTimerActive and time.time() - vTimeStampTimer >= 3 : # Check timer every 3 seconds
MotorActivator = "Timer"
MotorZones = CheckPoolSchedule (aFloat) # Check to see if the current time is inside the timer window
if len(MotorZones) > 0 and not gStopMotor:
RunSchedule (MotorZones) # The RunSchedule is the function that calls the MotorActivate function
if gStartSwitch:
RunSchedule (aPoolList) # Run the schedule with a default time frame
if time.time() - vLI >= 5: # Check light timer every 5 seconds
if not gLightActive:
aLightZone = CheckPoolSchedule (aLight) # Check to see if time is in the timer schedule
if len(aLightZone) > 0:
Light_Switch (99)
if gLightActive and vLightOffTime <> -1:
if time.time() >= vLightOffTime:
Light_Switch (98)
finally:
print "Leaving programme"
GPIO.cleanup()
您所看到的任何其他内容或有关使我的代码更好的建议都将不胜感激。
提前谢谢