multithreadinggpiopi

Why are these functions still active? Python 3


I’m trying to make a program to enter morse into my Pi, I have 3 buttons one for dot one for dash and a command button I want to use to indicate the end of a letter. I have used threads so that the Pi is listening for input from all 3 buttons. However I want to be able to make it stop listening to the buttons too. I’ve tried to make a global variable n which when the command button is pushed it sets to 10 which should break all the while-loops and end the threads - however this is not happening, n is indeed being set to 10 but then for some reason all the while-loops are continuing. It seems to be just completely ignoring the n == 0 condition - what am I doing wrong?

from gpiozero import Button
from threading import Thread
import sys
btn1 = Button(2)
btn2 = Button(3)
cmdbtn = Button(4)
currentMorse = ""

def pressed1():
    print("Pressed1")
    global currentMorse
    currentMorse = currentMorse + "."
    print(currentMorse)

def released1():
    print("Released")

def pressed2():
    print("Pressed2")
    global currentMorse
    currentMorse = currentMorse + ","
    print(currentMorse)

def released2():
    print("Released")

def pressedcmd():
    print("Pressedcmd")

def releasedcmd():
    print("Releasedcmd")
    global n
    n = 10

def checker1():
    global n
    while n == 0:
        btn1.when_pressed = pressed1
        btn1.when_released = released1
    print(n)

def checker2():
    global n
    while n == 0: 
        btn2.when_pressed = pressed2
        btn2.when_released = released2
    print(n)

def checkercmd():
    global n
    while n == 0:         
        cmdbtn.when_pressed = pressedcmd
        cmdbtn.when_released = releasedcmd
    print(n)

if __name__ == '__main__':
    n = 0
    Thread(target = checker1).start()
    Thread(target = checker2).start()
    Thread(target = checkercmd).start()

I’ve tried putting system exits in to try and break the threads and have played around with the n condition in various ways, but nothing is changing, it just keeps accepting inputs from the buttons as if the n == 0 condition wasnt there.


Solution

  • So it turns out that when_pressed makes a thread itself - so all the other threads I made were unnecessary and made everything much harder to solve.

    To stop when_pressed, you just need to set it to None:

        from gpiozero import Button
        from threading import Thread
        def start():
            global btn1
            btn1 = Button(2)
            global btn2
            btn2 = Button(3)
            global cmdbtn
            cmdbtn = Button(4)
            global currentMorse
            currentMorse = ""
            
            checker1()
            checker2()
            checkercmd()
    
        def continuer():
            checker1()
            checker2()
            checkercmd()
        
        
        def pressed1():
            print("Pressed1")
            global currentMorse
            currentMorse = currentMorse + "."
            print(currentMorse)
    
    
        def released1():
            print("Released")
    
        def pressed2():
            print("Pressed2")
            global currentMorse
            currentMorse = currentMorse + ","
            print(currentMorse)
    
        def released2():
            print("Released")
    
        def pressedcmd():
            print("Pressedcmd")
    
    
        def releasedcmd():
            print("Releasedcmd")
            global n
            n = 10
            btn1.when_pressed = None    
            btn1.when_released = None
            btn2.when_pressed = None    
            btn2.when_released = None 
            cmdbtn.when_pressed = None    
            cmdbtn.when_released = None
        
        def checker1():
            
            btn1.when_pressed = pressed1
    
    
        
            btn1.when_released = released1
    
            return()
    
        def checker2():
            
            btn2.when_pressed = pressed2
    
    
    
            btn2.when_released = released2
            return()
    
    
        def checkercmd():
            
            cmdbtn.when_pressed = pressedcmd
    
    
    
            cmdbtn.when_released = releasedcmd