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 getSpeed(self, index):
00319 values = self.read(index, P_PRESENT_SPEED_L, 2)
00320 try:
00321 return int(values[0]) + (int(values[1])<<8)
00322 except:
00323 return -1
00324
00325
00326
00327
00328
00329
00330 def getGoalSpeed(self, index):
00331 values = self.read(index, P_GOAL_SPEED_L, 2)
00332 try:
00333 return int(values[0]) + (int(values[1])<<8)
00334 except:
00335 return -1
00336
00337
00338
00339
00340
00341
00342 def getVoltage(self, index):
00343 try:
00344 return int(self.read(index, P_PRESENT_VOLTAGE, 1)[0])/10.0
00345 except:
00346 return -1
00347
00348
00349
00350
00351
00352
00353 def getTemperature(self, index):
00354 try:
00355 return int(self.read(index, P_PRESENT_TEMPERATURE, 1)[0])
00356 except:
00357 return -1
00358
00359
00360
00361
00362
00363
00364 def isMoving(self, index):
00365 try:
00366 d = self.read(index, P_MOVING, 1)[0]
00367 except:
00368 return True
00369 return d != 0
00370
00371
00372
00373
00374 def enableWheelMode(self, index):
00375 self.write(index, P_CCW_ANGLE_LIMIT_L, [0,0])
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 def disableWheelMode(self, index, resolution=10):
00386 resolution = (2 ** resolution) - 1
00387 self.write(index, P_CCW_ANGLE_LIMIT_L, [resolution%256,resolution>>8])
00388
00389
00390 FORWARD = 0
00391
00392 BACKWARD = 1
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 def setWheelSpeed(self, index, direction, speed):
00404 if speed > 1023:
00405 speed = 1023
00406 if direction == self.FORWARD:
00407
00408 self.write(index, P_GOAL_SPEED_L, [speed%256, speed>>8])
00409 else:
00410
00411 speed += 1024
00412 self.write(index, P_GOAL_SPEED_L, [speed%256, speed>>8])
00413
00414
00415
00416
00417
00418 LOW = 0
00419
00420 HIGH = 0xff
00421
00422 INPUT = 0
00423
00424 OUTPUT = 0xff
00425
00426
00427
00428
00429 REG_DIGITAL_IN0 = 5
00430 REG_DIGITAL_IN1 = 6
00431 REG_DIGITAL_IN2 = 7
00432 REG_DIGITAL_IN3 = 8
00433
00434 REG_RESCAN = 15
00435
00436
00437
00438 ANA_BASE = 18
00439
00440
00441 SERVO_BASE = 26
00442
00443 REG_DIGITAL_OUT0 = 47
00444
00445
00446 def rescan(self):
00447 self.write(253, self.REG_RESCAN, [1,])
00448
00449
00450
00451
00452
00453
00454 def getAnalog(self, index):
00455 try:
00456 return int(self.read(253, self.ANA_BASE+int(index), 1)[0])
00457 except:
00458 return -1
00459
00460
00461
00462
00463
00464
00465 def getDigital(self, index):
00466 try:
00467 if index < 32:
00468 x = self.read(253, self.REG_DIGITAL_IN0 + int(index/8), 1)[0]
00469 else:
00470 return -1
00471 except:
00472 return -1
00473 if x & (2**(index%8)):
00474 return 255
00475 else:
00476 return 0
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 def setDigital(self, index, value, direction=0xff):
00488 if index > 31: return -1
00489 if value == 0 and direction > 0:
00490 self.write(253, self.REG_DIGITAL_OUT0 + int(index), [1])
00491 elif value > 0 and direction > 0:
00492 self.write(253, self.REG_DIGITAL_OUT0 + int(index), [3])
00493 elif value > 0 and direction == 0:
00494 self.write(253, self.REG_DIGITAL_OUT0 + int(index), [2])
00495 else:
00496 self.write(253, self.REG_DIGITAL_OUT0 + int(index), [0])
00497 return 0
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 def setServo(self, index, value):
00508 if index > 7: return -1
00509 if value != 0 and (value < 500 or value > 2500):
00510 print "ArbotiX Error: Servo value out of range:",val
00511 else:
00512 self.write(253, self._SERVO_BASE + 2*index, [value%256, value>>8])
00513 return 0
00514