00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 import serial, time, sys, thread
00034 from ax12 import *
00035 from struct import unpack
00036
00037
00038 class ArbotiX:
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 def __init__(self, port="/dev/ttyUSB0",baud=115200, timeout = 0.1):
00049 self._mutex = thread.allocate_lock()
00050 self._ser = serial.Serial()
00051
00052 self._ser.baudrate = baud
00053 self._ser.port = port
00054 self._ser.timeout = timeout
00055 self._ser.open()
00056
00057
00058 self.error = 0
00059
00060
00061
00062
00063
00064
00065 def getPacket(self, mode, id=-1, leng=-1, error=-1, params = None):
00066 try:
00067 d = self._ser.read()
00068 except Exception as e:
00069 print e
00070 return None
00071
00072 if d == '':
00073 return None
00074
00075
00076 if mode == 0:
00077 if ord(d) == 0xff:
00078 return self.getPacket(1)
00079 else:
00080 return self.getPacket(0)
00081 elif mode == 1:
00082 if ord(d) == 0xff:
00083 return self.getPacket(2)
00084 else:
00085 return self.getPacket(0)
00086 elif mode == 2:
00087 if d != 0xff:
00088 return self.getPacket(3, ord(d))
00089 else:
00090 return self.getPacket(0)
00091 elif mode == 3:
00092 return self.getPacket(4, id, ord(d))
00093 elif mode == 4:
00094 self.error = ord(d)
00095 if leng == 2:
00096 return self.getPacket(6, id, leng, ord(d), list())
00097 else:
00098 return self.getPacket(5, id, leng, ord(d), list())
00099 elif mode == 5:
00100 params.append(ord(d))
00101 if len(params) + 2 == leng:
00102 return self.getPacket(6, id, leng, error, params)
00103 else:
00104 return self.getPacket(5, id, leng, error, params)
00105 elif mode == 6:
00106 checksum = id + leng + error + sum(params) + ord(d)
00107 if checksum % 256 != 255:
00108 return None
00109 return params
00110
00111 return None
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 def execute(self, index, ins, params, ret=True):
00125 values = None
00126 self._mutex.acquire()
00127 try:
00128 self._ser.flushInput()
00129 except Exception as e:
00130 print e
00131 length = 2 + len(params)
00132 checksum = 255 - ((index + length + ins + sum(params))%256)
00133 try:
00134 self._ser.write(chr(0xFF)+chr(0xFF)+chr(index)+chr(length)+chr(ins))
00135 except Exception as e:
00136 print e
00137 self._mutex.release()
00138 return None
00139 for val in params:
00140 try:
00141 self._ser.write(chr(val))
00142 except Exception as e:
00143 print e
00144 self._mutex.release()
00145 return None
00146 try:
00147 self._ser.write(chr(checksum))
00148 except Exception as e:
00149 print e
00150 self._mutex.release()
00151 return None
00152 if ret:
00153 values = self.getPacket(0)
00154 self._mutex.release()
00155 return values
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 def read(self, index, start, length):
00167 values = self.execute(index, AX_READ_DATA, [start, length])
00168 if values == None:
00169 return -1
00170 else:
00171 return values
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 def write(self, index, start, values):
00183 self.execute(index, AX_WRITE_DATA, [start] + values)
00184 return self.error
00185
00186
00187
00188
00189
00190
00191
00192 def syncWrite(self, start, values):
00193 output = list()
00194 for i in values:
00195 output = output + i
00196 length = len(output) + 4
00197 lbytes = len(values[0])-1
00198 self._mutex.acquire()
00199 try:
00200 self._ser.flushInput()
00201 except:
00202 pass
00203 self._ser.write(chr(0xFF)+chr(0xFF)+chr(254)+chr(length)+chr(AX_SYNC_WRITE))
00204 self._ser.write(chr(start))
00205 self._ser.write(chr(lbytes))
00206 for i in output:
00207 self._ser.write(chr(i))
00208 checksum = 255 - ((254 + length + AX_SYNC_WRITE + start + lbytes + sum(output))%256)
00209 self._ser.write(chr(checksum))
00210 self._mutex.release()
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 def syncRead(self, servos, start, length):
00222 return self.execute(0xFE, AX_SYNC_READ, [start, length] + servos )
00223
00224
00225
00226
00227
00228
00229
00230
00231 def setBaud(self, index, baud):
00232 return self.write(index, P_BAUD_RATE, [baud, ])
00233
00234
00235
00236
00237
00238
00239 def getReturnLevel(self, index):
00240 try:
00241 return int(self.read(index, P_RETURN_LEVEL, 1)[0])
00242 except:
00243 return -1
00244
00245
00246
00247
00248
00249
00250
00251
00252 def setReturnLevel(self, index, value):
00253 return self.write(index, P_RETURN_LEVEL, [value])
00254
00255
00256
00257
00258
00259
00260 def enableTorque(self, index):
00261 return self.write(index, P_TORQUE_ENABLE, [1])
00262
00263
00264
00265
00266
00267
00268 def disableTorque(self, index):
00269 return self.write(index, P_TORQUE_ENABLE, [0])
00270
00271
00272
00273
00274
00275
00276
00277
00278 def setLed(self, index, value):
00279 return self.write(index, P_LED, [value])
00280
00281
00282
00283
00284
00285
00286
00287
00288 def setPosition(self, index, value):
00289 return self.write(index, P_GOAL_POSITION_L, [value%256, value>>8])
00290
00291
00292
00293
00294
00295
00296
00297
00298 def setSpeed(self, index, value):
00299 return self.write(index, P_GOAL_SPEED_L, [value%256, value>>8])
00300
00301
00302
00303
00304
00305
00306 def getPosition(self, index):
00307 values = self.read(index, P_PRESENT_POSITION_L, 2)
00308 try:
00309 return int(values[0]) + (int(values[1])<<8)
00310 except:
00311 return -1
00312
00313
00314
00315
00316
00317
00318 def getVoltage(self, index):
00319 try:
00320 return int(self.read(index, P_PRESENT_VOLTAGE, 1)[0])/10.0
00321 except:
00322 return -1
00323
00324
00325
00326
00327
00328
00329 def getTemperature(self, index):
00330 try:
00331 return int(self.read(index, P_PRESENT_TEMPERATURE, 1)[0])
00332 except:
00333 return -1
00334
00335
00336
00337
00338
00339
00340 def isMoving(self, index):
00341 try:
00342 d = self.read(index, P_MOVING, 1)[0]
00343 except:
00344 return True
00345 return d != 0
00346
00347
00348
00349
00350 def enableWheelMode(self, index):
00351 self.write(index, P_CCW_ANGLE_LIMIT_L, [0,0])
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 def disableWheelMode(self, index, resolution=10):
00362 resolution = (2 ** resolution) - 1
00363 self.write(index, P_CCW_ANGLE_LIMIT_L, [resolution%256,resolution>>8])
00364
00365
00366 FORWARD = 0
00367
00368 BACKWARD = 1
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 def setWheelSpeed(self, index, direction, speed):
00380 if direction == self.FORWARD:
00381
00382 self.write(index, P_GOAL_SPEED_L, [speed%256, speed>>8])
00383 else:
00384
00385 speed += 1024
00386 self.write(index, P_GOAL_SPEED_L, [speed%256, speed>>8])
00387
00388
00389
00390
00391
00392 LOW = 0
00393
00394 HIGH = 0xff
00395
00396 INPUT = 0
00397
00398 OUTPUT = 0xff
00399
00400
00401
00402
00403 DIG_BASE = 5
00404
00405 REG_RESCAN = 15
00406
00407
00408
00409 ANA_BASE = 18
00410
00411
00412 SERVO_BASE = 26
00413
00414
00415
00416 def rescan(self):
00417 self.write(253, self.REG_RESCAN, [1,])
00418
00419
00420
00421
00422
00423
00424 def getAnalog(self, index):
00425 try:
00426 return int(self.read(253, self.ANA_BASE+int(index), 1)[0])
00427 except:
00428 return -1
00429
00430
00431
00432
00433
00434
00435 def getDigital(self, index):
00436 try:
00437 if index > 15:
00438 x = self.read(253, self.DIG_BASE+2, 1)[0]
00439 elif index > 7:
00440 x = self.read(253, self.DIG_BASE+1, 1)[0]
00441 else:
00442 x = self.read(253, self.DIG_BASE, 1)[0]
00443 except:
00444 return -1
00445 if x & (2**(index%8)):
00446 return 255
00447 else:
00448 return 0
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 def setDigital(self, index, value, direction=0xff):
00461 if index > 7: return -1
00462 if value == 0 and direction > 0:
00463 self.write(253, self.DIG_BASE + int(index), [1])
00464 elif value > 0 and direction > 0:
00465 self.write(253, self.DIG_BASE + int(index), [3])
00466 elif value > 0 and direction == 0:
00467 self.write(253, self.DIG_BASE + int(index), [2])
00468 else:
00469 self.write(253, self.DIG_BASE + int(index), [0])
00470 return 0
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 def setServo(self, index, value):
00481 if index > 7: return -1
00482 if value != 0 and (value < 500 or value > 2500):
00483 print "ArbotiX Error: Servo value out of range:",val
00484 else:
00485 self.write(253, self._serVO_BASE + 2*index, [value%256, value>>8])
00486 return 0
00487