Raspberry Pi workshop lesson tkinter issue

Following your tkinter 4.2 section on the console I get this error. Does anyone know what causes this?

## Toggle an LED when the GUI button is pressed ##

from tkinter import *
import tkinter.font
from gpiozero import LED
import RPi.GPIO
RPi.GPIO.setmode(RPi.GPIO.BCM)

### HARDWARE DEFINITIONS ###
led=LED(14)

### GUI DEFINITIONS ###
win = Tk()
win.title("LED Toggler")
myFont = tkinter.font.Font(family = 'Helvetica', size = 12, weight = "bold")


### Event Functions ###
def ledToggle():
    if led.is_lit:
        led.off()
        ledButton["text"]="Turn LED on" # Change only the button text property
    else:
        led.on()
        ledButton["text"]="Turn LED off"

def close():
    RPi.GPIO.cleanup()
    win.destroy()



### WIDGETS ###

# Button, triggers the connected command when it is pressed
ledButton = Button(win, text='Turn LED on', font=myFont, command=ledToggle, bg='bisque2', height=1, width=24)
ledButton.grid(row=0,column=1)

exitButton = Button(win, text='Exit', font=myFont, command=close, bg='red', height=1, width=6)
exitButton.grid(row=2, column=1)

win.protocol("WM_DELETE_WINDOW", close) # cleanup GPIO when user closes window

win.mainloop() # Loops forever

error

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 73, in _shutdown
    _PINS.pop().close()
  File "/usr/lib/python3/dist-packages/gpiozero/pins/rpigpio.py", line 118, in close
    GPIO.cleanup(self._number)
RuntimeError: Please set pin numbering mode using GPIO.setmode(GPIO.BOARD) or GPIO.setmode(GPIO.BCM)

It only happens if you are looking at the console. I think it has something to do with the window exiting before the cleanup() method is finished. Though I’m definitely no expert.

Hey @Wolf40565, thanks for bringing that to our attention!
I guess I was a bit naive trying to combine the two RPi.GPIO and gpiozero libraries. I did this to mix things up, give users a look at an alternative tool, and because I couldn’t find a satisfying cleanup() routine in gpiozero.

It’s pretty easy to port the script to use only RPi.GPIO, which seems to make everything behave.
I’ve tested that the interface works and no error is thrown, but unfortunately I’m working on a remote machine so I’m unable to test the hardware (led) side of things.

Here it is:

## Toggle an LED when the GUI button is pressed ##
# Use only RPi.GPIO to avoid spurious errors
from tkinter import *
import tkinter.font
import RPi.GPIO as GPIO
#setmode(BCM)
GPIO.setmode(GPIO.BCM)

### HARDWARE DEFINITIONS ###
led=14
GPIO.setup(led,GPIO.OUT)
GPIO.output(led, False)
### GUI DEFINITIONS ###
win = Tk()
win.title("LED Toggler")
myFont = tkinter.font.Font(family = 'Helvetica', size = 12, weight = "bold")


### Event Functions ###
def ledToggle():
    if GPIO.input(led):
        GPIO.output(led, False)
        ledButton["text"]="Turn LED on" # Change only the button text property
    else:
        GPIO.output(led, True)
        ledButton["text"]="Turn LED off"
    
def close():
    GPIO.cleanup()
    win.destroy()

In case anyone is interested
Here is the completed code that incorporates your changes and doesn’t produce any errors

## Toggle an LED when the GUI button is pressed ##
# Use only RPi.GPIO to avoid spurious errors
from tkinter import *
import tkinter.font
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)

### HARDWARE DEFINITIONS ###
led=14
GPIO.setup(led,GPIO.OUT)
GPIO.output(led, False)
### GUI DEFINITIONS ###
win = Tk()
win.title("LED Toggler")
myFont = tkinter.font.Font(family = 'Helvetica', size = 12, weight = "bold")


### Event Functions ###
def ledToggle():
    if GPIO.input(led):
        GPIO.output(led, False)
        ledButton["text"]="Turn LED on" # Change only the button text property
    else:
        GPIO.output(led, True)
        ledButton["text"]="Turn LED off"
    
def close():
    GPIO.cleanup()
    win.destroy()

### WIDGETS ###

# Button, triggers the connected command when it is pressed
ledButton = Button(win, text='Turn LED on', command=ledToggle, bg='bisque2', height=1, width=24)
ledButton.grid(row=0,column=1)

exitButton = Button(win, text='Exit', command=close, bg='red', height=1, width=6)
exitButton.grid(row=2, column=1)

win.protocol("WM_DELETE_WINDOW", close) # cleanup GPIO when user closes window

win.mainloop() # Loops forever
3 Likes

Thanks for that, I mustn’t have copied the entire script when I was posting the updated script.