]> pere.pagekite.me Git - homepage.git/blobdiff - blog/tags/robot/index.html
New post on the Debian handbook.
[homepage.git] / blog / tags / robot / index.html
index 5fcdf6d56013de273d419114c85252631aa8da3b..04abc75fc12bfef49450775ac4d07713c3073f4b 100644 (file)
 
     <h3>Entries tagged "robot".</h3>
     
+    <div class="entry">
+      <div class="title">
+        <a href="https://people.skolelinux.org/pere/blog/Automatic_LinuxCNC_servo_PID_tuning_.html">Automatic LinuxCNC servo PID tuning?</a>
+      </div>
+      <div class="date">
+        16th July 2022
+      </div>
+      <div class="body">
+        <p>While working on a CNC with servo motors controlled by the
+<a href="https://en.wikipedia.org/wiki/LinuxCNC">LinuxCNC</a>
+<a href="https://en.wikipedia.org/wiki/PID_controller">PID
+controller</a>, I recently had to learn how to tune the collection of values
+that control such mathematical machinery that a PID controller is.  It
+proved to be a lot harder than I hoped, and I still have not succeeded
+in getting the Z PID controller to successfully defy gravity, nor X
+and Y to move accurately and reliably.  But while climbing up this
+rather steep learning curve, I discovered that some motor control
+systems are able to tune their PID controllers.  I got the impression
+from the documentation that LinuxCNC were not.  This proved to be not
+true</p>
+
+<p>The LinuxCNC
+<a href="http://linuxcnc.org/docs/html/man/man9/pid.9.html">pid
+component</a> is the recommended PID controller to use.  It uses eight
+constants <tt>Pgain</tt>, <tt>Igain</tt>, <tt>Dgain</tt>,
+<tt>bias</tt>, <tt>FF0</tt>, <tt>FF1</tt>, <tt>FF2</tt> and
+<tt>FF3</tt> to calculate the output value based on current and wanted
+state, and all of these need to have a sensible value for the
+controller to behave properly.  Note, there are even more values
+involved, theser are just the most important ones.  In my case I need
+the X, Y and Z axes to follow the requested path with little error.
+This has proved quite a challenge for someone who have never tuned a
+PID controller before, but there is at least some help to be found.
+
+<p>I discovered that included in LinuxCNC was this old PID component
+at_pid claiming to have auto tuning capabilities.  Sadly it had been
+neglected since 2011, and could not be used as a plug in replacement
+for the default pid component.  One would have to rewriting the
+LinuxCNC HAL setup to test at_pid.  This was rather sad, when I wanted
+to quickly test auto tuning to see if it did a better job than me at
+figuring out good P, I and D values to use.</p>
+
+<p>I decided to have a look if the situation could be improved.  This
+involved trying to understand the code and history of the pid and
+at_pid components.  Apparently they had a common ancestor, as code
+structure, comments and variable names were quite close to each other.
+Sadly this was not reflected in the git history, making it hard to
+figure out what really happened.  My guess is that the author of
+<a href="https://github.com/LinuxCNC/linuxcnc/blob/master/src/hal/components/at_pid.c">at_pid.c</a>
+took a version of
+<a href="https://github.com/LinuxCNC/linuxcnc/blob/master/src/hal/components/pid.c">pid.c</a>,
+rewrote it to follow the structure he wished pid.c to have, then added
+support for auto tuning and finally got it included into the LinuxCNC
+repository.  The restructuring and lack of early history made it
+harder to figure out which part of the code were relevant to the auto
+tuning, and which part of the code needed to be updated to work the
+same way as the current pid.c implementation.  I started by trying to
+isolate relevant changes in pid.c, and applying them to at_pid.c.  My
+aim was to make sure the at_pid component could replace the pid
+component with a simple change in the HAL setup loadrt line, without
+having to "rewire" the rest of the HAL configuration.  After a few
+hours following this approach, I had learned quite a lot about the
+code structure of both components, while concluding I was heading down
+the wrong rabbit hole, and should get back to the surface and find a
+different path.</p>
+
+<p>For the second attempt, I decided to throw away all the PID control
+related part of the original at_pid.c, and instead isolate and lift
+the auto tuning part of the code and inject it into a copy of pid.c.
+This ensured compatibility with the current pid component, while
+adding auto tuning as a run time option.  To make it easier to identify
+the relevant parts in the future, I wrapped all the auto tuning code
+with '#ifdef AUTO_TUNER'.  The end result behave just like the current
+pid component by default, as that part of the code is identical.  The
+<a href="https://github.com/LinuxCNC/linuxcnc/pull/1820">end result
+entered the LinuxCNC master branch</a> a few days ago.</p>
+
+<p>To enable auto tuning, one need to set a few HAL pins in the PID
+component.  The most important ones are <tt>tune-effort</tt>,
+<tt>tune-mode</tt> and <tt>tune-start</tt>.  But lets take a step
+back, and see what the auto tuning code will do.  I do not know the
+mathematical foundation of the at_pid algorithm, but from observation
+I can tell that the algorithm will, when enabled, produce a square
+wave pattern centered around the <tt>bias</tt> value on the output pin
+of the PID controller.  This can be seen using the HAL Scope provided
+by LinuxCNC.  In my case, this is translated into voltage (+-10V) sent
+to the motor controller, which in turn is translated into motor speed.
+So at_pid will ask the motor to move the axis back and forth.  The
+number of cycles in the pattern is controlled by the
+<tt>tune-cycles</tt> pin, and the extremes of the wave pattern is
+controlled by the <tt>tune-effort</tt> pin.  Of course, trying to
+change the direction of a physical object instantly (as in going
+directly from a positive voltage to the equivalent negative voltage)
+do not change velocity instantly, and it take some time for the object
+to slow down and move in the opposite direction.  This result in a
+more smooth movement wave form, as the axis in question were vibrating
+back and forth.  When the axis reached the target speed in the
+opposing direction, the auto tuner change direction again.  After
+several of these changes, the average time delay between the 'peaks'
+and 'valleys' of this movement graph is then used to calculate
+proposed values for Pgain, Igain and Dgain, and insert them into the
+HAL model to use by the pid controller.  The auto tuned settings are
+not great, but htye work a lot better than the values I had been able
+to cook up on my own, at least for the horizontal X and Y axis.  But I
+had to use very small <tt>tune-effort<tt> values, as my motor
+controllers error out if the voltage change too quickly.  I've been
+less lucky with the Z axis, which is moving a heavy object up and
+down, and seem to confuse the algorithm.  The Z axis movement became a
+lot better when I introduced a <tt>bias</tt> value to counter the
+gravitational drag, but I will have to work a lot more on the Z axis
+PID values.</p>
+
+<p>Armed with this knowledge, it is time to look at how to do the
+tuning.  Lets say the HAL configuration in question load the PID
+component for X, Y and Z like this:</p>
+<blockquote><pre>
+loadrt pid names=pid.x,pid.y,pid.z
+</pre></blockquote>
+
+<p>Armed with the new and improved at_pid component, the new line will
+look like this:</p>
+
+<blockquote><pre>
+loadrt at_pid names=pid.x,pid.y,pid.z
+</pre></blockquote>
+
+<p>The rest of the HAL setup can stay the same.  This work because the
+components are referenced by name.  If the component had used count=3
+instead, all use of pid.# had to be changed to at_pid.#.</p>
+
+<p>To start tuning the X axis, move the axis to the middle of its
+range, to make sure it do not hit anything when it start moving back
+and forth.  Next, set the <tt>tune-effort</tt> to a low number in the
+output range.  I used 0.1 as my initial value.  Next, assign 1 to the
+<tt>tune-mode</tt> value. Note, this will disable the pid controlling
+part and feed 0 to the output pin, which in my case initially caused a
+lot of drift.  In my case it proved to be a good idea with X and Y to
+tune the motor driver to make sure 0 voltage stopped the motor
+rotation.  On the other hand, for the Z axis this proved to be a bad
+idea, so it will depend on your setup.  It might help to set the
+<tt>bias</tt> value to a output value that reduce or eliminate the
+axis drift.  Finally, after setting <tt>tune-mode</tt>, set
+<tt>tune-start</tt> to 1 to activate the auto tuning.  If all go well,
+your axis will vibrate for a few seconds and when it is done, new
+values for Pgain, Igain and Dgain will be active.  To test them,
+change <tt>tune-mode</tt> back to 0.  Note that this might cause the
+machine to suddenly jerk as it bring the axis back to its commanded
+position, which it might have drifted away from during tuning.  To
+summarize with some halcmd lines:</p>
+
+<blockquote><pre>
+setp pid.x.tune-effort 0.1
+setp pid.x.tune-mode 1
+setp pid.x.tune-start 1
+# wait for the tuning to complete
+setp pid.x.tune-mode 0
+</pre></blockquote>
+
+<p>After doing this task quite a few times while trying to figure out
+how to properly tune the PID controllers on the machine in, I decided
+to figure out if this process could be automated, and wrote a script
+to do the entire tuning process from power on.  The end result will
+ensure the machine is powered on and ready to run, home all axis if it
+is not already done, check that the extra tuning pins are available,
+move the axis to its mid point, run the auto tuning and re-enable the
+pid controller when it is done.  It can be run several times.  Check
+out the
+<a href="https://github.com/SebKuzminsky/MazakVQC1540/blob/bon-dev/scripts/run-auto-pid-tuner">run-auto-pid-tuner</a>
+script on github if you want to learn how it is done.</p>
+
+<p>My hope is that this little adventure can inspire someone who know
+more about motor PID controller tuning can implement even better
+algorithms for automatic PID tuning in LinuxCNC, making life easier
+for both me and all the others that want to use LinuxCNC but lack the
+in depth knowledge needed to tune PID controllers well.</p>
+
+<p>As usual, if you use Bitcoin and want to show your support of my
+activities, please send Bitcoin donations to my address
+<b><a href="bitcoin:15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b">15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b</a></b>.</p>
+
+      </div>
+      <div class="tags">
+        
+        
+        Tags: <a href="https://people.skolelinux.org/pere/blog/tags/3d-printer">3d-printer</a>, <a href="https://people.skolelinux.org/pere/blog/tags/debian">debian</a>, <a href="https://people.skolelinux.org/pere/blog/tags/english">english</a>, <a href="https://people.skolelinux.org/pere/blog/tags/robot">robot</a>.
+        
+        
+      </div>
+    </div>
+    <div class="padding"></div>
+    
     <div class="entry">
       <div class="title">
         <a href="https://people.skolelinux.org/pere/blog/LinuxCNC_translators_life_just_got_a_bit_easier.html">LinuxCNC translators life just got a bit easier</a>
@@ -826,6 +1018,8 @@ firmwaren. :)</p>
 
 <li><a href="https://people.skolelinux.org/pere/blog/archive/2022/06/">June (2)</a></li>
 
+<li><a href="https://people.skolelinux.org/pere/blog/archive/2022/07/">July (1)</a></li>
+
 </ul></li>
 
 <li>2021
@@ -1201,7 +1395,7 @@ firmwaren. :)</p>
 <h2>Tags</h2>
 <ul>
 
- <li><a href="https://people.skolelinux.org/pere/blog/tags/3d-printer">3d-printer (18)</a></li>
+ <li><a href="https://people.skolelinux.org/pere/blog/tags/3d-printer">3d-printer (19)</a></li>
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/amiga">amiga (1)</a></li>
 
@@ -1219,7 +1413,7 @@ firmwaren. :)</p>
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/chrpath">chrpath (2)</a></li>
 
- <li><a href="https://people.skolelinux.org/pere/blog/tags/debian">debian (180)</a></li>
+ <li><a href="https://people.skolelinux.org/pere/blog/tags/debian">debian (181)</a></li>
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/debian edu">debian edu (159)</a></li>
 
@@ -1233,7 +1427,7 @@ firmwaren. :)</p>
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/drivstoffpriser">drivstoffpriser (4)</a></li>
 
- <li><a href="https://people.skolelinux.org/pere/blog/tags/english">english (436)</a></li>
+ <li><a href="https://people.skolelinux.org/pere/blog/tags/english">english (437)</a></li>
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/fiksgatami">fiksgatami (23)</a></li>
 
@@ -1295,7 +1489,7 @@ firmwaren. :)</p>
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/rfid">rfid (3)</a></li>
 
- <li><a href="https://people.skolelinux.org/pere/blog/tags/robot">robot (15)</a></li>
+ <li><a href="https://people.skolelinux.org/pere/blog/tags/robot">robot (16)</a></li>
 
  <li><a href="https://people.skolelinux.org/pere/blog/tags/rss">rss (1)</a></li>