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 speed > 1023:
00381 speed = 1023
00382 if direction == self.FORWARD:
00383
00384 self.write(index, P_GOAL_SPEED_L, [speed%256, speed>>8])
00385 else:
00386
00387 speed += 1024
00388 self.write(index, P_GOAL_SPEED_L, [speed%256, speed>>8])
00389
00390
00391
00392
00393
00394 LOW = 0
00395
00396 HIGH = 0xff
00397
00398 INPUT = 0
00399
00400 OUTPUT = 0xff
00401
00402
00403
00404
00405 REG_DIGITAL_IN0 = 5
00406 REG_DIGITAL_IN1 = 6
00407 REG_DIGITAL_IN2 = 7
00408 REG_DIGITAL_IN3 = 8
00409
00410 REG_RESCAN = 15
00411
00412
00413
00414 ANA_BASE = 18
00415
00416
00417 SERVO_BASE = 26
00418
00419 REG_DIGITAL_OUT0 = 47
00420
00421
00422 def rescan(self):
00423 self.write(253, self.REG_RESCAN, [1,])
00424
00425
00426
00427
00428
00429
00430 def getAnalog(self, index):
00431 try:
00432 return int(self.read(253, self.ANA_BASE+int(index), 1)[0])
00433 except:
00434 return -1
00435
00436
00437
00438
00439
00440
00441 def getDigital(self, index):
00442 try:
00443 if index < 32:
00444 x = self.read(253, self.REG_DIGITAL_IN0 + int(index/8), 1)[0]
00445 else:
00446 return -1
00447 except:
00448 return -1
00449 if x & (2**(index%8)):
00450 return 255
00451 else:
00452 return 0
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 def setDigital(self, index, value, direction=0xff):
00464 if index > 31: return -1
00465 if value == 0 and direction > 0:
00466 self.write(253, self.REG_DIGITAL_OUT0 + int(index), [1])
00467 elif value > 0 and direction > 0:
00468 self.write(253, self.REG_DIGITAL_OUT0 + int(index), [3])
00469 elif value > 0 and direction == 0:
00470 self.write(253, self.REG_DIGITAL_OUT0 + int(index), [2])
00471 else:
00472 self.write(253, self.REG_DIGITAL_OUT0 + int(index), [0])
00473 return 0
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 def setServo(self, index, value):
00484 if index > 7: return -1
00485 if value != 0 and (value < 500 or value > 2500):
00486 print "ArbotiX Error: Servo value out of range:",val
00487 else:
00488 self.write(253, self._SERVO_BASE + 2*index, [value%256, value>>8])
00489 return 0
00490