0

So I'm working on a project which requires both limit switch inputs and relay control outputs. I'm using an optocoupled relay so the output from the Pi's GPIO is more than adequate to run them. It's pretty simple to toggle the relays however when you use a "while True" arg, there seems to be a looping problem which prevents the other buttons from functioning. I have a simple project and it's eating me alive. I've rewritten the code 100 times and still I can't figure out how to write around this looping issue. I know there has to be an answer so if anyone has any ideas, I'd be really in debt to them. (Emotionally anyway). So Here's the code so far and it's not working but I'll comment on it so perhaps somebody may see my logic fallacy.

import Tkinter as tk
import tkinter.font
import RPi.GPIO as GPIO
from gpiozero inport LED, Button
from signal import pause
from time import sleep


win = tk.TK()
win.title("ARBOR")
myFont =tKinter.font.Font(Family = 'Helvectica', size = 24, weight = "bold")

led1 = LED(13) #These are actually three relays on pin 13, 6 and 26
led2 = LED(6)
led3 = LED(26)
button = Button(5)  #sensing status of pin 5

GPIO.setmode(GPIO.BCM)
GPIO.setup(5, GPIO.IN pull_up_down=GPIO.PUD_UP)


while True:
    input_state = GPIO.imput(5)
    if input_state == True:
        button["text"] = "System in Use"
        led3.on()
        break
else:
    button["text"] = "System Available"
    led1.off()
    led2.off()
    led3.off()
    break
#So the nested if statements below identify is another button is in use and
#renders the other buttons unavailable if conditions are not met

def selectOption1():
    if led1.is_lit:
       led1.off()
       led3.off()
       paperButton["text"] "Paper"
    else:
       if button["text"] != "System Available":
          if plasticButton["text"] != "Please Wait!":
             if glassButton["text"] != "Please Wait!":
                if generalButton["text"] != "Please Wait!":
                   led1.on() #turn on relay to send 24V to main control
                   led3.on() # turn on relay to control local latch
                   paperButton["text"] = "Please Wait"
def selectOption2():
    if led2.is_lit:
       led2.off() #relay for plastic selection is off
       led3.off() # relay for hopper latch is off
       plasticButton["text"] "Plastic"
    else:
       if button["text"] != "System Available":
          if paperButton["text"] != "Please Wait!":
             if glassButton["text"] != "Please Wait!":
                if generalButton["text"] != "Please Wait!":
                   led1.on() #relay for relay 1 is on
                   led3.on() #relay for hopper latch is activated
                   plasticButton["text"] = "Please Wait"
def selectOption3():
    if led1.is_lit:
       led1.off()
       led3.off()
       glassButton["text"] "Glass/Metal"
    else:
       if button["text"] != "System Available":
          if paperButton["text"] != "Please Wait!":
             if plasticButton["text"] != "Please Wait!":
                if generalButton["text"] != "Please Wait!":
                   led1.on()
                   led3.on()
                   glassButton["text"] = "Please Wait"
def selectOption4():
    if led2.is_lit:
       led2.off()
       led3.off()
       generlButton["text"] "General Waste"
    else:
       if button["text"] != "System Available":
          if paperButton["text"] != "Please Wait!":
             if glassButton["text"] != "Please Wait!":
                if plasticButton["text"] != "Please Wait!":
                   led13.on() #only the latch operates here. 
                   generalButton["text"] = "Please Wait"
def exitProgram():
    win.quit()
    win.destroy()
#packing the GUI

button=tk.Button(win, text='System Available', font=myFont, bg='blue', height=2, width=32) #button to change according to limit switch condition
button.grid(row=0, sticky=tk.NSEW)

paperButton=tk.Button(win, text='Paper', font=myFont, command=selectOption1, bg='blue', height=2, width=38)
paperButton.grid(row=1, sticky=tk.NSEW)

plasticButton=tk.Button(win, text='Plastic', font=myFont, command=selectOption2, bg='blue', height=2, width=38)
plasticButton.grid(row=2, sticky=tk.NSEW)

glassButton=tk.Button(win, text='Glass/Metal', font=myFont, command=selectOption3, bg='blue', height=2, width=38)
glassButton.grid(row=3, sticky=tk.NSEW)

generalButton=tk.Button(win, text='General Waste', font=myFont, command=selectOption4, bg='blue', height=2, width=38)
generalButton.grid(row=4, sticky=tk.NSEW)

exitButton=tk.Button(win, text='Exit', font=myFont, command=exitProgram, bg='red', height=2, width=38)
exitButton.grid(row=5, sticky=tk.E)

tk.mainloop()
1

Tk like all windowing systems needs to process events to work properly. This is done by setting up all your widgets and callbacks and then calling the mainloop function to start handling events. So when your user moves the mouse over the button and then clicks the button, we receive a sequence of MouseMove, Enter, ButtonDown, ButtonUp, Expose, Leave and probably other events. All of these have to be handled promptly or the UI appears to hang or not work in various ways. If you put some other loop like your while True: loop then you are not handling windowing system events and the UI cannot work correctly.

You can resolve this in one of two ways. Either use a single thread and schedule your GPIO calls using the Tk event processing with after. This lets you call a function after some time interval and you can re-schedule the same function again to get a regular timer. Alternatively you can use a background thread to handle the GPIO part of your application and use event generate to notify the UI thread when something interesting has happened. You MUST avoid making UI calls from a non-UI thread.

1
  • That makes sense Pathhoyts. I run into this same argument in Keil tool on Motorola chipware since it too can't process multiple threads at the same time. I've always figured ways around it. So if I get what you're saying is I have to write a loop which includes all the events on one single event and run a loop through all of them rather than waiting for an input from the limit switch. SO the limit switch and button events have to run in the same loop. I'll look up "after" syntax and see how to utilize it in the code. I think I understand what you're telling me to do. Thank you for feedback. Dec 4 '18 at 4:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.