Функция обратного вызова add_event_detect запущена без повышения GPIO
Я мучился с этой проблемой в течение нескольких недель и, наконец, поддался просьбе о помощи.
ПОСТАНОВКА ЗАДАЧИ: add_event_detect запускается и вызывает свои собственные (и другие) функции обратного вызова несколько раз, даже если связанный вывод GPIO не сделан ВЫСОКИМ. Это как если бы у программного обеспечения была собственная жизнь. Когда я нажимаю кнопку LIGHT, события TIMER и MOTOR запускаются несколько раз - и я не могу понять, почему.
Я пытался:
- Использование параметра bouncetime, но это не перехватывает лишние события
- Использование резисторов для дебасинга
Только добавив условия таймера в обратный вызов, я могу остановить многократный запуск обратных вызовов, но это не устраняет причину проблемы, связанную с маршрутом. Мне нужно остановить выполнение обратных вызовов в первую очередь.
Схема выглядит следующим образом.
Важные элементы кода показаны ниже. (Я удалил довольно много неактуального кода, и может быть трудно отследить весь поток программы, но ключевые элементы есть.
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()
Будем благодарны за все, что вы увидите, или за советы по улучшению кода.
заранее спасибо