Stap 15: Codevoorbeeld voor de toepassing van de Python
#!/usr/bin/env python # # For Linux, BSD or Mac OSX you can chmod +x on this script to make executable # ########### # Rover control app # # Allows for simple multi-byte commands. # # Written by Scott Beasley - 2015 # Free to use or modify. Enjoy. # ########### import sys import serial import time from Tkinter import * import tkFont import tkMessageBox # Create the window for the application class App (Frame): # Make the window def createWidgets (self): self.connected = False self.message = StringVar ( ) # Make a little font for the gripper set buttons. helv6 = tkFont.Font (family = 'Helvetica', size = 6, weight = 'normal') self.frame = Frame (self.master) self.frame.pack ( ) self.f1 = Frame (self.frame) self.l1 = Label (self.f1, text = "Comm Port: ") self.l1.pack (side = LEFT) self.comm_entry = Entry (self.f1, bd = 5, name = "comm_entry") self.comm_entry.pack (side = LEFT) self.connectButton = Button (self.f1, text = "Connect", command = self.SerialConnect, name = "b_connect") self.connectButton.pack (side = LEFT) self.disconnectButton = Button (self.f1, text = "Disconnect", command = self.SerialDisconnect, name = "b_disconnect") self.disconnectButton.pack (side = RIGHT) self.f1.grid (row = 0, column = 0) self.f2 = LabelFrame (self.frame, bd = 3, relief = "groove", text="Ground Control") self.g_vert_fm = Frame (self.f2) self.grip_vert = Scale (self.g_vert_fm, from_ = 0, to = 180) # Bind on mouse button 1 release to set the boom position self.grip_vert.bind ('', self.GripperY) self.grip_vert.grid (row = 0, column = 0, rowspan = 4, sticky = W) self.master.bind ("", self.GripperY) self.g_vert_fm.grid (row = 0, column = 0, rowspan = 4, sticky = W) self.leftforwardButton = Button (self.f2, text = "\\", command = self.TurnLeft45, name = "b_left_forward") self.leftforwardButton.grid (row = 0, column = 1) self.master.bind ("<a rel="nofollow">", self.TurnLeft45) self.leftButton = Button (self.f2, text = "<", command = self.TurnLeft, name = "b_left") self.leftButton.grid (row = 1, column = 1) self.master.bind ("</a><a rel="nofollow">", self.TurnLeft) self.rightforwardButton = Button (self.f2, text = "/", command = self.TurnRight45, name = "b_right_forward") self.rightforwardButton.grid (row = 0, column = 3) self.master.bind ("</a><a rel="nofollow">", self.TurnRight45) self.haltButton = Button (self.f2, text = "Halt!", command = self.Halt, name = "b_halt") self.haltButton.grid (row = 1, column = 2) self.master.bind ("</a><a rel="nofollow">", self.Halt) self.rightButton = Button (self.f2, text=">", command = self.TurnRight, name = "b_right") self.rightButton.grid(row = 1, column = 3) self.master.bind ("</a><a rel="nofollow">", self.TurnRight) self.upButton = Button (self.f2, text="^", command = self.Forward, name = "b_forward") self.upButton.grid (row = 0, column = 2) self.master.bind ("</a><a rel="nofollow">", self.Forward) self.leftdownButton = Button (self.f2, text = "/", command = self.TurnRight45, name = "b_left_down") self.leftdownButton.grid (row = 2, column = 1) self.downButton = Button (self.f2, text="V", command = self.Reverse, name = "b_reverse") self.downButton.grid (row = 2, column = 2) self.master.bind ("</a><a rel="nofollow">", self.Reverse) self.f2.grid (row = 1, column = 0, pady = 25) self.rightdownButton = Button (self.f2, text = "\\", command = self.TurnLeft45, name = "b_right_down") self.rightdownButton.grid (row = 2, column = 3) self.g_horz_fm = Frame (self.f2) self.grip_horz = Scale (self.g_horz_fm, from_ = 0, to = 180, orient = HORIZONTAL) # Bind on mouse button 1 release to set the gripper position self.grip_horz.bind ('</a><a rel="nofollow">', self.GripperX) self.grip_horz.grid (row = 0, column = 0, columnspan = 7, sticky = E) self.master.bind ("<u>", self.GripperX) self.g_horz_fm.grid (row = 4, column = 0, columnspan = 7, sticky = E) self.master.bind ("</u></a><a rel="nofollow"><u>", self.GripperHome) self.f_spd_dist = Frame (self.frame) self.l_speed = Label (self.f_spd_dist, text = " Speed: ") self.l_speed.grid (row = 0, column = 0) self.speed_spin = Spinbox (self.f_spd_dist, values = (1, 2, 3), width = 2, command = self.SetSpeed) self.speed_spin.grid (row = 0, column = 1) self.l_dist = Label (self.f_spd_dist, text = " Distance: ") self.l_dist.grid (row = 0, column = 3) self.dist_spin = Spinbox (self.f_spd_dist, values = ('Short', 'Medium', 'Continuous'), width = 10, command = self.SetDistance) self.dist_spin.grid (row = 0, column = 4) self.l_turns = Label (self.f_spd_dist, text = " Turns: ") self.l_turns.grid (row = 0, column = 5) self.turns_spin = Spinbox (self.f_spd_dist, values = ('Hard', 'Soft'), width = 5, command = self.SetTurns) self.turns_spin.grid (row = 0, column = 6) self.f_spd_dist.grid (row = 2, column = 0) self.f3 = Frame (self.frame) self.l2 = Label (self.f3, text = "Last action: ") self.l2.pack (side = LEFT) self.l3 = Label (self.f3, text=" ", textvariable = self.message) self.l3.pack (side = RIGHT) self.f3.grid (row = 5, column = 0, pady = 8) # Set the state of the bot control buttons. Enable when connected, # Disabled otherwise. def CtrlButtonsState (self, bstate): self.leftforwardButton.config (state = bstate) self.leftButton.config (state = bstate) self.rightforwardButton.config (state = bstate) self.rightButton.config (state = bstate) self.upButton.config (state = bstate) self.leftdownButton.config (state = bstate) self.downButton.config (state = bstate) self.rightdownButton.config (state = bstate) self.haltButton.config (state = bstate) self.disconnectButton.config (state = bstate) self.grip_horz.config (state = bstate) self.grip_vert.config (state = bstate) # Set the state of the comm port entry. Enable when not connected, # Disabled when the bot is connected. def ConnCtrlsState (self, bstate): self.connectButton.config (state = bstate) self.comm_entry.config (state = bstate) # Connect to the comm port typed in the comm entry field. def SerialConnect (self): try: # Change the baud rate here if diffrent then 9600 self.ser = serial.Serial (self.comm_entry.get ( ), 9600) except IOError: tkMessageBox.showerror ("Invalid comm port", "Comm port not found.") return self.ConnCtrlsState (DISABLED) self.CtrlButtonsState (NORMAL) self.message.set ("SerialConnect") self.connected = True time.sleep (3) # Dwell a bit for the connection to happen # Do some after connection bot talking. if self.connected == True: self.setbotParms ( ) # Disconnect from the bot (close the comm port). def SerialDisconnect (self): try: # Send a Halt command just in case the bot is still moving. self.send_cmd ('h', "Halt!") time.sleep (1) self.ser.close ( ) except IOError: print "Could not close port..." self.message.set ("SerialDisconnect") self.ConnCtrlsState (NORMAL) self.CtrlButtonsState (DISABLED) self.connected = False time.sleep (2) # Dwell a bit for the disconnection to happen # Send the command to the open comm port # the action input variable is a tuple that allows for multy part commands def send_cmd (self, action, msg): if self.connected == True: for val in action: self.ser.write (val) self.ser.flush ( ) self.message.set (msg) # Send the bot a turn-left command. def TurnLeft (self, event = None): self.send_cmd ('a', "Left") # Send the bot a turn-left-up command. def TurnLeft45 (self, event = None): self.send_cmd ('q', "Left45") # Send the bot a turn-right command. def TurnRight (self, event = None): self.send_cmd ('s', "Right") # Send the bot a turn-right-up command. def TurnRight45 (self, event = None): self.send_cmd ('e', "Right45") # Send the bot a Forward command. def Forward (self, event = None): self.send_cmd ('w', "Up") # Send the bot a Reverse command. def Reverse (self, event = None): self.send_cmd ('z', "Down") # Send the bot a Halt command. def Halt (self, event = None): self.send_cmd ('h', "Halt!") # Set the gripper (X). def GripperX (self, event = None): # Read the slider control and send the value to the bot controller # Note: 0 is all the way closed and 180 is all the way open # This is a multi-byte command. The command + the servo set val # + a buffer clear command (optional) grp_change = ('>', chr (self.grip_horz.get ( )), chr (255)) self.send_cmd (grp_change, "Gripper X") self.boomchange = None # Set the gripper Y. def GripperY (self, event = None): # Read the slider control and send the value to the bot controller # Note: 0 is all the way up and 180 is all the way down # This is a multi-byte command. The command + the servo set val # + a buffer clear command (optional) grp_change = ('^', chr (self.grip_vert.get ( )), chr (255)) self.send_cmd (grp_change, "Gripper Y") self.gripperchange = None # Set the gripper to the "home" position. def GripperHome (self, event = None): self.send_cmd (('c', chr (255)), "Gripper Home") self.grip_horz.set (90) self.grip_vert.set (90) # Set the speed of the rover. def SetSpeed (self, event = None): spd_str = self.speed_spin.get ( ) if spd_str == "1": speed = 1 if spd_str == "2": speed = 2 if spd_str == "3": speed = 3 # Sends a multi-byte command to set the speed. self.send_cmd (('v', chr (speed)), "Set Speed") # Set the distance travled when a for or rev is issued to # the rover. def SetDistance (self, event = None): dist = 1 dist_str = self.dist_spin.get ( ) if dist_str == "Short": dist = 1 if dist_str == "Medium": dist = 2 if dist_str == "Continuous": dist = 3 # Sends a multi-byte command to set the distance. self.send_cmd (('d', chr (dist)), "Set Distance") # Set the turn style to use turning. def SetTurns (self, event = None): turn = 1 turn_str = self.turns_spin.get ( ) if turn_str == "Hard": turn = 1 if turn_str == "Soft": turn = 2 # Sends a multi-byte command to set the turn style. self.send_cmd (('t', chr (turn)), "Set Turns") def setbotParms (self): self.Halt ( ) self.GripperHome ( ) self.SetSpeed ( ) self.SetDistance ( ) self.SetTurns ( ) def __init__ (self, master = None): Frame.__init__ (self, master) self.pack ( ) self.createWidgets ( ) self.CtrlButtonsState (DISABLED) # Kick off the GUI (Tk) then size and title the app window def main ( ): root = Tk ( ) root.geometry ("450x360") root.wm_title ("Rover Control Center (RCC)") app = App (master = root) app.mainloop ( ) if __name__ == '__main__': main ( ) </u></a>