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