This is my complete code, that does not work as expected. The issue is if f_trigger
def while loop runs, then f_reset
is deaf - not listening anymore and not triggered. therefore alarm_cancel
is never turned to True. Is this something documented, that if loop runs in one callback function, then another callback is ignored?
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
_gpin = 11
_gpin_reset = 12
alarm_cancel = False
def f_trigger(channel):
global alarm_cancel
while alarm_cancel == False:
print('alarm cancel status: %s' % (alarm_cancel))
time.sleep(.3)
alarm_cancel = False
def f_reset(channel):
global alarm_cancel
print('f_reset called')
alarm_cancel = True
# Define INPUTs
GPIO.setup(
_gpin,
GPIO.IN,
pull_up_down=GPIO.PUD_UP
) # input #1
# Trigger #1
GPIO.add_event_detect(
_gpin, GPIO.BOTH, callback=f_trigger, bouncetime=100
)
# Define INPUTs
GPIO.setup(
_gpin_reset,
GPIO.IN,
pull_up_down=GPIO.PUD_UP
) # input #2
# Trigger #2
GPIO.add_event_detect(
_gpin_reset, GPIO.BOTH, callback=f_reset, bouncetime=100
)
while True:
print('main thread loop running')
time.sleep(60)
2 Answers 2
Callbacks are emitted by one thread. Each callback will therefore run to completion before the next is called.
This is true for RPi.GPIO and all the other Pi GPIO Python and C modules that I am aware of.
Treat callbacks as interrupts. Do the minimum possible before returning, e.g. set a flag to be picked up in the main thread.
-
Thanks for explanation, so i need to make different implementationB.Ondrej– B.Ondrej2021年04月13日 17:11:55 +00:00Commented Apr 13, 2021 at 17:11
Another option that will make multiple callback work together is to use threading like in example below and run the callback function with loop as specific thread, then if another callback function sets flag to True, this thread will still be able to read the alarm_cancel flag:
import threading
def f_trigger(channel):
threading.Thread(name='_thread_fireup_alarm', target=fireup_alarm, args=(channel,)).start()
def fireup_alarm(channel):
global alarm_cancel
while alarm_cancel == False:
print('alarm cancel status: %s' % (alarm_cancel))
time.sleep(1)
alarm_cancel = False