# Project#7 - Combination Lock # Information - In this project, we're going to create a graphical user interface (GUI) with tkinter to... # control a relay on the RPInoRPI. Like project#5, we're controlling a relay, and we're using a GUI, only this time... # We're going to create a combination lock GUI. # If you want to create awesome GUIs, I highly recommend this tutorial: https://www.youtube.com/watch?v=YXPyB4XeYLA from tkinter import * # Import tkinter for GUI makin' fun! import time # For delays import serial # For microcontroller communication counter = 0 # Create and declare 'counter' as 0. val = 0 # Create 'val' and set to 0 numbers = [1, 2, 3, 4] # Create a list of 4 numbers that you want to be your deactivation code. 1234 in this case. comparelist = [0, 0, 0, 0] # Create an empty list of 0z that well modify with our code print('Enter Combination...') try: # Try to establish communication with the RPInoRPI board. if successful, only the 'try:' will be executed MCU = serial.Serial(port='COM10', baudrate=115200, timeout=0.01) # Timeout = 0.01. More on this later. time.sleep(1) # Wait 5 seconds. except: # If communication with the RPInoRPI could not be established, then perform the following instead: print('System Locked - Cannot communicate with MCU. Close this program, then reconnect to MCU and restart program') while True: # Forever loop. Close the program and start again. Check connection to the RPInoRPI pass # Do nothing def write_read(x): # This function acts to send data (x) to the RPInoRPI. Nothing more. MCU.write(bytes(x, 'utf-8')) # Write the value stored in 'x' to the RPInoRPI time.sleep(0.2) # Wait 0.2 seconds/200ms class App: # Create a class named 'App'. You can build on project#5 and follow that method of GUI design if you'd like def __init__(self, master): # This function takes care of the button presses frame = Frame(master) # Create the GUI frame frame.pack() # Pack() is something that I rarely use. I like to grid things up manually, # But let's try it this way for the sake of education, shall we? Label(frame, text='Numeric Keypad').grid(row=0, column=1) # Create this label and set to Row 0 and Column 1 button = Button(frame, text='1', command=self.convert) # Button #1 (Text='1'), calls 'convert' function below button.grid(row=1, column=0) # Place Button#1 in row1, column 1 button2 = Button(frame, text='2', command=self.convert2) # We do this for all 10 buttons from 0-9. button2.grid(row=1, column=1) # Row 1 column 1 button3 = Button(frame, text='3', command=self.convert3) # When a button is pressed, the convert3 function s called button3.grid(row=1, column=2) # and so on, and so on! button4 = Button(frame, text='4', command=self.convert4) button4.grid(row=2, column=0) button5 = Button(frame, text='5', command=self.convert5) button5.grid(row=2, column=1) button6 = Button(frame, text='6', command=self.convert6) button6.grid(row=2, column=2) button7 = Button(frame, text='7', command=self.convert7) button7.grid(row=3, column=0) button8 = Button(frame, text='8', command=self.convert8) button8.grid(row=3, column=1) button9 = Button(frame, text='9', command=self.convert9) button9.grid(row=3, column=2) button0 = Button(frame, text='0', command=self.convert0) button0.grid(row=4, column=1) def convert(self): # When button#1 has been pressed, this function is called print('1') # Prints '1' to the shell global val # Sets variable 'Val' as a global, which means it can be used across functions val = 1 # Set Val to 1 (button#1). countnum() # Call the countum() function. Really we could send over 'Val' in a more organized way... #... But I want to make this program as easy to follow as I can. # Check out the countnum() function below. def convert2(self): # Same as above, only this function is called when button#2 is pressed, print('2') global val val = 2 countnum() def convert3(self): # For button#3 print('3') global val val = 3 countnum() def convert4(self): # and button#4 (You get it at this point, right?) print('4') global val val = 4 countnum() def convert5(self): print('5') global val val = 5 countnum() def convert6(self): print('6') global val val = 6 countnum() def convert7(self): print('7') global val val = 7 countnum() def convert8(self): print('8') global val val = 8 countnum() def convert9(self): print('9') global val val = 9 countnum() def convert0(self): print('0') global val val = 0 countnum() def countnum(): # Finally! Here we are. This function creates our new list and compares the completed list against... # Our pre-selected combination. Follow along with me. global counter # Set counter as a global variable global val # Do the same with val compare = 0 # Set 'compare' to 0. We will get to compare later in this function comparelist[counter] = val # Place the value in 'val' from the last button press into the comparelist # the value in counter points to the place in the list where val goes. 1-4, or rather 0-3 counter = counter + 1 # Add 1 to counter if counter == 4: # If counter equals 4, then we're ready to compare our entered combo to our fixed combo for i in range(4): # Run the following two lines of code 4 times if comparelist[i] == numbers[i]:# Compare our new 4x comparelist numbers to the 4x saved numbers list numbers compare = compare + 1 # For ever match of numbers, add 1 to compare. counter = 0 # compare will only be 4 if all 4 numbers matched across the two lists val = 0 # Clear both counter and val if compare == 4: # Check to see if all four numbers matched # If yes, send the command to the MCU to activate the relay for 10 seconds print("Success! Access Granted!") # Print this to the shell x = '5' write_read(x) else: print("Incorrect Code... Try again!") # Oopsie-Poopsie! You entered in an incorrect 4-digit password! x = '4' # Send over a value of anything other than '5' to trigger the buzzer/bad combo write_read(x) print('Enter Combination...') root = Tk() # More GUI stuff. This command runs the GUI root.wm_title('Numeric Keypad') # The title of the GUI app = App(root) # Necessary the buttons to show up in the GUI. Comment it out and see what happens! root = mainloop() # Loop the GUI