GPIO, Input & Output GUI panel using Tkinter
The article guides you through Designing a Graphical panel to control all the 21 GPIO’s of Raspberry Pi as an Input or Output Pin.
In this tutorial we will be Designing a Graphical panel through which we will be able to control all the 21 GPIO's of Raspberry Pi as an Input or Output Pin.
Credits for the program - scotty3785, Original code link - click here
Step 1 - Programming the Raspberry Pi
Step 2 - Running the program and Understanding the GUI panel
- Open the python IDLE in Raspberry Pi and create a new Python file and enter the following code.
#This code has been published by Robu.in
#visit https://robu.in for more information
import sys
if(sys.version_info[0]<3):
from Tkinter import *
else:
from tkinter import *
import RPi.GPIO as pi
import math
#import tkSimpleDialog
class LED(Frame):
"""A Tkinter LED Widget.
a = LED(root,10)
a.set(True)
current_state = a.get()"""
OFF_STATE = 0
ON_STATE = 1
def __init__(self,master,size=10,**kw):
self.size = size
Frame.__init__(self,master,width=size,height=size)
self.configure(**kw)
self.state = LED.OFF_STATE
self.c = Canvas(self,width=self['width'],height=self['height'])
self.c.grid()
self.led = self._drawcircle((self.size/2)+1,(self.size/2)+1,(self.size-1)/2)
def _drawcircle(self,x,y,rad):
"""Draws the circle initially"""
color="red"
return self.c.create_oval(x-rad,y-rad,x+rad,y+rad,width=rad/5,fill=color,outline='black')
def _change_color(self):
"""Updates the LED colour"""
if self.state == LED.ON_STATE:
color="green"
else:
color="red"
self.c.itemconfig(self.led, fill=color)
def set(self,state):
"""Set the state of the LED to be True or False"""
self.state = state
self._change_color()
def get(self):
"""Returns the current state of the LED"""
return self.state
## Future Functionality
##class gpioEdit(tkSimpleDialog.Dialog):
## """Dialog to be expanded to support advanced gpio features like
## - Pull Up / Pull Down Resistor Config
## - Debounce"""
## def __init__(self, master,gpio):
## top = self.top = Toplevel(master)
## if gpio.isInput():
## title = "Edit Input: %s" %(str(gpio.name))
## else:
## title = "Edit Output: %s" %(str(gpio.name))
## l = Label(top,text=title)
## b = Button(top, text="Submit", command=self.submit)
##
## l.grid(row=0)
## b.grid(row=1)
##
## def submit(self):
## print("Submitted")
## self.top.destroy()
class GPIO(Frame):
"""Each GPIO class draws a Tkinter frame containing:
- A Label to show the GPIO Port Name
- A data direction spin box to select pin as input or output
- A checkbox to set an output pin on or off
- An LED widget to show the pin's current state
- A Label to indicate the GPIOs current function"""
gpio_modes = ("Passive","Input","Output")
def __init__(self,parent,pin=0,name=None,**kw):
self.pin = pin
if name == None:
self.name = "GPIO %02d" % (self.pin)
Frame.__init__(self,parent,width=150,height=20,relief=SUNKEN,bd=1,padx=5,pady=5)
##Future capability
##self.bind('<Double-Button-1>', lambda e, s=self: self._configurePin(e.y))
self.parent = parent
self.configure(**kw)
self.state = False
self.cmdState = IntVar()
self.Label = Label(self,text=self.name)
self.mode_sel = Spinbox(self,values=self.gpio_modes,wrap=True,command=self.setMode)
self.set_state = Checkbutton(self,text="High/Low",variable=self.cmdState,command=self.toggleCmdState)
self.led = LED(self,20)
self.Label.grid(column=0,row=0)
self.mode_sel.grid(column=1,row=0)
self.set_state.grid(column=2,row=0)
self.current_mode = StringVar()
self.led.grid(column=3,row=0)
self.set_state.config(state=DISABLED)
function = self.getPinFunctionName()
if function not in ['Input','Output']:
self.mode_sel.delete(0,'end')
self.mode_sel.insert(0,function)
self.mode_sel['state'] = DISABLED
## def _configurePin(self, y):
## """Future capability to setup pull up/down"""
## new = gpioEdit(self.parent,self)
def isInput(self):
"""Returns True if the current pin is an input"""
return (self.mode_sel.get() == "Input")
def setMode(self):
"""Sets the GPIO port to be either an input or output
Depending on the value in the spinbox"""
if (self.mode_sel.get() == "Input"):
self.set_state.config(state=DISABLED)
pi.setup(self.pin,pi.IN)
elif (self.mode_sel.get() == "Passive"):
self.set_state.config(state=DISABLED)
pi.cleanup(self.pin)
else:
self.set_state.config(state=NORMAL)
pi.setup(self.pin,pi.OUT)
self.updateInput()
def getPinFunctionName(self):
pin = self.pin
functions = {pi.IN:'Input',
pi.OUT:'Output',
pi.I2C:'I2C',
pi.SPI:'SPI',
pi.HARD_PWM:'HARD_PWM',
pi.SERIAL:'Serial',
pi.UNKNOWN:'Unknown'}
return functions[pi.gpio_function(pin)]
## Future Functionality
## def setPullUp(self,pullup):
## """Defines the GPIO as having a pull up resistor so the input
## state is inverted when read
## setPullUp(True) - Pin is pulled up
## setPullUP(False) - Pin is not pulled up"""
## self.pullup = pullup
def toggleCmdState(self):
"""Reads the current state of the checkbox, updates LED widget
and sets the gpio port state."""
self.state = self.cmdState.get()
self.updateLED()
self.updatePin()
def updatePin(self):
"""Sets the GPIO port state to the current state"""
pi.output(self.pin,self.state)
def updateLED(self):
"""Refreshes the LED widget depending on the current state"""
self.led.set(self.state)
def updateInput(self):
"""Updates the current state if the pin is an input and sets the LED"""
if self.isInput():
state = pi.input(self.pin)
self.state = state
self.updateLED()
class App(Frame):
def __init__(self,parent=None, **kw):
Frame.__init__(self,parent,**kw)
self.parent = parent
pi.setmode(pi.BCM)
self.ports = []
## Get the RPI Hardware dependant list of GPIO
gpio = self.getRPIVersionGPIO()
for num,(p,r,c) in enumerate(gpio):
self.ports.append(GPIO(self,pin=p))
self.ports[-1].grid(row=r,column=c)
self.update()
def onClose(self):
"""This is used to run the Rpi.GPIO cleanup() method to return pins to be an input
and then destory the app and its parent."""
try:
pi.cleanup()
except RuntimeWarning as e:
print(e)
self.destroy()
self.parent.destroy()
def readStates(self):
"""Cycles through the assigned ports and updates them based on the GPIO input"""
for port in self.ports:
port.updateInput()
def update(self):
"""Runs every 100ms to update the state of the GPIO inputs"""
self.readStates()
self._timer = self.after(100,self.update)
def getRPIVersionGPIO(self):
"""Returns the GPIO hardware config for different Pi versions
Currently supports layout 1 and 3"""
gpio1 = ((0,0,0),
(1,1,0),
(4,2,0),
(17,3,0),
(21,4,0),
(22,5,0),
(10,6,0),
(9,7,0),
(11,8,0),
(14,0,1),
(15,1,1),
(18,2,1),
(23,3,1),
(24,4,1),
(25,5,1),
(8,6,1),
(7,7,1))
gpio2 = ((2,0,0),
(3,1,0),
(4,2,0),
(17,3,0),
(27,4,0),
(22,5,0),
(10,6,0),
(9,7,0),
(11,8,0),
(14,0,1),
(15,1,1),
(18,2,1),
(23,3,1),
(24,4,1),
(25,5,1),
(8,6,1),
(7,7,1))
gpio3 = ((2,0,0),
(3,1,0),
(4,2,0),
(17,3,0),
(27,4,0),
(22,5,0),
(10,6,0),
(9,7,0),
(11,8,0),
(5,9,0),
(6,10,0),
(13,11,0),
(19,12,0),
(26,13,0),
(14,0,1),
(15,1,1),
(18,2,1),
(23,3,1),
(24,4,1),
(25,5,1),
(8,6,1),
(7,7,1),
(12,8,1),
(16,9,1),
(20,10,1),
(21,11,1))
if pi.RPI_REVISION == 3:
gpio = gpio3
self.parent.title('Raspberry Pi GPIO - A+/B+/2B+')
elif pi.RPI_REVISION == 2:
#Change this when I know the pins on RPi GPIO Version 2
gpio = gpio2
self.parent.title('Raspberry Pi GPIO - A/B Rev2')
elif pi.RPI_REVISION == 1:
self.parent.title('Raspberry Pi GPIO - A/B')
gpio = gpio1
else:
self.parent.title('Raspberry Pi GPIO - Unknown Version')
##Assume same config as A+/B+/2B+
gpio = gpio3
return gpio
def main():
root = Tk()
root.title("Raspberry Pi GPIO")
a = App(root)
a.grid()
"""When the window is closed, run the onClose function."""
root.protocol("WM_DELETE_WINDOW",a.onClose)
root.resizable(False,False)
root.mainloop()
if __name__ == '__main__':
main()
- Now save the program. We are saving it as gpio.py python file.
Step 2 - Running the program and Understanding the GUI panel
- Now open terminal and type command sudo python gpio.py to run the program.
- A panel window will open up like this -
- From here you can set the status of any GPIO pin from the Corresponding drop down menu as Passive, Input or Output.
- If you have selected Output, then you will have to mark or unmark the corresponding High/Low box to make the Pin Low or High
- If you have selected Input, then the low Input will show the the Red colour and if input is high, it will show Green Colour.
Tags : Raspberry Pi Article
