1 """! Documentation for the servo_demo.py script. 2 An example script for controlling the right hand. 3 This script can also be used to calibrate the bot. Please see @ref connect, 4 @ref cmd, and @ref calibrate. 5 This script requires python with a library called pyserial. 6 After instally python 3, pyserial can be installed by calling 12 Or through your package manager. Example: 15 sudo apt-get install python-pyserial 18 Once you have the library installed, you must have your \b PYTHONPATH variable set 19 to the location of the library. 22 export PYTHONPATH=/usr/lib/python2.7/site-packages 25 Replace 2.7 with your version of python (type in /usr/lib/python and press tab 28 This may vary from system to system. 29 See the <a href="http://www.python.org/">python</a> and 30 <a href="http://pyserial.sourceforge.net/">pyserial</a> websites for help. 32 To run the script, execute 35 python -i servo_demo.py 44 This will allow you to call the functions from a command interpreter. 45 It is recommended you experiment with all functions and view the source to 46 understand how you might produce commands. Also try demo() while connected. 48 The movements included are quickly written and for demo purposes only. 50 @see @ref index for the servo codes. 53 The serial connection for input and output. Must be initialized. 56 The identification byte of the right hand board. 60 from time
import sleep
70 ser = serial.Serial ()
73 """! Sets the global @ref ser variable. 75 Call this to connect to the board. 77 connect ('/dev/ttyUSB0') 79 Replace \b /dev/ttyUSB0 with the name of the port your board is connected 80 to. Usually this is \b /dev/ttyUSB* for the arduino nano or \b 81 /dev/ttyACM* for the arduino uno. This is the same port used in @ref 84 Note that you must be part of the dialout group in Linux. Enter this 85 command to add yourself to a group. 88 usermod -a -G dialout $USER 91 You must logout to apply group changes. If you cannot logout, you can run 96 export PYTHONPATH=/usr/lib/python2.7/site-packages 97 python -i example/servo_demo.py 101 ser = serial.Serial (port, 9600, timeout=1)
103 def sweep (initial, servos, starts, ends, steps):
104 """! Produces complex command chains. 106 The output returned from the function is formatted in such a way that the 107 commands can be transmitted to the serial port at variable speeds. 109 The parameters must all be lists of the same length whose indexes 110 correspond with \b servos. 112 @param initial An array of initial commands to append to. 113 @param servos The servos to control. 114 @param starts The current positions of the servos. 115 @param ends The desired end positions. 116 @param steps The values to use to decrement/increment. 117 Converted to absolute value. 119 @returns Upon success, returns the generated list of commands. 120 The commands are surrounded by the @ref CANCEL_SIGNAL for syncing. 121 The servos will always reach their exact final destination, unless if 122 \b steps at the index of the servo is 0. 123 Upon error, raises <b>'Invalid sweep command'</b>. 124 This indicates non-matching list lengths. 127 @code sweep ([], [1,2], [180,0], [90,180], [90,45]) @endcode 130 [CANCEL_SIGNAL, 1, 180, 2, 0, 1, 90, 2, 45, 2, 90, 2, 135, 2, 180, CANCEL_SIGNAL] 132 The protocol this follows is described in servo.ino. 133 By intertwining commands in this way, a delay can be inserted between 134 bytes and fluid motion is still preserved. 143 if ln != len (starts)
or ln != len (ends)
or ln != len (steps):
144 raise NameError (
'Invalid sweep command')
146 initial.append (CANCEL_SIGNAL)
161 initial.append (servos [i])
162 initial.append (pos [i])
165 if pos [i] == ends [i]
or steps [i] == 0:
168 elif starts [i] < ends [i]:
169 pos [i] += abs (steps [i])
171 if pos [i] > ends [i]:
175 pos [i] -= abs (steps [i])
177 if pos [i] < ends [i]:
184 initial.append (CANCEL_SIGNAL)
188 """! Produces a command chain that resets all servos to 0. 192 ends = list ([0
for x
in servos])
193 return sweep ([], servos, starts, ends, steps)
196 """! Writes commands to the serial port. 198 If \b delay is 0, immediately writes a list of ints to @ref ser as bytes. 199 Otherwise, writes a list of ints to @ref ser as bytes one at a time. 201 Inserting a delay controls the speed of the movements. 212 def gesture (initial, servos, starts, ends, steps, delay):
214 Sets the servos to a position, waits for input, then resets them to 0. 215 @see sweep() servowrite() 217 initial = sweep (initial, servos, starts, ends, steps)
219 servowrite (initial, delay)
221 initial = unsweep (servos, ends, steps)
223 servowrite (initial, delay)
226 """! Immediately sets the servos to 0.""" 227 servowrite ([CANCEL_SIGNAL,1,0,2,0,3,0,4,0,5,0], 0)
230 """! Sends the input to the serial port until a blank line is given. 231 Must enter integers between 0-255. 239 servowrite ([int (s)], 0)
242 """! Retrieves information about the board. 243 The command sends the @ref DUMP_SIGNAL to the serial port and reads back 244 the response. The response is described in servo.ino. 246 When you write your own similar function, timing is important. 248 We may need to increase the response delay on the Arduino if you are unable 249 to recieve a response. View the source of this function to understand how 250 it works, but keep in mind it is untested. Also keep in mind that the 251 function is very non-general as it always reads the same amount of bytes 252 instead of looking for the end signal. 254 @note While this function could be used to change dynamically between 255 gestures instead of resetting the servos to 0, this function did not exist 256 when this script was first written. 263 servowrite ([DUMP_SIGNAL], 0)
267 response = ser.read (servos * 2 + 4)
269 response = list (response)
272 if not (response [0] == START_RESPONSE
and response [-1] == END_RESPONSE):
275 print (
'id: ' + str (response [1]))
276 if response [1] == RHAND_ID:
277 print (
'this board is the right hand.')
278 print (
'servos: ' + str (response [2]))
279 servos = response [2]
281 while i < servos * 2:
282 print (
'servo ' + str (response [i + 3]) +
': ' + str (response [i + 4]))
288 """! Makes a peace sign. @see gesture()""" 289 gesture ([CANCEL_SIGNAL,2,0,3,0], [1,4,5], [0] * 3, [180] * 3, [10] * 3, delay)
292 """! Makes an ok sign. @see gesture()""" 293 gesture ([CANCEL_SIGNAL,3,0,4,0,5,0], [1,2], [0,0], [180,160], [10,10], delay)
296 """! Makes a fist. @see gesture()""" 297 gesture ([], [1,2,3,4,5], [0] * 5, [180] * 5, [60] * 5, delay)
300 """! Makes a rock on sign. @see gesture()""" 301 gesture ([], [3,4], [0,0], [180,180], [10,10], 0.01)
303 def wiggle (n=90, delay=0.01, wiggles=1):
304 """! Wiggles the fingers. @see sweep()""" 307 servowrite (sweep ([CANCEL_SIGNAL,4,0,3,0,2,0,1,th], [5], [0], [n], [step]), delay)
309 servowrite (sweep ([], [5,4], [n,0], [0,n], [step,step]), delay)
310 servowrite (sweep ([], [4,3], [n,0], [0,n], [step,step]), delay)
311 servowrite (sweep ([], [3,2], [n,0], [0,n], [step,step]), delay)
312 servowrite (sweep ([], [2,1], [n,th], [0,n+th], [step] * 2), delay)
313 servowrite (sweep ([], [1], [n+th], [0], [step]), delay)
314 servowrite (sweep ([], [2,1], [0,th+n], [n,th], [step] * 2), delay)
315 servowrite (sweep ([], [3,2], [0,n], [n,0], [step,step]), delay)
316 servowrite (sweep ([], [4,3], [0,n], [n,0], [step,step]), delay)
317 servowrite (sweep ([], [5,4], [0,n], [n,0], [step,step]), delay)
319 servowrite (sweep ([], [5], [n], [0], [step]), delay)
322 """! Counts to 5 on the fingers. @see sweep()""" 323 servowrite (sweep ([CANCEL_SIGNAL,2,0], [1,3,4,5], [0] * 4, [180] * 4, [10] * 4), 0.005)
324 servowrite (sweep ([], [3], [180], [0], [10]), 0.02)
325 servowrite (sweep ([], [4], [180], [0], [10]), 0.02)
326 servowrite (sweep ([], [5], [180], [0], [10]), 0.02)
327 servowrite (sweep ([], [1], [180], [0], [10]), 0.02)
330 """! Performs all movements.""" 347 fd = sys.stdin.fileno()
348 old_settings = termios.tcgetattr(fd)
351 ch = sys.stdin.read(1)
353 termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
376 """! Calibrate a servo. 377 Takes one argument, which is the id of a server. @ref index has the servo 380 Use the left and right arrow keys to adjust the value of the servo. Use any 383 Enter the maximum values into the @ref limit array in your settings file. 385 Note that if a servo isn't moving the correct way, for example if a finger 386 isn't flat at 0 and curved at 180, you must set @ref reverse to 1 at the 392 ser.write ([255, s, i])
394 if arrow ==
'up' or arrow ==
'right':
397 elif arrow ==
'down' or arrow ==
'left':
403 def calibrate_all ():
405 for i
in range (1, 6):
def connect(port)
Sets the global ser variable.
def reset()
Immediately sets the servos to 0.
def demo()
Performs all movements.
def ok(delay=0.01)
Makes an ok sign.
def unsweep(servos, ends, steps)
Produces a command chain that resets all servos to 0.
def wiggle(n=90, delay=0.01, wiggles=1)
Wiggles the fingers.
def rockon(delay=0.01)
Makes a rock on sign.
def peace(delay=0)
Makes a peace sign.
def cmd()
Sends the input to the serial port until a blank line is given.
def grab(delay=0.02)
Makes a fist.
def gesture(initial, servos, starts, ends, steps, delay)
Sets the servos to a position, waits for input, then resets them to 0.
def count()
Counts to 5 on the fingers.
def dump(servos=6)
Retrieves information about the board.
def servowrite(commands, delay)
Writes commands to the serial port.
def calibrate(s=1)
Calibrate a servo.
def sweep(initial, servos, starts, ends, steps)
Produces complex command chains.