<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-gb">
<link rel="self" type="application/atom+xml" href="http://forum.robosavvy.com/feed.php?f=5&amp;t=8080" />

<title>RoboSavvy Forum</title>
<subtitle>Robosavvy Forum: The largest online community of Humanoid Robot Builders</subtitle>
<link href="http://forum.robosavvy.com/index.php" />
<updated>2012-07-13T22:46:44+01:00</updated>

<author><name><![CDATA[RoboSavvy Forum]]></name></author>
<id>http://forum.robosavvy.com/feed.php?f=5&amp;t=8080</id>
<entry>
<author><name><![CDATA[wolf]]></name></author>
<updated>2012-07-13T22:46:44+01:00</updated>
<published>2012-07-13T22:46:44+01:00</published>
<id>http://forum.robosavvy.com/viewtopic.php?t=8080&amp;p=34819#p34819</id>
<link href="http://forum.robosavvy.com/viewtopic.php?t=8080&amp;p=34819#p34819"/>
<title type="html"><![CDATA[Random failures on servo commands (Mac OS Lion w/ Python)]]></title>

<content type="html" xml:base="http://forum.robosavvy.com/viewtopic.php?t=8080&amp;p=34819#p34819"><![CDATA[
Hello everyone, <br /><br />I'm working on getting my Bioloid GP robot working to interface with Python code. Currently it works, but not consistently. The write out commands to the servo don't consistently produce movement. I've put it in a loop until the command does take, but it's not a useable solution. <br />Has anyone run into this before? I'm in Python using the PySerial module to communicate with AX-12A servos. Here's the code! Based on code from Mac Mason<br /><br /><dl class="codebox"><dt>Code: </dt><dd><code>import sys<br />import serial <br />import time<br /><br /># The types of packets.<br />PING       = &#91;0x01&#93;<br />READ_DATA  = &#91;0x02&#93;<br />WRITE_DATA = &#91;0x03&#93;<br />REG_WRITE  = &#91;0x04&#93;<br />ACTION     = &#91;0x05&#93;<br />RESET      = &#91;0x06&#93;<br />SYNC_WRITE = &#91;0x83&#93;<br /><br /># The various errors that might take place.<br />ERRORS = &#123;64 : &quot;Instruction&quot;,<br />          32 : &quot;Overload&quot;,<br />          16 : &quot;Checksum&quot;,<br />           8 : &quot;Range&quot;,<br />           4 : &quot;Overheating&quot;,<br />           2 : &quot;AngleLimit&quot;,<br />           1 : &quot;InputVoltage&quot;&#125;<br /><br />def _Checksum&#40;s&#41;:<br />  &quot;&quot;&quot;Calculate the Dynamixel checksum &#40;~&#40;ID + length + ...&#41;&#41; &amp; 0xFF.&quot;&quot;&quot;<br />  return &#40;~sum&#40;s&#41;&#41; &amp; 0xFF<br /><br />def _VerifyID&#40;id&#41;:<br />  &quot;&quot;&quot;<br />  Just make sure the id is valid.<br />  &quot;&quot;&quot;<br />  if not &#40;0 &lt;= id &lt;= 0xFD&#41;:<br />    raise ValueError, &quot;ID %d isn't legal!&quot; % id<br /><br />def _EnWire&#40;v&#41;:<br />  &quot;&quot;&quot;<br />  Convert an int to the on-wire &#40;little-endian&#41; format. Actually returns the<br />  list &#91;lsbyte, msbyte&#93;. Of course, this is only useful for the 16-bit<br />  quantities we need to deal with.<br />  &quot;&quot;&quot;<br />  if not 0 &lt;= v &lt;1023&gt;&gt; 8&#93;<br /><br />def _DeWire&#40;v&#41;:<br />  &quot;&quot;&quot;<br />  Invert EnWire. v should be the list &#91;lsbyte, msbyte&#93;.<br />  &quot;&quot;&quot;<br />  return &#40;v&#91;1&#93; &lt;&lt;8&gt; 0:<br />        res.append&#40;self.port.read&#40;&#41;&#41;<br />      count += 1<br />      print count<br />    return Response&#40;map&#40;ord, res&#41;&#41;.Verify&#40;&#41;<br /><br />  # From here on out, you're looking at functions that really do something to<br />  # the servo itself. You should look at the user manual for details on what<br />  # all of these mean, although most are self-explanatory.<br />  def Reset&#40;self, id&#41;:<br />    &quot;&quot;&quot;<br />    Perform a reset on the servo. Note that this will reset the ID to 1, which<br />    could be messy if you have many servos plugged in.<br />    &quot;&quot;&quot;<br />    _VerifyID&#40;id&#41;<br />    self.Interact&#40;id, RESET&#41;.Verify&#40;&#41;<br /><br />  def GetPosition&#40;self, id&#41;:<br />    &quot;&quot;&quot;<br />    Return the current position of the servo. See the user manual, page 16,<br />    for what the return value means.<br />    &quot;&quot;&quot;<br />    _VerifyID&#40;id&#41;<br />    packet = READ_DATA + &#91;0x24&#93; + &#91;2&#93;<br />    res = self.Interact&#40;id, packet&#41;.Verify&#40;&#41;<br />    if len&#40;res.parameters&#41; != 2:<br />      raise ValueError, &quot;GetPosition didn't get two parameters!&quot;<br />    return _DeWire&#40;res.parameters&#41;<br /><br />  def GetPositionDegrees&#40;self, id&#41;:<br />    &quot;&quot;&quot;<br />    If you'd rather work in degrees, use this one. Again, see the user manual,<br />    page 16, for details.<br />    &quot;&quot;&quot;<br />    return self.GetPosition&#40;id&#41; * &#40;300.0 / 1023.0&#41;<br /><br />  def SetPosition&#40;self, id, position&#41;:<br />    &quot;&quot;&quot;<br />    Set servo id to be at position position. See the user manual, page 16, for<br />    how this works. This just sends the set position packet; the servo won't<br />    necessarily go where you told it. You can use GetPosition to figure out<br />    where it actually went.<br />    &quot;&quot;&quot;<br />    _VerifyID&#40;id&#41;<br />    if not &#40;0 &lt;= position &lt;= 1023&#41;:<br />      raise ValueError, &quot;Invalid position!&quot;<br />    packet = WRITE_DATA + &#91;0x1e&#93; + _EnWire&#40;position&#41;<br />    self.Interact&#40;id, packet&#41;.Verify&#40;&#41;<br /><br />  def SetPositionDegrees&#40;self, id, deg&#41;:<br />    &quot;&quot;&quot;<br />    Set the position in degrees, according to the diagram in the manual on<br />    page 16.<br />    &quot;&quot;&quot;<br />    if not 0 &lt;= deg &lt;= 300:<br />      raise ValueError, &quot;%d is not a valid angle!&quot; % deg<br />    self.SetPosition&#40;id, int&#40;1023.0/300 * deg&#41;&#41;<br /><br />  def SetID&#40;self, id, nid&#41;:<br />    &quot;&quot;&quot;<br />    Change the ID of a servo. Note that this is persistent; you may also be<br />    interested in Reset&#40;&#41;.<br />    &quot;&quot;&quot;<br />    _VerifyID&#40;id&#41;<br />    if not 0 &lt;= nid &lt;= 253:<br />      raise ValueError, &quot;%id is not a valid servo ID!&quot; % nid<br />    packet = WRITE_DATA + &#91;0x03&#93; + &#91;nid&#93;<br />    self.Interact&#40;id, packet&#41;.Verify&#40;&#41;<br />  <br />  def GetMovingSpeed&#40;self, id&#41;:<br />    &quot;&quot;&quot;<br />    Get the moving speed. 0 means &quot;unlimited&quot;.<br />    &quot;&quot;&quot;<br />    _VerifyID&#40;id&#41;<br />    packet = READ_DATA + &#91;0x20&#93; + &#91;2&#93;<br />    Q = self.Interact&#40;id, packet&#41;.Verify&#40;&#41;<br />    if len&#40;Q.parameters&#41; != 2:<br />      raise ValueError, &quot;GetMovingSpeed has the wrong return shape!&quot;<br />    return _DeWire&#40;Q.parameters&#41;<br /><br />  def SetMovingSpeed&#40;self, id, speed&#41;:<br />    &quot;&quot;&quot;<br />    Set the moving speed. 0 means &quot;unlimited&quot;, so the servo will move as fast<br />    as it can.<br />    &quot;&quot;&quot;<br />    _VerifyID&#40;id&#41;<br />    if not 0 &lt;= speed &lt;= 1023:<br />      raise ValueError, &quot;%d is not a valid moving speed!&quot; % speed<br />    packet = WRITE_DATA + &#91;0x20&#93; + _EnWire&#40;speed&#41;<br />    self.Interact&#40;id, packet&#41;.Verify&#40;&#41;<br /><br />  def Moving&#40;self, id&#41;:<br />    &quot;&quot;&quot;<br />    Return True if the servo is currently moving, False otherwise.<br />    &quot;&quot;&quot;<br />    _VerifyID&#40;id&#41;<br />    packet = READ_DATA + &#91;0x2e&#93; + &#91;1&#93;<br />    Q = self.Interact&#40;id, packet&#41;.Verify&#40;&#41;<br />    return Q.parameters&#91;0&#93; == 1<br /><br />  def WaitUntilStopped&#40;self, id&#41;:<br />    &quot;&quot;&quot;<br />    Spinlock until the servo has stopped moving.<br />    &quot;&quot;&quot;<br />    while self.Moving&#40;id&#41;:<br />      pass<br /><br /># Handy for interactive testing.<br />if __name__ == &quot;__main__&quot;:<br />  if len&#40;sys.argv&#41; != 1:  # Specifying a port for interactive use<br />    ps = sys.argv&#91;1&#93;<br />  else:<br />    ps = &quot;/dev/cu.usbserial-A4008bbH&quot;<br />  X = ServoController&#40;ps&#41;<br />  X.SetPosition&#40;7,512&#41; # Set servo ID 1 to position 512 &#40;straight up&#41;<br />  X.WaitUntilStopped&#40;7&#41;<br />  X.SetPosition&#40;7,1&#41;<br />  #X.SetPosition&#40;8,1023&#41;<br /></code></dd></dl><br /><br />Any help or insight would be greatly appreciatated!<p>Statistics: Posted by <a href="http://forum.robosavvy.com/memberlist.php?mode=viewprofile&amp;u=3466">wolf</a> — Fri Jul 13, 2012 10:46 pm</p><hr />
]]></content>
</entry>
</feed>