<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ZMOTION CONTROLLER</title>
    <description>The latest articles on DEV Community by ZMOTION CONTROLLER (@zmotion_controller).</description>
    <link>https://dev.to/zmotion_controller</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1824099%2Fa0796261-6f5c-4828-9ca9-59e0dca6a857.png</url>
      <title>DEV Community: ZMOTION CONTROLLER</title>
      <link>https://dev.to/zmotion_controller</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zmotion_controller"/>
    <language>en</language>
    <item>
      <title>How to Trigger Signals to do Loading &amp; Unloading?</title>
      <dc:creator>ZMOTION CONTROLLER</dc:creator>
      <pubDate>Tue, 18 Mar 2025 06:50:49 +0000</pubDate>
      <link>https://dev.to/zmotion_controller/how-to-trigger-signals-to-do-loading-unloading-5gpf</link>
      <guid>https://dev.to/zmotion_controller/how-to-trigger-signals-to-do-loading-unloading-5gpf</guid>
      <description>&lt;p&gt;Nowadays, for the manufacturing industry, it needs to develop towards the intelligence, like, 3C electronics, PCB, food packaging, medicine, cosmetics and automotive parts, etc., then in these fields, especially for tiny materials, there is no doubt they are undergoing a transformation in production mode.&lt;/p&gt;

&lt;p&gt;Like, for loading by traditional mechanical vibration disk / single placing / single labeling, they can’t meet high-precision, high-efficiency, and soft production needs of current market.&lt;/p&gt;

&lt;p&gt;In a word, now industry trends to “multi-type &amp;amp; small-bulk customized” production mode from former “single-type with a large amount” mode.&lt;/p&gt;

&lt;p&gt;Today, we mainly talk about &lt;a href="https://www.zmotionglobal.com/support_info_167.html" rel="noopener noreferrer"&gt;“vision fly-shooting loading &amp;amp; unloading with multi-nozzle”&lt;/a&gt; solution.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Technology Brief Introduction of “Multi-Nozzle” Vision Fly-Shooting Loading &amp;amp; Unloading”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Firstly, put materials in the flexible vibration disk, and spread it out through vibration. Then,  roughly recognize, match, and generate OK material coordinates by the third-party vision. At the same time, the machine runs to OK coordinates synchronously, sucking materials through multi-nozzle. Next, in the process of placing material at material disk, it will do  vision fly-shooting to achieve position correction. At last, materials are put into material disk.&lt;/p&gt;

&lt;p&gt;Sometimes, the loading &amp;amp; unloading system needs to process complex material types, such as, it includes packaging materials with smart labels such as QR codes, barcodes, anti-counterfeiting codes, as well as various types of precision electronic components and micro hardware accessories.  Obviously, these kinds of materials need high vision recognition precision, mechanical positioning accuracy, and software flexibility.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj8lmyy7i3miwnlpflmku.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj8lmyy7i3miwnlpflmku.png" alt="Image description" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;common loading &amp;amp; unloading materials&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Common Vision Loading &amp;amp; Unloading Traditional Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffr8ozoct5pgtyo0rlpbs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffr8ozoct5pgtyo0rlpbs.png" alt="Image description" width="539" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Generally, when picking and placing the material, there will be small position offset by manipulator gripper / suction disk, then causing whole placing precision. In order to avoid this problem, an industrial camera is usually used to capture the position of the material being grabbed or sucked during the movement of the workpiece, and to perform position correction.&lt;/p&gt;

&lt;p&gt;If without vision fly-shooting, solution of “IPC + machine vision + PLC + touch screen” is used. And it only can shoot when it stops at fixed position to do position correction, that is, it needs to stop for shooting, then moves again after shot. In this way, waiting time is more obviously, which not only reduces loading &amp;amp; unloading technology efficiency, also affects the capacity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faeernyhto0sm3r8s32v3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faeernyhto0sm3r8s32v3.png" alt="Image description" width="800" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;device V/T of traditional fixed position shooting&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Zmotion Technology Multi-Nozzle Vision Loading &amp;amp; Unloading Solution&lt;br&gt;
According to traditional solution situation, Zmotion develops one  super-high-speed PCIe EtherCAT motion control card PCIE464M to do multi-nozzle vision loading &amp;amp; unloading solution.&lt;/p&gt;

&lt;p&gt;Specifically, when it moves to preset shooting area, motion control card itself high-speed IO port can precisely trigger the industrial camera to execute multi-position fly-shooting. At the same time, combining with the third-party vision, it can capture graphics parallelly and recognize features for multi-nozzle station in a short time, as well as feedback the real-time pixel level positioning data to motion controller.&lt;/p&gt;

&lt;p&gt;Zmotion multi-nozzle fly-shooting loading &amp;amp; unloading solution can complete multi-axis position compensation and angle correction synchronously, high-speed continuous fly-shooting can be achieved, which can promote more 12% comprehensive efficiency than traditional fixed shooting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcs5ki8vu8snsx8dcy17d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcs5ki8vu8snsx8dcy17d.png" alt="Image description" width="800" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;device V/T of Zmotion fly-shooting&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. How to Achieve Loading &amp;amp; Unloading?
&lt;/h2&gt;

&lt;p&gt;PCIE464M motion control card sends commands to EtherCAT drives, then motors will execute corresponding motion control tasks. Then, the system will feedback the motor real-time position (MPOS) through encoder / grating ruler. And the precision position control can be realized by our powerful motion control algorithm. During the motion, trigger the camera to shoot at precise target position, even in high-speed motion, image acquisition precision and consistency can be ensured.&lt;/p&gt;

&lt;p&gt;Therefore, it can realize precision positioning under high-speed fly-shooting.&lt;/p&gt;

&lt;h4&gt;
  
  
  (1)   Solution Whole Process
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiukchock4sg8bbla6j2m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiukchock4sg8bbla6j2m.png" alt="Image description" width="800" height="1548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  (2)   Solution Specific Actions
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;[Step 1: Material Disk Vision Positioning]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The camera takes the picture for materials in vibration disk to do rough positioning, then calculate position coordinates and planning path of capturing through vision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Step 2: Loading Capturing]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;According to calculated position, motion axis’ suction moves to correct position, then multiple nozzles to suck and capture materials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Step 3: Bottom Camera Multi-Position Vision Fly-Shooting]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Captured material moves to shooting area of bottom camera, then, the camera will be triggered by motion control card inner precision output / hardware position comparison output (HW) to do vision fly-shooting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1m2vu39q74uil9qcgxmk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1m2vu39q74uil9qcgxmk.png" alt="Image description" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Step 4: Multi-Position Positioning &amp;amp; Correction]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use the third-party vision to do vision analysis for shot graphic, and correct the position.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Step 5: Unloading &amp;amp; Placing]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While moving to placing position, correct angle and position, after arrived correct position, place materials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Step 6: Next Capturing]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When placed, return to loading position and ready to next capture.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Why Choose this Loading &amp;amp; Unloading Solution?
&lt;/h2&gt;

&lt;p&gt;a.   High Compatibility&lt;/p&gt;

&lt;p&gt;It supports all kinds of operation systems, WindowsXP / 7 / 10 / 11, Linux.&lt;/p&gt;

&lt;p&gt;b.  Easy to Develop&lt;/p&gt;

&lt;p&gt;It supports general API function interface, easy and flexible to program.&lt;/p&gt;

&lt;p&gt;c.  Faster Efficiency&lt;/p&gt;

&lt;p&gt;PCIe interface is faster than PCI to transfer data, suit to high-speed &amp;amp; high-precision applications.&lt;/p&gt;

&lt;p&gt;There are 12 independent hardware position comparison output, which can achieve fly-shooting at multi-point multi-position, that is, the whole production efficiency can be promoted above 10%.&lt;/p&gt;

&lt;p&gt;d .  C onvenient Wiring&lt;/p&gt;

&lt;p&gt;There are 16 digital inputs and 16 digital outputs, no need of adaptor board.&lt;/p&gt;

&lt;p&gt;e.  Higher Execution Efficiency&lt;/p&gt;

&lt;p&gt;It not only can develop by PC host computer languages (C# / C++ / LabVIEW / Python, etc.), also these languages can be used together with our BASIC language, which promotes command’s real-time execution efficiency.&lt;/p&gt;

&lt;p&gt;f.  Higher Device Capacity&lt;/p&gt;

&lt;p&gt;The motion control card’s EtherCAT synchronous period achieves 125us.&lt;/p&gt;

&lt;p&gt;g.  Lower Machine CT&lt;/p&gt;

&lt;p&gt;In the process of machine vision positioning correction, use fly-shooting technology, which can reduce machine CT.&lt;/p&gt;

&lt;p&gt;h.  Higher Precision&lt;/p&gt;

&lt;p&gt;There is real test that shows the loading &amp;amp; unloading precision can be up to ±0.02mm.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Delta Parallel Robotic Arm by C# | Vision Synchronous Sorting</title>
      <dc:creator>ZMOTION CONTROLLER</dc:creator>
      <pubDate>Tue, 18 Feb 2025 07:26:16 +0000</pubDate>
      <link>https://dev.to/zmotion_controller/delta-parallel-robotic-arm-by-c-vision-synchronous-sorting-b8a</link>
      <guid>https://dev.to/zmotion_controller/delta-parallel-robotic-arm-by-c-vision-synchronous-sorting-b8a</guid>
      <description>&lt;p&gt;Today, Zmotion shares &lt;a href="https://www.zmotionglobal.com/support_info_147.html" rel="noopener noreferrer"&gt;"how to do synchronous sorting in assemble line through C# for Delta robotic arm".&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, we combine our "vision motion controller" with C# to achieve that.&lt;br&gt;
"Vision Motion Controller" -- "VPLCXXX" -- "VPLC711"&lt;/p&gt;

&lt;p&gt;PART ONE: &lt;br&gt;
&lt;a href="https://www.zmotionglobal.com/support_info_136.html" rel="noopener noreferrer"&gt;Delta Parallel Robotic Arm by C# | How to Do Kinematic and Manual&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PART TWO:&lt;br&gt;
&lt;a href="https://www.zmotionglobal.com/support_info_145.html" rel="noopener noreferrer"&gt;Delta Parallel Robotic Arm by C# | How to Do Camera Calibration &amp;amp; Shape Matching&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  01
&lt;/h2&gt;

&lt;p&gt;How to Add Motion and Vision Libraries for Delta Robotic Arm by C#&lt;/p&gt;

&lt;p&gt;Here, use VS2010.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Build One Project&lt;/strong&gt;&lt;br&gt;
--click "File" - "New" - "Project"--&lt;br&gt;
--select "Visual C#", .Net Framework 4 and Windows program--&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Obtain Zmotion C# Library&lt;/strong&gt;&lt;br&gt;
--method 1: find corresponding library in Zmotion website "download", then download by yourself--&lt;br&gt;
--method 2: contact us, send the corresponding library to you--&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Develop by Zmotion C# Library File&lt;/strong&gt;&lt;br&gt;
&lt;u&gt;Note: the downloaded library is "motion control library", if you need vision function, please obtain vision library from us.&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;--copy "Zmcaux.cs" (motion library) and "Zvision.cs" (vision library) files into new built project--&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81i79fwkv9g7f9k6m5tv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81i79fwkv9g7f9k6m5tv.png" alt="Image description" width="618" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;--put zauxdll.dll, zmotion.dll, and zvision.dll files into folder of bin\debug--&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ovzcack16qos0tw47gm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ovzcack16qos0tw47gm.png" alt="Image description" width="607" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;--open the file, and click "show all files" in the "solution resource manager", and right click "Zmcaux.cs" and "Zvision.cs" files, then click "include in project".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Edit&lt;/strong&gt;&lt;br&gt;
--double click "Form 1" of "Form 1.cs"--&lt;br&gt;
--edit "using cszmcaux" and "using ZVision" at the beginning--&lt;br&gt;
--state controller handle "g_handle"--&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsk2jzbfubp20tjhj4bg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsk2jzbfubp20tjhj4bg.png" alt="Image description" width="727" height="510"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  0 2
&lt;/h2&gt;

&lt;p&gt;Main PC Commands for Delta&lt;/p&gt;

&lt;p&gt;In "PC Function Library Programming Manual”, you can check all encapsulated commands. It can be downloaded here or contact us directly.&lt;/p&gt;

&lt;p&gt;Here, it will show Delta Synchronous Sorting related commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(1) Connect to Controller -- ZAux_OpenEth&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4qozm04mgrlecyib6ur.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4qozm04mgrlecyib6ur.png" alt="Image description" width="662" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(2) Synchronize -- ZAux_Direct_MoveSync&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fityn7jzqes69mlw8mf9a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fityn7jzqes69mlw8mf9a.png" alt="Image description" width="800" height="795"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  03
&lt;/h2&gt;

&lt;p&gt;How to Use Basic Command to Check MoveSync&lt;/p&gt;

&lt;p&gt;(1) Edit Basic to Test MoveSync Usage&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'**************************************************************************************
'if there are one pair of “through-beam photoelectric sensor” fixed at two sides of assemble line to real-time detect the product position on the assemble line.
'how to fill in MOVESYNC command parameters: 
'syncposition: the belt axis position when the object arrived at induction position, it needs to record product position through encoder latching. 
'pos1: the position from following axis 1 origin to photoelectric sensor induction position is fixed for each product.
'**************************************************************************************
GLOBAL CONST BeltAxis=4      'belt axis is axis 4
GLOBAL CONST FollowAxis1=0  'following axis 1 is axis 0
GLOBAL CONST InducPos1=30  'the position from following axis 1 origin to photoelectric sensor induction point
GLOBAL CONST StandbyPos1=50'following axis 1’ standby position
GLOBAL CONST EmptyPos1=400  'following axis 1’s unloading position
'stop all axes
RAPIDSTOP(2)
WAIT IDLE     
'initialize axis parameters of corresponding axes
BASE(FollowAxis1, BeltAxis)
ATYPE = 1,1
UNITS = 1000,1000
SPEED = 50,100
DPOS = 0,0
'trigger SCOPE to capture data waveform
TRIGGER
DELAY(1000)
'following axis moves to standby at first
BASE(FollowAxis1)
MOVEABS(StandbyPos1)
'belt axis starts to move
VMOVE(1)  AXIS(BeltAxis)
'if there is one product detected when belt moved at 200
BASE(FollowAxis1)
Wait UNTIL MPOS(BeltAxis)&amp;gt; 200
MOVESYNC(0, 2000, 200, BeltAxis, InducPos1) 'when the command (following axis accelerates to synchronize) executed, it will synchronize with the product
MOVE_OP(0, ON)                           'synchronized, ON vacuum suction 
MOVESYNC(0, 1000, 200, BeltAxis, InducPos1) 'keep synchronizing 1s
MOVESYNC(-1, 0, 0, -1, EmptyPos1)          'move to unloading position
MOVE_OP(0, OFF)                       'arrive unloading position, off vacuum suction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  (2) Check Data Waveform
&lt;/h4&gt;

&lt;p&gt;Obtain corresponding waveform through &lt;a href="https://www.zmotionglobal.com/pro_info_282.html" rel="noopener noreferrer"&gt;RTSys&lt;/a&gt; (ZDevelop) -- SCOPE, then analyze synchronization process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2yy8wkbr1wbzsrpgc4jz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2yy8wkbr1wbzsrpgc4jz.png" alt="Image description" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftvyqr21ow0qpfjzva8u1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftvyqr21ow0qpfjzva8u1.png" alt="Image description" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;According above scope data we can know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a. when product is detected, the belt position is 200, following axis position is 50.&lt;/li&gt;
&lt;li&gt;b. following axis follows with the product, and keeps the same speed, when it synchronized with belt axis, belt position is 400, following axis 1 position is 230.&lt;/li&gt;
&lt;li&gt;c. it can be know the product moves forward 200 (400-200) while synchronizing from "a" and "b".&lt;/li&gt;
&lt;li&gt;d. the data from following axis 1 origin to photoelectric sensor's sense point position "InducPos1" is 30, so when axis 1 is parallel with belt, belt makes product move forward 200, then now the real distance becomes 230 (200+30).&lt;/li&gt;
&lt;li&gt;e. therefore, the result of "d" is consistent with following axis 1 real position after synchronized, that is, assemble synchronous command is OK.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  04
&lt;/h2&gt;

&lt;p&gt;One Routine: How C# Do Vision Synchronous Sorting in Assemble Line&lt;/p&gt;

&lt;h4&gt;
  
  
  (1) Belt Synchronized Command Key Parameters
&lt;/h4&gt;

&lt;p&gt;ZAux_Direct_MoveSync(ZMC_HANDLE handle,float  imode,int synctime, float syncposition, int syncaxis, int imaxaxises, int &lt;em&gt;piAxislist, float *pfDisancelist)&lt;br&gt;
*&lt;/em&gt;--imode--**&lt;br&gt;
Select synchronized mode.&lt;br&gt;
imode=0+angle: synchronous mode, if belt and axis X are parallel, fill in 0.&lt;br&gt;
imode =-1: end mode, move to the specified absolute position, it is usually used at the unloading position after synchronized and captured the material.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;--synctime--&lt;/strong&gt;&lt;br&gt;
Synchronization time, in ms unit. The movement is completed within the specified time. When completed, axis speed and object speed (on the belt axis) keep same. 0 indicates that the synchronization time is estimated according to motion axis' speed and acceleration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;--syncposition--&lt;/strong&gt;&lt;br&gt;
When vision or sensor sensed product on the belt, now belt position is MPOS (measurement position).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;--pfDistancelist--&lt;/strong&gt;&lt;br&gt;
If locates the product by vision, this parameter is "world coordinate" of the product when vision recoginized the product.&lt;/p&gt;

&lt;p&gt;If it uses photoelectric sensor to detect the product, this parameter is fixed, when the sensor feels the product, product current position absolute coordinate. Now, it can move slave axis manually to positioning the product to get the position.&lt;/p&gt;
&lt;h4&gt;
  
  
  (2) Vision Synchronous Sorting Steps
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fut00qtw8pi8zfvojsk3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fut00qtw8pi8zfvojsk3b.png" alt="Image description" width="800" height="857"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A. Codes Details of Vision Matching &amp;amp; Positioning&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/************************************************************************************
'Task No.: /
'Function of this function: vision positioning
'Input: /
'Output: / 
'returned value: sub thread – do vision positioning 
**************************************************************************************/
public void RunSubTaskVisua()
{
    int TempArrid = 0;
    float TempVar = 0;
    WriteLog("Vision Function ON");
    while (SysRunFlag &amp;gt; 0)
    {
        //when pause button is not pressed
        while (SysRunFlag == 1) 
        {
            //capture the image
            VisuaOper.CameAcquisition();
            //do template matching
            RTDisplay.Image = VisuaOper.ShapeFind();
            if (MainWindows.BeltMpos != 0)//if gets the belt encoder position normally when capturing the image
            {
                //operate MoveSyncBuff data, please lock at first
                while (true)
                {
                    if (MainWindows.SetMoveSyncFlag == 0)
                    {
                        MainWindows.SetMoveSyncFlag = 1;
                        break;
                    }
                }
                //find array starting subscript that can save data
                int ArrId = 0;
                for (int i = 0; i &amp;lt; 50; i++)
                {
                    if (MainWindows.MoveSyncBuff[i, 0] == 0)
                    {
                        ArrId = i;
                        break;
                    }
                }
                //start to save the data, 10 results can be matched at most
                TempArrid = ArrId;
                for (int i = 0; i &amp;lt; 10; i++)
                {
                    //if the score is OK
                    if (MainWindows.VisionRst[i, 0] &amp;gt;= MainWindows.VisionScore)
                    {
                        int j;
                        //if there is repeated target, delete repeated one
                        for (j = 0; j &amp;lt; TempArrid; j++)
                        {
                            TempVar = MainWindows.VisionRst[i, 1] - MainWindows.BeltMpos - MainWindows.MoveSyncBuff[j, 1] + MainWindows.MoveSyncBuff[j, 4];
                            if (((TempVar) &amp;lt;= 10) &amp;amp;&amp;amp; (TempVar &amp;gt;= -10))
                            {
                                j = -10;
                                break;
                            }
                        }
                        if (j &amp;gt;= 0)
                        {
                            MainWindows.MoveSyncBuff[ArrId, 0] = 1;
                            MainWindows.MoveSyncBuff[ArrId, 1] = MainWindows.VisionRst[i, 1];   //save matched X coordinate
                            MainWindows.MoveSyncBuff[ArrId, 2] = MainWindows.VisionRst[i, 2];   //save matched Y coordinate
                            MainWindows.MoveSyncBuff[ArrId, 3] = MainWindows.VisionRst[i, 3];   //save matched angle offset
                            MainWindows.MoveSyncBuff[ArrId, 4] = MainWindows.BeltMpos;       //save belt position when product is matched
                            ArrId = ArrId + 1;
                            IdentiNum.Text = (Convert.ToInt32(IdentiNum.Text) + 1).ToString();
                            WriteLog("Vision Target:" + "(" + MainWindows.VisionRst[i, 1].ToString("0,0") + "," + MainWindows.VisionRst[i, 2].ToString("0,0") + ")");
                        }
                    }
                    //clear scores
                    MainWindows.VisionRst[i, 0] = 0;
                }
                //unlock
                MainWindows.SetMoveSyncFlag = 0;
            }
        }
        Thread.Sleep(100);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;B. Codes Details of Vision Sorting in Assemble Line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/************************************************************************************
'Task No.: /
'Function of this function: assemble line synchronous sorting
'Input: /
'Output: / 
'returned value: /          
**************************************************************************************/
public void RunSubTaskMotion()
{
    float[] MoveSyncTemp = new float[5];
    float TempMpos = 0;
    while (SysRunFlag &amp;gt; 0)
    {
        while (SysRunFlag == 1)
        {
            if (MainWindows.MoveSyncBuff[0, 0] == 1)
            {
                MainWindows.ZauxErr = zmcaux.ZAux_Direct_GetMpos(MainWindows.g_Handle, MainWindows.ConveyorAxisId, ref TempMpos);
                //if gets the encoder position correctly
                if (0 == MainWindows.ZauxErr) 
                {
                    //how far the encoder moves forward
                    TempMpos = TempMpos - MainWindows.MoveSyncBuff[0, 4];


                    //check whether it is at synchronization starting area
                    if (((MainWindows.MoveSyncBuff[0, 1] + TempMpos) &amp;gt;= MainWindows.SyncReX[0]) &amp;amp;&amp;amp; ((MainWindows.MoveSyncBuff[0, 1] + TempMpos) &amp;lt;= MainWindows.SyncReX[1]))
                    {
                        WriteLog("Start to Synchronize to Capture");
                        //get one group of data
                        MoveSyncTemp[0] = MainWindows.MoveSyncBuff[0, 1] ;    //X
                        MoveSyncTemp[1] = MainWindows.MoveSyncBuff[0, 2] ;    //Y  
                        MoveSyncTemp[2] = MainWindows.GetBinHigt;            //capture height
                        MoveSyncTemp[3] = MainWindows.MoveSyncBuff[0, 3];    //Aanle
                        MoveSyncTemp[4] = MainWindows.MoveSyncBuff[0, 4];    //Mpos
                       //send synchronous motion command
                       //0, reset OUT
                        zmcaux.ZAux_Direct_MoveOp(MainWindows.g_Handle, MainWindows.gVAxisList[0], MainWindows.VacSucIo, 0);
                        //1, synchronize with transfer belt at first
                        zmcaux.ZAux_Direct_MoveSync(MainWindows.g_Handle, 0, 0, MainWindows.MoveSyncBuff[0, 4], MainWindows.ConveyorAxisId, 4, MainWindows.gVAxisList, MoveSyncTemp);
                        //2, synchronize a certain time, (there is lag of joint axis) 50ms
                        zmcaux.ZAux_Direct_MoveSync(MainWindows.g_Handle, 0, 50, MainWindows.MoveSyncBuff[0, 4], MainWindows.ConveyorAxisId, 4, MainWindows.gVAxisList, MoveSyncTemp);
                        //3, open vacuum nozzle
                        zmcaux.ZAux_Direct_MoveOp(MainWindows.g_Handle, MainWindows.gVAxisList[0], MainWindows.VacSucIo, 1);
                        //4, synchronize a certain time, 1500ms
                        zmcaux.ZAux_Direct_MoveSync(MainWindows.g_Handle, 0, 700, MainWindows.MoveSyncBuff[0, 4], MainWindows.ConveyorAxisId, 4, MainWindows.gVAxisList, MoveSyncTemp);
                        //5, in synchronization, move axis Z up to safe height, select axis unloading angle
                        MoveSyncTemp[2] = MainWindows.StandPos[2];             //capture height
                        zmcaux.ZAux_Direct_MoveSync(MainWindows.g_Handle, 0, 100, MainWindows.MoveSyncBuff[0, 4], MainWindows.ConveyorAxisId, 4, MainWindows.gVAxisList, MoveSyncTemp);
                        //4, release “synchronize to unloading point”
                        MoveSyncTemp[0] = MainWindows.EmptPos[0];    //X
                        MoveSyncTemp[1] = MainWindows.EmptPos[1];    //Y  
                        MoveSyncTemp[2] = MainWindows.EmptPos[2];    //unloading height
                        MoveSyncTemp[3] = MainWindows.EmptPos[3];    //Aanle
                        zmcaux.ZAux_Direct_MoveSync(MainWindows.g_Handle, -1, 0, 0, -1, 4, MainWindows.gVAxisList, MoveSyncTemp);
                        //5, close vacuum nozzle to place material, delay 100ms
                        zmcaux.ZAux_Direct_MoveOp(MainWindows.g_Handle, MainWindows.gVAxisList[0], MainWindows.VacSucIo, 0);
                        zmcaux.ZAux_Direct_MoveDelay(MainWindows.g_Handle, MainWindows.gVAxisList[0], 100);
                        //6, move to safe height
                        MoveSyncTemp[0] = MainWindows.EmptPos[0];    //X
                        MoveSyncTemp[1] = MainWindows.EmptPos[1];    //Y  
                        MoveSyncTemp[2] = MainWindows.StandPos[2];    //unloading height
                        MoveSyncTemp[3] = MainWindows.EmptPos[3];    //Aanle
                        zmcaux.ZAux_Direct_MoveAbs(MainWindows.g_Handle, 4, MainWindows.gVAxisList, MoveSyncTemp);


                        //operate MoveSyncBuff data, please lock at first
                        while (true)
                        {
                            if (MainWindows.SetMoveSyncFlag == 0)
                            {
                                MainWindows.SetMoveSyncFlag = 1;
                                break;
                            }
                        }
                        //in vision matching buffer, data are covered
                        for (int k = 0; k &amp;lt; 49; k++)
                        {
                            MainWindows.MoveSyncBuff[k, 0] = MainWindows.MoveSyncBuff[k + 1, 0];
                            MainWindows.MoveSyncBuff[k, 1] = MainWindows.MoveSyncBuff[k + 1, 1];
                            MainWindows.MoveSyncBuff[k, 2] = MainWindows.MoveSyncBuff[k + 1, 2];
                            MainWindows.MoveSyncBuff[k, 3] = MainWindows.MoveSyncBuff[k + 1, 3];
                            MainWindows.MoveSyncBuff[k, 4] = MainWindows.MoveSyncBuff[k + 1, 4];
                        }
                        //unlock
                        MainWindows.SetMoveSyncFlag = 0;
                        //until OUT opens
                        int TimeOut = 10000;
                        TimeOut = 100000;
                        //until axis stops
                        int AxisIdle = 0;                 //axis stopped state
                        while (TimeOut &amp;gt; 0)
                        {
                            zmcaux.ZAux_Direct_GetIfIdle(MainWindows.g_Handle, MainWindows.gVAxisList[0], ref AxisIdle);
                            if (AxisIdle == (-1))
                            {
                                break;
                            }
                            Thread.Sleep(10);
                            TimeOut = TimeOut - 10;
                        }
                        if (TimeOut &amp;lt;= 0)
                        {
                            //if timeout, report an error, program stops
                            WriteLog("Timeout Waiting for Axis to Stop ");
                            //Thread.Sleep(100);
                            SysRunFlag = 0;
                            break;
                        }
                        SortNum.Text = (Convert.ToInt32(SortNum.Text) + 1).ToString();
                        WriteLog("Unloading Succeeded ");
                        //exit while, cycle once
                        continue;
                    }
                    else if ((MainWindows.MoveSyncBuff[0, 1] + TempMpos) &amp;gt; MainWindows.SyncReX[1])
                    {
                        //operate MoveSyncBuff data, please lock at first
                        while (true)
                        {
                            if (MainWindows.SetMoveSyncFlag == 0)
                            {
                                MainWindows.SetMoveSyncFlag = 1;
                                break;
                            }
                        }
                        //in vision matching buffer, data are covered
                        for (int k = 0; k &amp;lt; 49; k++)
                        {
                            MainWindows.MoveSyncBuff[k, 0] = MainWindows.MoveSyncBuff[k + 1, 0];
                            MainWindows.MoveSyncBuff[k, 1] = MainWindows.MoveSyncBuff[k + 1, 1];
                            MainWindows.MoveSyncBuff[k, 2] = MainWindows.MoveSyncBuff[k + 1, 2];
                            MainWindows.MoveSyncBuff[k, 3] = MainWindows.MoveSyncBuff[k + 1, 3];
                            MainWindows.MoveSyncBuff[k, 4] = MainWindows.MoveSyncBuff[k + 1, 4];
                        }
                        //unlock
                        MainWindows.SetMoveSyncFlag = 0;
                        //if there is no data in the vision matching buffer area
                        if (MainWindows.MoveSyncBuff[0, 0] == 0)
                        {
                            //Delta moves to standby position
                            zmcaux.ZAux_Direct_MoveAbs(MainWindows.g_Handle, 4, MainWindows.gVAxisList, MainWindows.StandPos);
                            WriteLog("To Standby");
                        }
                    }
                }
            }
            else
            {
                //Delta moves to standby position
                zmcaux.ZAux_Direct_MoveAbs(MainWindows.g_Handle, 4, MainWindows.gVAxisList, MainWindows.StandPos);
            }
            Thread.Sleep(50);
        }
        //stop transfer belt
        zmcaux.ZAux_Direct_Single_Cancel(MainWindows.g_Handle, MainWindows.ConveyorAxisId, 2);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>programming</category>
      <category>csharp</category>
      <category>delta</category>
      <category>motioncontrol</category>
    </item>
    <item>
      <title>Delta Parallel Robotic Arm by C# | How to Do Kinematic and Manual?</title>
      <dc:creator>ZMOTION CONTROLLER</dc:creator>
      <pubDate>Thu, 02 Jan 2025 03:28:59 +0000</pubDate>
      <link>https://dev.to/zmotion_controller/delta-parallel-robotic-arm-by-c-how-to-do-kinematic-and-manual-3fo2</link>
      <guid>https://dev.to/zmotion_controller/delta-parallel-robotic-arm-by-c-how-to-do-kinematic-and-manual-3fo2</guid>
      <description>&lt;p&gt;Here, we take ZMC406R-V2 EtherCAT Motion Controller to build forward or inverse kinematics for Delta through C#. In addition, how to manually control it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. How C# Develops Delta Parallel Robotic Arm?
&lt;/h2&gt;

&lt;p&gt;Here, use VS2010.&lt;/p&gt;

&lt;p&gt;Step 1: Build One Project&lt;br&gt;
--click "File" - "New" - "Project"--&lt;br&gt;
--select "Visual C#", .Net Framework 4 and Windows program--&lt;/p&gt;

&lt;p&gt;Step 2: Obtain Zmotion Library&lt;br&gt;
--method 1: find corresponding library in Zmotion website "download", then download by yourself--&lt;br&gt;
--method 2: contact us, send the corresponding library to you--&lt;/p&gt;

&lt;p&gt;Step 3: Develop by Zmotion C# Library File&lt;br&gt;
--copy downloaded C# library file and corresponding file into new built project--&lt;br&gt;
&lt;em&gt;copy "zmcaux.cs" into new built project&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv85no07tk18f6klnt0r7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv85no07tk18f6klnt0r7.png" alt="Image description" width="732" height="248"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;copy "zaux.dll" and "zmotion.dll" into bin\debug folder&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjxbjnbrst02xw9h453nk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjxbjnbrst02xw9h453nk.png" alt="Image description" width="745" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;--open new created file--&lt;br&gt;
*open the file, and click "show all files" in the "solution resource manager", and right click "zmcaux.cs" file, then click "include in project".&lt;/p&gt;

&lt;p&gt;--edit--&lt;br&gt;
&lt;em&gt;double click "Form 1" of "Form 1.cs"&lt;/em&gt;&lt;br&gt;
&lt;em&gt;edit "using cszmcaux" at the beginning&lt;/em&gt;&lt;br&gt;
*state controller handle "g_handle".&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkn5y7qi5cg6txc8gcxib.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkn5y7qi5cg6txc8gcxib.png" alt="Image description" width="726" height="561"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Main PC Commands for Delta
&lt;/h2&gt;

&lt;p&gt;In "PC Function Library Programming Manual", you can check all encapsulated commands. It can be downloaded &lt;a href="https://www.zmotionglobal.com/download_list_17.html" rel="noopener noreferrer"&gt;here&lt;/a&gt; or &lt;a href="https://www.zmotionglobal.com/contactus.html" rel="noopener noreferrer"&gt;contact us&lt;/a&gt; directly.&lt;/p&gt;

&lt;p&gt;Here, it will show Delta related commands.&lt;br&gt;
(1) Connection Command -- ZAux_OpenEth&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdek6u8ebhgywmedvrb4f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdek6u8ebhgywmedvrb4f.png" alt="Image description" width="662" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(2) Forward Connection -- ZAux_Direct_Connreframe&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmpqyl1dt6mpqxhfsslop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmpqyl1dt6mpqxhfsslop.png" alt="Image description" width="662" height="574"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(3) Inverse Connection -- ZAux_Direct_Connframe&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiuvdxbfcl5eyrf1fvfo8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiuvdxbfcl5eyrf1fvfo8.png" alt="Image description" width="629" height="879"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(4) Rotate robotic arm coordinate system to get user coordinate system&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwsmqipst071iov0pc906.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwsmqipst071iov0pc906.png" alt="Image description" width="616" height="880"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. One Routine: How C# Builds Delta Kinematics?
&lt;/h2&gt;
&lt;h4&gt;
  
  
  --Theory--
&lt;/h4&gt;

&lt;p&gt;(1) Check Axis Direction&lt;br&gt;
Use Zmotion Delta parallel robotic arm model, the direction of 3 joint axes must be forward when they rotate downside, and the direction of end rotary axis also should be forward when it rotates anticlockwise (looking down).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F68iiz7ukwhry3nvlls57.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F68iiz7ukwhry3nvlls57.png" alt="Image description" width="559" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(2) Save Structural Parameters&lt;/p&gt;

&lt;p&gt;Please obtain structural parameters from your robot body manufacturer.&lt;/p&gt;

&lt;p&gt;Then write corresponding parameters into our controller TABLE register, next, it can call the interface to build forward or inverse kinematics.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tsoqijv6i1jyai995ka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tsoqijv6i1jyai995ka.png" alt="Image description" width="559" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feo51kwvz5muxkkzzv95q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feo51kwvz5muxkkzzv95q.png" alt="Image description" width="800" height="625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(3) Define Origin&lt;/p&gt;

&lt;p&gt;A. when each joint-axis' connection rod L1 is in the horizontal position, it is considered as the joint origin position (generally, robot body will provide positioning pin, if no, it can use "gradienter" to make sure L1 in the horizontal when it is at origin.&lt;/p&gt;

&lt;p&gt;B. at this time, axis 0 and axis 1' connection direction is X direction of Cartesian Coordinate System, and system's origin is located at the center of the horizontal plane of connecting rod L1.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwaw3aztxa0h0vnk1357y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwaw3aztxa0h0vnk1357y.png" alt="Image description" width="800" height="754"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(4) Set Joint-Axis &amp;amp; Virtual-Axis&lt;/p&gt;

&lt;p&gt;The joint-axis is an actual motor axis. For Delta, it has joint-axis 0, joint-axis 1, joint-axis 2 and end rotation axis. And these joint axes' pulse amounts must be set as needed pulses in one circle (Units = motor pulses in one circle * reduction ratio / 360).&lt;/p&gt;

&lt;p&gt;The virtual-axis is a virtual axis for Cartesian Coordinate System, it has system virtual axis X, axis Y, axis Z, and one rotation axis RZ. For X,Y,Z, their UNITS (pulse amount) are recommended as 1000. For RZ, UNITS should be set as needed pulses in one circle.&lt;/p&gt;
&lt;h4&gt;
  
  
  --Example--
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;(1) Connect to Controller&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Connect to controller, get the handle, then PC uses the obtained handle to control controller.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//connect to controller, default IP is 192.168.0.11
ZauxErr = zmcaux.ZAux_OpenEth("192.168.0.11", out g_Handle);
if (0 != ZauxErr)
{
AlmInifFile.Write(DateTime.Now.ToString("F"), "ZAux_OpenEth Execute Error, Error Code:" + ZauxErr.ToString(), "Error Code Info");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;(2) Set Delta Parallel Robotic Arm Parameters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdeagneajqc06h0tlojz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffdeagneajqc06h0tlojz.png" alt="Image description" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66tpnwsfnclq7idr9lj5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66tpnwsfnclq7idr9lj5.png" alt="Image description" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figut52dwe2rzfn7d2dqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figut52dwe2rzfn7d2dqy.png" alt="Image description" width="800" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(3) Build Forward Kinematic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/************************************************************************************
'Task No.: /
'Function of this function: build robotic arm forward or inverse connection 
'Input: Mode=0—disconnect, 1—inverse connection, 2—forward connection
'Output: /
'Returned Value: 0—success, 1--failure
'Notes: 
‘    *only controller with R is valid    
'    *when in forward, virtual axis MTYPE = 34
‘    *when in inverse, joint axis MTYPE = 34
‘    *when in inverse, keep enable.
**************************************************************************************/
public int ScaraEstab(int Mode)
{
    //update UI interface’s Delta parameters
    ScaraParaWindows.DeltaParaSave();
    //set robotic arm parameters
    SetControPara();
    //save Delta parameters into Ini file
    WriteIniFile();
    //clear controller alarms
    ZauxErr = zmcaux.ZAux_Direct_Single_Datum(g_Handle, 0, 0);
    //update axis list, the axis sequence is J1, J2, Ju, Jz(joint-axis), Vx, Vy, Vr, Vz (virtual-axis)
    int[] mJScaraAxisList = new int[4]; //joint-axis list
    int[] mVScaraAxisList = new int[4]; //virtual-axis list
    for (int i = 0; i &amp;lt; 4; i++)
    {
        mJScaraAxisList[i] = gDeltaAxisList[i];
        mVScaraAxisList[i] = gVAxisList[i];
    }
    //check whether robotic arm parameters are correct
    if ((DeltaR &amp;lt;= 0) || (Deltar &amp;lt;= 0) || (DeltaL1 &amp;lt;= 0) || (DeltaL2 &amp;lt;= 0))
    {
        MessageBox.Show("Delta Robot has Problem, Please Confirm! ");
        return -1;
    }
    //first to save robotic arm structural parameters into controller TABLE register, then it can build robotic arm connection
    //update robotic arm parameters into controller TABLE register
    float[] ScaraParaList = new float[11] { DeltaR, Deltar, DeltaL1, DeltaL2, gMotorPulNum[0] * gReducRatio[0], gMotorPulNum[1] * gReducRatio[1], gMotorPulNum[2] * gReducRatio[2], 0, 0, 0, gMotorPulNum[3] * gReducRatio[3] };
    ZauxErr = zmcaux.ZAux_Direct_SetTable(g_Handle, TableStaraId, 11, ScaraParaList);
    if (0 != ZauxErr)
    {
        return -1;
    }
    if ((1 == Mode) &amp;amp;&amp;amp; (0 == ZauxErr)) //build inverse solution for the robot (when the robot parameters are updated successfully)
    {
        //build Scara inverse
        ZauxErr = zmcaux.ZAux_Direct_Connframe(g_Handle, 4, mJScaraAxisList, 14, TableStaraId, 4, mVScaraAxisList);
        if (0 != ZauxErr)
        {
            ProceWindows.WriteLog("Fail to Switch Inverse");
            return -1;
        }
        ProceWindows.WriteLog("Switch to Inverse");
    }
    else if ((2 == Mode) &amp;amp;&amp;amp; (0 == ZauxErr)) //build forward solution for the robot (when the robot parameters are updated successfully)
    {
        //build Scara forward
        ZauxErr = zmcaux.ZAux_Direct_Connreframe(g_Handle, 4, mVScaraAxisList, 14, TableStaraId, 4, mJScaraAxisList);
        if (0 != ZauxErr)
        {
            ProceWindows.WriteLog("Fail to Switch Forward");
            return -1;
        }
        ProceWindows.WriteLog("Switch to Forward");
        }
    }
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: for forward, virtual-axis MTYPE will be 34, for inverse, joint-axis MTYPE will be 33. For more, please check former article "EtherCAT Motion Controller in Delta Robotic Arm".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(4) Operate Manual Motion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Below shows routine's manual motion interface.&lt;/p&gt;

&lt;p&gt;Press the "Manual" button of "Joint Coordinate System Manual Control", it will automatically build forward connection.&lt;/p&gt;

&lt;p&gt;Press the "Manual" button of "Cartesian Coordinate System Manual Control", it will automatically build inverse connection.&lt;/p&gt;

&lt;p&gt;When the manual speed decreases to a certain value, it will automatically switch to the inching mode.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftaprswnrbfy7qd9xap78.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftaprswnrbfy7qd9xap78.png" alt="Image description" width="800" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feifyimzoy3oob5j18iy1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feifyimzoy3oob5j18iy1.png" alt="Image description" width="800" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A. Joint-Axis Manual Motion&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/************************************************************************************
'Task No.: /
'Function of this “function”: joint-axis manual inverse motion, press “-“ to call
'Input: /
'Output: / 
'Returned Value: /
'Note: / 
**************************************************************************************/
private void JHandDirRev0_MouseDown(object sender, MouseEventArgs e)
{
    //whether locks it or not, after locked, then it can move
    int EnableState = 0;
    cszmcaux.zmcaux.ZAux_Direct_GetAxisEnable(MainWindows.g_Handle, MainWindows.gDeltaAxisList[0], ref EnableState);
    //if enabled
    if ((1 == EnableState) || (MainWindows.IsDebug)) 
    {
        int Vmtype = 0;//virtual axis MTYPE
        cszmcaux.zmcaux.ZAux_Direct_GetMtype(MainWindows.g_Handle, MainWindows.gVAxisList[0], ref Vmtype); 
        //if it is not forward state
        if (Vmtype != 34)
        {
            //build robotic arm forward connection
            if (0 != MainWindows.ScaraEstab(2))
            {
                //Fail to build the robot connection
                return;
            }
        }
        //which button to be pressed
        int Id = 0;
        for (int i = 0; i &amp;lt; 4; i++)
        {
            if (((Button)sender).Name == ("JHandDirRev" + i))
            {
                Id = i;
            }
        }
        int TempAxis = 0;
        TempAxis = MainWindows.gDeltaAxisList[Id];
        //if manual speed is less than 5, it is inching mode
        if (5 &amp;lt;= MainWindows.HnadSpeedPerc)
        {
            //set point motion speed
            cszmcaux.zmcaux.ZAux_Direct_SetSpeed(MainWindows.g_Handle, TempAxis, MainWindows.HnadSpeedPerc * MainWindows.gAxisHandSpeed[Id] / 100);
            //send “inverse” motion command
            cszmcaux.zmcaux.ZAux_Direct_Single_Vmove(MainWindows.g_Handle, TempAxis, -1);
        }
        else
        {
            //set inching speed
            cszmcaux.zmcaux.ZAux_Direct_SetSpeed(MainWindows.g_Handle, TempAxis, MainWindows.gAxisHandSpeed[Id] / 10);
            //send inching motion command
            cszmcaux.zmcaux.ZAux_Direct_Single_Move(MainWindows.g_Handle, TempAxis, -1 * MainWindows.HnadSpeedPerc);
        }
    }
}
/************************************************************************************
'Task No.: /
'Function of this “function”: joint-axis manual forward motion, press “+“ to call
'Input: /
'Output: / 
'Returned Value: /
'Note: /     
**************************************************************************************/
private void JHandDirFwd0_MouseDown(object sender, MouseEventArgs e)
{
    //whether locks it or not, after locked, then it can move
    int EnableState = 0;
    cszmcaux.zmcaux.ZAux_Direct_GetAxisEnable(MainWindows.g_Handle, MainWindows.gDeltaAxisList[0], ref EnableState);
    //if enabled
    if ((1 == EnableState) || (MainWindows.IsDebug)) 
    {
        int Vmtype = 0;//virtual axis MTYPE
        cszmcaux.zmcaux.ZAux_Direct_GetMtype(MainWindows.g_Handle, MainWindows.gVAxisList[0], ref Vmtype); 
        //if it is not forward state
        if (Vmtype != 34)
        {
            //build robotic arm forward kinematic
            if (0 != MainWindows.ScaraEstab(2))
            {
                //Fail to build the robot connection
                return;
            }
        }
        //which button to be pressed
        int Id = 0;
        for (int i = 0; i &amp;lt; 4; i++)
        {
            if (((Button)sender).Name == ("JHandDirFwd" + i))
            {
                Id = i;
            }
        }
        int TempAxis = 0;
        TempAxis = MainWindows.gDeltaAxisList[Id];
        //if manual speed is less than 5, it is inching mode
        if (5 &amp;lt;= MainWindows.HnadSpeedPerc)
        {
            //set point motion speed
            cszmcaux.zmcaux.ZAux_Direct_SetSpeed(MainWindows.g_Handle, TempAxis, MainWindows.HnadSpeedPerc * MainWindows.gAxisHandSpeed[Id] / 100);
            //send “forward” motion command
            cszmcaux.zmcaux.ZAux_Direct_Single_Vmove(MainWindows.g_Handle, TempAxis, 1);
        }
        else
        {
            //set inching speed
            cszmcaux.zmcaux.ZAux_Direct_SetSpeed(MainWindows.g_Handle, TempAxis, MainWindows.gAxisHandSpeed[Id] / 10);
            //send inching motion command
            cszmcaux.zmcaux.ZAux_Direct_Single_Move(MainWindows.g_Handle, TempAxis, 1 * MainWindows.HnadSpeedPerc);
        }
    }
}
/************************************************************************************
'Task No.: /
'Function of this “function”: joint-axis stop manual motion, call when point button is released
'Input: /
'Output: / 
'Returned Value: /
'Note: /      
**************************************************************************************/
private void JHandDirRev0_MouseUp(object sender, MouseEventArgs e)
{
    //which button to be pressed
    int Id = 0;
    for (int i = 0; i &amp;lt; 4; i++)
    {
        if (((Button)sender).Name == ("JHandDirRev" + i))
        {
            Id = i;
        }
    }
    int TempAxis = 0;
    TempAxis = MainWindows.gDeltaAxisList[Id];
    //if manual speed is less than 5, it is inching mode
    if (5 &amp;lt;= MainWindows.HnadSpeedPerc)
    {
        MainWindows.ZauxErr = cszmcaux.zmcaux.ZAux_Direct_Single_Cancel(MainWindows.g_Handle, TempAxis, 2);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;B. Virtual-Axis Manual Motion&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/************************************************************************************
'Task No.: /
'Function of this “function”: virtual manual inverse motion, press “-“ to call
'Input: /
'Output: / 
'Returned Value: /
'Note: /     
**************************************************************************************/
private void VHandDirRev0_MouseDown(object sender, MouseEventArgs e)
{
    //whether locks it or not, after locked, then it can move
    int EnableState = 0;
    cszmcaux.zmcaux.ZAux_Direct_GetAxisEnable(MainWindows.g_Handle, MainWindows.gDeltaAxisList[0], ref EnableState);
    //if enabled
    if ((1 == EnableState) || (MainWindows.IsDebug)) 
    {
        int Jmtype = 0;//joint-axis Mtype
        cszmcaux.zmcaux.ZAux_Direct_GetMtype(MainWindows.g_Handle, gDeltaAxisList[0], ref Jmtype);
        //if it is not inverse state
        if (Jmtype != 33)
        {
            //build robotic arm inverse kinematic
            if (0 != MainWindows.ScaraEstab(1))
            {
                //Fail to build the robot connection
                return;
            }
        }
        //which button to be pressed
        int Id = 0;
        for (int i = 0; i &amp;lt; 5; i++)
        {
            if (((Button)sender).Name == ("VHandDirRev" + i))
            {
                Id = i;
            }
        }
        int TempAxis = 0;
        //update current robotic arm state
        TempAxis = MainWindows.gVAxisList[Id];
        //if manual speed is less than 5, it is inching mode
        if (5 &amp;lt;= MainWindows.HnadSpeedPerc)
        {
            //set point motion speed
            cszmcaux.zmcaux.ZAux_Direct_SetSpeed(MainWindows.g_Handle, TempAxis, MainWindows.HnadSpeedPerc * MainWindows.gAxisHandSpeed[Id] / 100);
            //send “inverse” motion command
           cszmcaux.zmcaux.ZAux_Direct_Single_Vmove(MainWindows.g_Handle, TempAxis, -1); 
        }
        else
        {
            //set inching speed
            cszmcaux.zmcaux.ZAux_Direct_SetSpeed(MainWindows.g_Handle, TempAxis, MainWindows.gAxisHandSpeed[Id] / 10);
            //send inching motion command
           cszmcaux.zmcaux.ZAux_Direct_Single_Move(MainWindows.g_Handle, TempAxis, -1 * MainWindows.HnadSpeedPerc);
        }
    }
}
/************************************************************************************
'Task No.: /
'Function of this “function”: joint-axis manual forward motion, press “+“ to call
'Input: /
'Output: / 
'Returned Value: /
'Note: /    
**************************************************************************************/
private void VHandDirFwd0_MouseDown(object sender, MouseEventArgs e)
{
    //whether locks it or not, after locked, then it can move
    int EnableState = 0;
    cszmcaux.zmcaux.ZAux_Direct_GetAxisEnable(MainWindows.g_Handle, MainWindows.gDeltaAxisList[0], ref EnableState);
    //if enabled
    if ((1 == EnableState) || (MainWindows.IsDebug)) 
    {
        int Jmtype = 0;//joint-axis Mtype
        cszmcaux.zmcaux.ZAux_Direct_GetMtype(MainWindows.g_Handle, gDeltaAxisList[0], ref Jmtype);
        //if it is not forward kinematic
        if (Jmtype != 33)
        {
            //build robotic arm forward connection
            if (0 != MainWindows.ScaraEstab(1))
            {
                //Fail to build the robot connection
                return;
            }
        }
        //which button to be pressed
        int Id = 0;
        for (int i = 0; i &amp;lt; 5; i++)
        {
            if (((Button)sender).Name == ("VHandDirFwd" + i))
            {
                Id = i;
            }
        }
        int TempAxis = 0;
        //update current robotic arm state
        TempAxis = MainWindows.gVAxisList[Id];
        //if manual speed is less than 5, it is inching mode
        if (5 &amp;lt;= MainWindows.HnadSpeedPerc)
        {
           //set point motion speed
            cszmcaux.zmcaux.ZAux_Direct_SetSpeed(MainWindows.g_Handle, TempAxis, MainWindows.HnadSpeedPerc * MainWindows.gAxisHandSpeed[Id] / 100);
           //send “forward” motion command
           cszmcaux.zmcaux.ZAux_Direct_Single_Vmove(MainWindows.g_Handle, TempAxis, 1); 
        }
        else
        {
            //set inching speed
            cszmcaux.zmcaux.ZAux_Direct_SetSpeed(MainWindows.g_Handle, TempAxis, MainWindows.gAxisHandSpeed[Id] / 10);
            //send inching motion command
           cszmcaux.zmcaux.ZAux_Direct_Single_Move(MainWindows.g_Handle, TempAxis, 1 * MainWindows.HnadSpeedPerc);
        }
    }
}
/************************************************************************************
'Task No.: /
'Function of this “function”: virtual-axis stop motion, call when the point motion button is released
'Input: /
'Output: / 
'Returned Value: /
'Note: /     
**************************************************************************************/
//stop the motion
private void VHandDirRev0_MouseUp(object sender, MouseEventArgs e)
{
    //which button to be pressed
    int Id = 0;
    for (int i = 0; i &amp;lt; 5; i++)
    {
        if (((Button)sender).Name == ("VHandDirRev" + i))
        {
            Id = i;
        }
    }
    int TempAxis = 0;
    TempAxis = MainWindows.gVAxisList[Id];
    //if manual speed is less than 5, it is inching mode
    if (5 &amp;lt;= MainWindows.HnadSpeedPerc)
    {
        cszmcaux.zmcaux.ZAux_Direct_Single_Cancel(MainWindows.g_Handle, TempAxis, 2);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;(5) Use Robotic Arm Simulator Tool&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open "ZRobotView" software, enter controller IP (default IP: 192.168.0.11), then click "connect". After connected, click "switch", it can 3D simulate robotic arm operation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6gr1p1ohtaew2o82zdzd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6gr1p1ohtaew2o82zdzd.png" alt="Image description" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3hn00g943jyrqshjp75.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3hn00g943jyrqshjp75.png" alt="Image description" width="800" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's all, thank you for your reading -- &lt;a href="https://www.zmotionglobal.com/support_info_144.html" rel="noopener noreferrer"&gt;Delta Parallel Robotic Arm by C# | How to Do Kinematic and Manual.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article is edited by ZMOTION, here, share with you, let's learn together.&lt;/p&gt;

&lt;p&gt;Note: Copyright belongs to Zmotion Technology, if there is reproduction, please indicate article source. Thank you.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Control SSI Absolute Encoder by EtherCAT Controller?</title>
      <dc:creator>ZMOTION CONTROLLER</dc:creator>
      <pubDate>Tue, 24 Dec 2024 09:13:02 +0000</pubDate>
      <link>https://dev.to/zmotion_controller/how-to-control-ssi-absolute-encoder-by-ethercat-controller-2cic</link>
      <guid>https://dev.to/zmotion_controller/how-to-control-ssi-absolute-encoder-by-ethercat-controller-2cic</guid>
      <description>&lt;p&gt;Before, &lt;a href="https://www.zmotionglobal.com/support_info_150.html" rel="noopener noreferrer"&gt;“How to Use ZMC432-V2 EtherCAT Motion Controller to Read Position from BissC Absolute Encoder”&lt;/a&gt; had been shared, you can review that~&lt;/p&gt;

&lt;p&gt;Then, today, let’s see another kind of encoder “SSI absolute encoder” in EtherCAT motion controller, still, taking the example of &lt;a href="https://www.zmotionglobal.com/pro_info_177.html" rel="noopener noreferrer"&gt;ZMC432-V2 EtherCAT motion controller&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SSI Absolute Encoder?
&lt;/h2&gt;

&lt;p&gt;“SSI” means Synchronous Serial Interface, it is one digital interface protocol. Moreover, it is one communication protocol for data transferring between motion control and absolute encoder. And one main feature is "master-slave" interface because it uses synchronous serial interface mode. &lt;br&gt;
Specifically, there are clock signal and pulse on the controller that can transfer data from the encoder to the controller synchronously. And the output data can be binary system or Gray-code. &lt;br&gt;
Therefore, SSI absolute encoder is used to measure the position and angle. It only needs 2 cables to do the data transferring: Data &amp;amp; Clock. The principle is very simple, it converts the position information to binary code, encoding the codes as serial data, during the control, controller “clock” signal will control data’s transferring velocity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zavs3tdfwsxcox0x5os.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zavs3tdfwsxcox0x5os.png" alt="Image description" width="800" height="362"&gt;&lt;/a&gt;&lt;br&gt;
SSI Absolute Encoder&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4xsmyzj36q6kccv8mpn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4xsmyzj36q6kccv8mpn.png" alt="Image description" width="800" height="273"&gt;&lt;/a&gt;&lt;br&gt;
SSI Interface&lt;/p&gt;

&lt;h2&gt;
  
  
  How EtherCAT Motion Controller Controls SSI Absolute Encoder?
&lt;/h2&gt;

&lt;h4&gt;
  
  
  (1) EtherCAT Motion Controller
&lt;/h4&gt;

&lt;p&gt;A. Valid EtherCAT Motion Controller&lt;br&gt;
For Zmotion, EtherCAT motion controller must meet below requirements:&lt;br&gt;
*Controller Model: ZMC432-V2, ZMC406-V2&lt;/p&gt;

&lt;p&gt;It supports rich motion control interfaces, and this kind of controller “ZMC” can run without PC. &lt;/p&gt;

&lt;p&gt;It supports 32 axes motion control at most, that is, it can control 32 motors. All kinds of motion control functions and applications, it is OK.&lt;br&gt;
*Firmware Version: above 4.930-20190305&lt;br&gt;
*AXIS Interface: for ZMC432-V2 series, only AXIS4/5 support SSI/BISS communication.&lt;br&gt;
You can check through "controller status", if there is "Ssi", which means it supports.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frpmq5h4fr8fwqr1uwhs7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frpmq5h4fr8fwqr1uwhs7.png" alt="Image description" width="248" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;B. Development&lt;br&gt;
--RTSys / ZDevelop: PLC / Basic / HMI.&lt;br&gt;
--PC Languages: C#, C++, LabVIEW, Matlab, Qt, Linux, VB.Net, Python&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1vt2pdkg75khuff1xp6i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1vt2pdkg75khuff1xp6i.png" alt="Image description" width="800" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  (2) Wiring: EtherCAT Controller &amp;amp; SSI Absolute Encoder
&lt;/h4&gt;

&lt;p&gt;EtherCAT motion controller has two pulse axes AXIS 4 &amp;amp; AXIS 5 that support SSI/BISS communication protocol, but SSI absolute encoder must be powered by 5V. And whatever SSI absolute encoder uses +5V power supply, the public end must be connected to controller GND.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frh4vu5j4dlulcud3yufw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frh4vu5j4dlulcud3yufw.png" alt="Image description" width="461" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1yad2ch35hl6r92mexwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1yad2ch35hl6r92mexwg.png" alt="Image description" width="800" height="693"&gt;&lt;/a&gt;&lt;br&gt;
ZMC432-V2 Controller AXIS 4 / 5 &amp;amp; SSI / BISS Interface&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0nt1n5qotkx4o5oc177.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0nt1n5qotkx4o5oc177.png" alt="Image description" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wiring of EtherCAT Master &amp;amp; SSI Absolute Encoder&lt;/p&gt;

&lt;h4&gt;
  
  
  (3) Needed Parameters
&lt;/h4&gt;

&lt;p&gt;--ATYPE: Axis Type--&lt;br&gt;
48 = SSI absolute encoder, 49 = BISS absolute encoder&lt;br&gt;
--UNITS: Pulse Amount--&lt;br&gt;
Take SSI absolute encoder as the example, the resolution is 16-bit, then one circle corresponds to 65535 pulses, that is, the controller sets this axis' pulse amount UNITS according to this parameter.&lt;br&gt;
--ENCODER_BITS: SSI/BISS Encoder Absolute Bit--&lt;br&gt;
Refer to SSI absolute encoder manual data bit. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2qted9qyy67jgtxalen3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2qted9qyy67jgtxalen3.png" alt="Image description" width="650" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  (4) Program Configuration
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global CONST ENC_AxisStart = 4     'local absolute encoder axis starting axis No.
global CONST ENC_AxisNum = 2     'how many axes of local absolute encoder axes
'set local absolute encoder axis
for i = 0 to ENC_AxisNum - 1
   BASE(ENC_AxisStart + i)
   AXIS_ADDRESS=(-1&amp;lt;&amp;lt;16)+4+i     'map absolute encoder to axis 4, 5
   ENCODER_BITS = 26                     '26-bit absolute
   ATYPE=48                                        'SSI absolute encoder
Next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  (5) Origin Settings
&lt;/h4&gt;

&lt;p&gt;Generally, the origin position of absolute encoder is set through the signal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55ojy3r5i9h8o9to1rke.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55ojy3r5i9h8o9to1rke.png" alt="Image description" width="800" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If not to use signal, you also can contact with encoder manufacturer.&lt;/p&gt;

&lt;h4&gt;
  
  
  (6) Absolute Encoder Position Reading
&lt;/h4&gt;

&lt;p&gt;After encoder position cleared when at the origin position, set UNITS, and read axis 4 / 5 MPOS values, then you will know encoder current position, if you need encoder original value, then read “ENCODER” of axis 4 / 5. &lt;br&gt;
Note: SSI absolute encoder position supports power-down storage function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqm6x2s2kc7m4d1vymkt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqm6x2s2kc7m4d1vymkt.png" alt="Image description" width="711" height="425"&gt;&lt;/a&gt;&lt;br&gt;
Axis 4 SSI Absolute Encoder Position MPOS&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6bir020icq4tkcgrlgpz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6bir020icq4tkcgrlgpz.png" alt="Image description" width="800" height="491"&gt;&lt;/a&gt;&lt;br&gt;
Position Curve Captured by SCOPE when Rotating SSI Absolute Encoder Manually&lt;/p&gt;

&lt;h2&gt;
  
  
  Q &amp;amp; A of Related SSI Absolute Encoder:
&lt;/h2&gt;

&lt;p&gt;--when downloading, it shows atype 48 error of axis 4 / axis 5--&lt;br&gt;
Please check controller firmware version, it should be above 20190305, if not, contact with us to update it.&lt;/p&gt;

&lt;p&gt;--no MPOS / wrong MPOS for axis 4 / axis 5--&lt;br&gt;
Check wiring.&lt;br&gt;
Check encoder_bit parameter configuration. You can online send the command “?* encoder_bits” to see if the parameter is set correctly.&lt;/p&gt;

&lt;p&gt;That's all, thank you for your reading -- &lt;a href="https://www.zmotionglobal.com/support_info_156.html" rel="noopener noreferrer"&gt;How to Control SSI Absolute Encoder in EtherCAT Motion Controller?&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Control BissC Absolute Encoder in EtherCAT Motion Controller</title>
      <dc:creator>ZMOTION CONTROLLER</dc:creator>
      <pubDate>Thu, 12 Dec 2024 08:10:45 +0000</pubDate>
      <link>https://dev.to/zmotion_controller/how-to-control-bissc-absolute-encoder-in-ethercat-motion-controller-2d9l</link>
      <guid>https://dev.to/zmotion_controller/how-to-control-bissc-absolute-encoder-in-ethercat-motion-controller-2d9l</guid>
      <description>&lt;h2&gt;
  
  
  What is Bissc Absolute Encoder?
&lt;/h2&gt;

&lt;p&gt;BissC means Binary Synchronous Serial Communication . From the name, it can be known it is one digital interface protocol . Moreover, it is one communication protocol for data transferring between motion control and absolute encoder. And one main feature is "master-slave" interface because it uses fast dual-station synchronous serial interface mode.&lt;/p&gt;

&lt;p&gt;In BissC protocol, master interface controls the sequence of position capture and data transferring speed, then encoder as the slave interface, mainly to respond main interface's position capture request.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;BISS Interface&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frqlc8w4hayb1ak7u1z8o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frqlc8w4hayb1ak7u1z8o.png" alt="Image description" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From above BISS Interface, it can be seen data transferring is made by two pairs of single-direction differential cables: Clock &amp;amp; Data .&lt;/p&gt;

&lt;p&gt;--Clock: transfer "position capture request" and "time sequence information" from master interface to encoder--&lt;/p&gt;

&lt;p&gt;--Data: back position data to interface that is synchronous with Clock--&lt;/p&gt;

&lt;p&gt;Then for BissC absolute encoder, it is used to measure position and angle, and in industrial automation and control system, it plays an important role because more accurate and more specific position can be obtained by high-frequency signal.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;BissC Absolute Encoder&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnryfgh0snm0ce5e8ebok.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnryfgh0snm0ce5e8ebok.png" alt="Image description" width="562" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;BissC Absolute Grating Ruler&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9uz5felnqsvrmcfgrf5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9uz5felnqsvrmcfgrf5g.png" alt="Image description" width="631" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How EtherCAT Motion Controller Controls BissC Absolute Encoder?
&lt;/h2&gt;

&lt;h4&gt;
  
  
  (1) EtherCAT Motion Controller
&lt;/h4&gt;

&lt;p&gt;A. Valid EtherCAT Motion Controller&lt;/p&gt;

&lt;p&gt;For Zmotion, &lt;a href="https://www.zmotionglobal.com/pro_list_83.html" rel="noopener noreferrer"&gt;EtherCAT motion controller&lt;/a&gt; must meet below requirements:&lt;br&gt;
*Controller Model: ZMC432-V2, ZMC406-V2&lt;br&gt;
*Firmware Version: above 4.930-20190305&lt;br&gt;
*AXIS Interface: for ZMC432-V2 series, only AXIS4/5 support SSI/BISS communication.&lt;br&gt;
You can check through "controller status", if there is "Ssi", which means it supports.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgx054ha1juu2cicb30a4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgx054ha1juu2cicb30a4.png" alt="Image description" width="248" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;B. Development&lt;/p&gt;

&lt;p&gt;--&lt;a href="https://www.zmotionglobal.com/pro_info_282.html" rel="noopener noreferrer"&gt;RTSys&lt;/a&gt;: PLC / Basic / HMI.&lt;br&gt;
--PC Languages: C#, C++, LabVIEW, Matlab, Qt, Linux, VB.Net, Python&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmjr95w81l7f3sysam5co.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmjr95w81l7f3sysam5co.png" alt="Image description" width="800" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more details, please refer to ZMC432-V2 EtherCAT motion controller user manual.&lt;/p&gt;

&lt;h4&gt;
  
  
  (2) Wiring between EtherCAT &amp;amp; BissC Absolute Encoder
&lt;/h4&gt;

&lt;p&gt;EtherCAT motion controller supports SSI/BISS communication protocol, it only supports the BissC absolute encoder of 5V power. And whatever BissC absolute encoder uses +5V power supply, the public end must be connected to controller GND.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk3cnrypyeer55dxl17br.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk3cnrypyeer55dxl17br.png" alt="Image description" width="461" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;ZMC432-V2 AXIS4/5 SSI/BISS&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7sceepcebwpuh243eogm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7sceepcebwpuh243eogm.png" alt="Image description" width="800" height="693"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Wiring between ZMC432-V2 EtherCAT Motion Controller and BissC Absolute Encoder&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fya6b0ocmunr8yaawwvrv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fya6b0ocmunr8yaawwvrv.png" alt="Image description" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  (3) Needed Parameters
&lt;/h4&gt;

&lt;p&gt;--ATYPE: Axis Type--&lt;/p&gt;

&lt;p&gt;48 = SSI absolute encoder, 49 = BISS absolute encoder&lt;/p&gt;

&lt;p&gt;--UNITS: Pulse Amount--&lt;/p&gt;

&lt;p&gt;Take BissC absolute grating ruler as the example, resolution is 100nm, then one pulse corresponds to 100nm, 1mm = 10000 pulses, that is, controller sets this axis' UNITS according to this parameter.&lt;/p&gt;

&lt;p&gt;--ENCODER_BITS: SSI/BISS Encoder Absolute Bit--&lt;/p&gt;

&lt;p&gt;Refer to BissC absolute encoder manual data bit. Some BissC absolute encoders have more auxiliary state bits, generally there are 18-20 bits. ENCODER_BITS can manually adjust it. ENOCDER_BITS = data bit + auxiliary state bit (some encoders don't support).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6y77gbl8ezj006g1yfj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6y77gbl8ezj006g1yfj.png" alt="Image description" width="800" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  (4) Program Configuration
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global CONST ENC_AxisStart = 4     'local absolute encoder axis starting axis No.
global CONST ENC_AxisNum = 2     'how many axes of local absolute encoder axes
'set local absolute encoder axis
for i = 0 to ENC_AxisNum - 1
    BASE(ENC_AxisStart + i)
    AXIS_ADDRESS=(-1&amp;lt;&amp;lt;16)+4+i    'map absolute encoder to axis 4, 5
    ENCODER_BITS = 51      '32 bits absolute value, it is with 19 auxiliary state bits
    ATYPE=49               'BISS absolute encoder
Next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  (5) Origin Settings
&lt;/h4&gt;

&lt;p&gt;--Grating Ruler--&lt;/p&gt;

&lt;p&gt;Use origin configuration tool to set the origin position.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mt8xmhu942kna3oxoik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mt8xmhu942kna3oxoik.png" alt="Image description" width="530" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;--General Rotary Absolute Encoder--&lt;/p&gt;

&lt;p&gt;Use signal to set origin position.&lt;/p&gt;

&lt;p&gt;--Others--&lt;/p&gt;

&lt;p&gt;Please contact with encoder manufacturers.&lt;/p&gt;

&lt;h4&gt;
  
  
  (6) Absolute Encoder Position Reading
&lt;/h4&gt;

&lt;p&gt;A. How to Achieve&lt;/p&gt;

&lt;p&gt;Step 1: clear encoder position at origin position.&lt;/p&gt;

&lt;p&gt;Step 2: set UNITS&lt;/p&gt;

&lt;p&gt;Step 3: read axis 4 / axis 5 MPOS value to get encoder current position, if you need encoder original value, read axis 4 / axis 5 ENCODER.&lt;/p&gt;

&lt;p&gt;Note: BissC absolute encoder position supports power failure storage.&lt;/p&gt;

&lt;p&gt;B. Example:&lt;/p&gt;

&lt;p&gt;Manually rotate BissC absolute encoder, and capture the position curve by oscilloscope, then you will get:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F385odrhywaj2djicqw9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F385odrhywaj2djicqw9f.png" alt="Image description" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;C. Problems &amp;amp; Solutions&lt;/p&gt;

&lt;p&gt;--when downloading, it shows atype 49 error of axis 4 / axis 5--&lt;/p&gt;

&lt;p&gt;Please check controller firmware version, it should be above 20190305, if not, contact with us to update it.&lt;/p&gt;

&lt;p&gt;--no MPOS / wrong MPOS for axis 4 / axis 5--&lt;/p&gt;

&lt;p&gt;Check wiring.&lt;/p&gt;

&lt;p&gt;Check encoder_bit parameters, manually adjust the state bit, send "encoder_bits" command in "output" window, see whether parameters are valid.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That's all, thank you for your reading -- &lt;a href="https://www.zmotionglobal.com/support_info_150.html" rel="noopener noreferrer"&gt;How to Control BissC Absolute Encoder in EtherCAT Motion Controller&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Control Delta Robotic Arm by EtherCAT Motion Controller?</title>
      <dc:creator>ZMOTION CONTROLLER</dc:creator>
      <pubDate>Tue, 03 Dec 2024 07:02:10 +0000</pubDate>
      <link>https://dev.to/zmotion_controller/how-to-control-delta-robotic-arm-by-ethercat-motion-controller-3c8p</link>
      <guid>https://dev.to/zmotion_controller/how-to-control-delta-robotic-arm-by-ethercat-motion-controller-3c8p</guid>
      <description>&lt;p&gt;&lt;strong&gt;_Read Me at First: _&lt;/strong&gt;&lt;br&gt;
A. This article is written by Zmotion, original article is &lt;a href="https://www.zmotionglobal.com/support_info_136.html" rel="noopener noreferrer"&gt;https://www.zmotionglobal.com/support_info_136.html&lt;/a&gt;.&lt;br&gt;
B. Article corresponding video description: &lt;a href="https://youtu.be/GCFTSja_HOM" rel="noopener noreferrer"&gt;https://youtu.be/GCFTSja_HOM&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Generally, Delta robotic arm supports 3-4 axes (joint axis 1 + joint axis 2 + joint axis 3 + [end rotary axis 4]). For Zmotion motion controllers, not all controllers support Delta robot function, only the controller that is with suffix “R” can be applied in Delta robot application, for example, ZMC406R. &lt;br&gt;
Then, here we take &lt;a href="https://www.zmotionglobal.com/pro_info_132.html" rel="noopener noreferrer"&gt;ZMC406R EtherCAT Robot Motion Controller&lt;/a&gt; as the example to show you how to control your Delta robotic arm.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg08xxoh6lmva1kfi85ie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg08xxoh6lmva1kfi85ie.png" alt="Image description" width="316" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For development:&lt;br&gt;
*&lt;a href="https://www.zmotionglobal.com/pro_info_282.html" rel="noopener noreferrer"&gt;ZDevelop / RTSys&lt;/a&gt;: it can develop, compile and debug your program in advance.&lt;br&gt;
*PC Language: C++ / C# / Labview / Python, etc.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Brief Introduction of Robotic Arm
&lt;/h2&gt;
&lt;h4&gt;
  
  
  (1) Two Main Related Robotic Arm Definition
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;--Joint-Axis &amp;amp; Virtual-Axis--&lt;/em&gt;&lt;br&gt;
A. Joint-Axis: &lt;br&gt;
The joint axis refers to the rotary joint in the actual mechanical structure. In program, generally it shows the rotation angle (some structures are also translation axes). Since there is a reduction ratio between the motor and the rotary joint, when setting UNITS (the number of pulses when motor moves 1mm or 1°), it should be set according to the actual joint rotation. At the same time, when filling in the structural parameters in the TABLE, it should also be calculated according to the rotary joint center, not the center of the motor axis.&lt;/p&gt;

&lt;p&gt;B. Virtual-axis&lt;br&gt;
The virtual axis does not actually exist. It is 6 degrees of freedom of the world coordinate system, which are X, Y, Z, RX, RY, and RZ in turn. Also, it can be understood as the three linear axes and three rotary axes of the Cartesian coordinate system. This kind of axis can be used to determine the processing trajectory and coordinates of robot end working point.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;--Forward Kinematics &amp;amp; Inverse Kinematics--&lt;/em&gt;&lt;br&gt;
A. Forward Kinematics&lt;br&gt;
By operating the joint coordinates, the spatial position of the end position in the Cartesian coordinate system can be calculated according to the mechanical structure parameters. This process is called “Forward Kinematics”. Now, the actual joint axis is operated, then the virtual axis automatically calculates the coordinates. And at this time, only joint-axis motion can be operated. Generally, forward kinematics is used to adjust joint position manually or point-homing when powered on.&lt;br&gt;
B. Inverse Kinematics&lt;br&gt;
Given a spatial position in a Cartesian coordinate system, calculate the coordinates of each joint axis. This process is called “Inverse Kinematics”. Now, the virtual axis is operated, then the actual joint axis automatically calculates the coordinates and moves.&lt;br&gt;
There is one command for controller to build the inverse kinematics mode, “CONNFRAME”. This instruction acts on the joint axis. At this time, only the virtual axis can be operated (send motion command to virtual axis). Then, it can do linear motion, circular motion, space arc motions in the Cartesian coordinate system, for the joint axis, it will automatically move to the position where is after the inverse solution due to CONNFRAME command.&lt;/p&gt;
&lt;h4&gt;
  
  
  (2) How to Use Robotic Arm
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;A. Observe Motor Direction&lt;/strong&gt;&lt;br&gt;
At first, check whether the motor’s rotary direction is correct or not. When 3 joint axes rotate down, it is positive. Look down, when the end rotate axis rotates in the anticlockwise, it is positive. At this time, we can connect to robotic arm simulation tool “ZRobotView”, and click “Tool—Manual” in ZDevelop / RTSys, then operate 3 joint axes separately at one small speed. While moving, please see whether each joint-axis trends to end working point in the movement process of down. If “YES”, the direction is correct.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe87nbu5dg6juq12qx6vr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe87nbu5dg6juq12qx6vr.png" alt="Image description" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. Save Robot Structure Parameters into TABLE Register&lt;/strong&gt;&lt;br&gt;
While building the robotic arm connection, it needs to fill in mechanical parameters into TABLE arrays according to below sequence. &lt;br&gt;
--Mechanical Structural Parameters of Delta Robotic Arm FRAME 12--&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frpzm9da4iixpf2a6ahdu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frpzm9da4iixpf2a6ahdu.png" alt="Image description" width="559" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8709pk4wyv25lbak21i8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8709pk4wyv25lbak21i8.png" alt="Image description" width="800" height="625"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;‘starting from TableNum, save robotic arm structural parameters shown in above form into Table.&lt;br&gt;
&lt;em&gt;TABLE(TableNum,Top_R,Under_R,Top_L,Under_L,OneCirPules_J1,OneCirPules_J2,OneCirPules_J3,Offset_X,Offset_Y,Offset_Z,OneCirPules_J4)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C. Set Parameters of Joint-Axis &amp;amp; Virtual-Axis&lt;/strong&gt;&lt;br&gt;
All axes’ axis types and pulse amounts (units) should be set correctly. UNITS means the number of pulses for the motor in 1° motion. But for virtual-axis, its “units” is unrelated to actual sending pulses, it is used to set motion precision. And it is recommended to set virtual-axis’ units in 1mm is 1000, which means the accuracy is 3 digits after decimal part.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'joint-axis setting
BASE(Axis_JList(0),Axis_JList(1),Axis_JList(2),Axis_JList(3))
'set pulse axis type (ATYPE) as 1, if it is bus type, set it as 65. 
ATYPE = 1,1,1,1 
UNITS = UnitsJList(0),UnitsJList(1),UnitsJList(2),UnitsJList(3)
'set joint-axis speed, acceleration (usually be 10 times of speed), deceleration (usually be 10 times of speed)
SPEED = SpeedJList(0),SpeedJList(1),SpeedJList(2),SpeedJList(3) 
ACCEL = ADSpeedJList(0),ADSpeedJList(1),ADSpeedJList(2),ADSpeedJList(3)
DECEL = ADSpeedJList(0),ADSpeedJList(1),ADSpeedJList(2),ADSpeedJList(3)
'S curve setting
SRAMP = SrampJ(0),SrampJ(1),SrampJ(2),SrampJ(3)
'virtual-axis setting
BASE(Axis_VList(0),Axis_VList(1),Axis_VList(2))
'set virtual axes type as 0
ATYPE = 0,0,0
'set virtual axes’ pulse amount (ATYPE) as 1000, which means the precision is after 3 digits decimal part
UNITS = 1000,1000,1000
'set virtual-axis speed, acceleration (usually be 10 times of speed), deceleration (usually be 10 times of speed)
SPEED = SpeedVList(0),SpeedVList(1),SpeedVList(2)
ACCEL = AccelV(0),AccelV(1),AccelV(2)
DECEL = DecelV(0),DecelV(1),DecelV(2)
'S curve setting
SRAMP = SrampV(0),SrampV(1),SrampV(2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;D. Move Each Joint-Axis to Planned Origin Position&lt;/strong&gt;&lt;br&gt;
While robotic arm algorithm is building, it needs one origin position as the reference. When Delta robot each joint-axis’ connection rods L1 are all in horizontal position, it is considered as joint origin position. In real robotic arm machine on site, generally there is one location pin, if it doesn’t have the location pin, it can adjust L1 to be horizontal by “level instrument”. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2rkbh23cnkg63yghytx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2rkbh23cnkg63yghytx.png" alt="Image description" width="800" height="754"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E. Control Robotic Arm&lt;/strong&gt;&lt;br&gt;
There are two modes to control it, according to needs, build the forward kinematics or inverse kinematics.&lt;/p&gt;
&lt;h4&gt;
  
  
  (3) Robotic Arm Commands
&lt;/h4&gt;

&lt;p&gt;Different robotic arm models are with different parameters. Please check details in “Zmotion Robotic Arm Command Manual”, then do selection.&lt;br&gt;
Here, take Delta FRAME 12 model as the example. FRAME 12 means there is one end rotary axis, then use joint-axis to operate the rotary axis. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8f40ryeqdq3r3fws85vd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8f40ryeqdq3r3fws85vd.png" alt="Image description" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A. CONNREFRAME: Build Forward Kinematics Connection&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;--what is forward kinematics mode--&lt;/em&gt;&lt;br&gt;
Associate virtual-axis coordinate with joint-axis coordinate, when joint-axis moves, virtual-axis will automatically move to corresponding position.&lt;br&gt;
&lt;em&gt;--how to use command--&lt;/em&gt;&lt;br&gt;
CONNREFRAME(frame, tablenum, Axis_J1, Axis_J2, Axis_J3, Axis_J4)&lt;br&gt;
Frame: the type of coordinate system. (for example, 12 means the robotic arm is 4-axis Delta robot, please refer to Zmotion robot command manual).&lt;br&gt;
Tablenum: TABLE starting position that saves robotic arm structural parameters.&lt;br&gt;
Axis_J1: the first joint-axis axis No.&lt;br&gt;
Axis_J2: the second joint-axis axis No.&lt;br&gt;
Axis_J3: the third joint-axis axis No.&lt;br&gt;
Axis_J4: the fourth joint-axis axis No.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. CONNFRAME: Build Inverse Kinematics Connection&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;--what is inverse kinematics mode--&lt;/em&gt;&lt;br&gt;
Associate current joint-axis coordinate system demand position with virtual-axis coordinate system position. Please note the motion max speed of joint-axis coordinate system is limited by SPEED parameter. And when there is one alarm of joint-axis, the motion will be cancelled.&lt;br&gt;
&lt;em&gt;--how to use command--&lt;/em&gt;&lt;br&gt;
CONNFRAME(frame, tablenum, Axis_Vx, Axis_Vy, Axis_Vz, Axis_J4)&lt;br&gt;
Frame: the type of coordinate system. (for example, 12 means the robotic arm is 4-axis Delta robot, please refer to Zmotion robot command manual).&lt;br&gt;
Tablenum: TABLE starting position that saves robotic arm structural parameters.&lt;br&gt;
Axis_Vx: the first virtual-axis axis No.&lt;br&gt;
Axis_Vy: the second virtual-axis axis No.&lt;br&gt;
Axis_Vz: the third virtual-axis axis No.&lt;br&gt;
Axis_J4: the fourth virtual-axis axis No.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. How to Build Delta Robotic Arm Mode
&lt;/h2&gt;
&lt;h4&gt;
  
  
  (1) Forward Kinematics Connection
&lt;/h4&gt;

&lt;p&gt;Take Delta robotic arm Frame 12 as the example. At first, save robotic arm structural parameters into Table in order, starting from one certain Table No., then select corresponding model axis list, at last, use CONNREFRAME command to build the forward kinematics mode.&lt;br&gt;
For details of this command, please refer to “ZBasic Programming Manual”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'save robotic arm parameters into Table array in order starting from TableNum
TABLE(TableNum,Top_R,Under_R,Top_L,Under_L,OneCirPules_J1,OneCirPules_J2,OneCirPules_J3,Offset_X,Offset_Y,Offset_Z,OneCirPules_J4)
'select axes
BASE(Axis_Vx,Axis_Vy,Axis_Vz,Axis_J4)
'build robotic arm forward kinematics
CONNREFRAME(FrameType,TableNum,Axis_J1,Axis_J2,Axis_J3,Axis_J4)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the building succeeds, virtual axes’ MTYPE (current motion type) will become 34, now, only joint-axis can be operated in joint-axis coordinate to adjust the robotic arm attitude. In ZDevelop (RTSys), there is one “manual” tool, we can select joint-axis No. to do point or inch (here, we select axis 0, axis 1, and axis 2 joint axes, and axis 3 terminal rotate axis). At this time, virtual axis will automatically calculate the position of end working place in the Cartesian coordinate system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqa6yl4n6ogjro6hh33g8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqa6yl4n6ogjro6hh33g8.png" alt="Image description" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4qew2z4itdw21iew9ofg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4qew2z4itdw21iew9ofg.png" alt="Image description" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  (2) Inverse Kinematics Connection
&lt;/h4&gt;

&lt;p&gt;Take Delta robotic arm Frame 12 as the example. At first, save robotic arm structural parameters into Table in order, starting from one certain Table No., then select corresponding model axis list, at last, use CONNFRAME command to build the inverse kinematics mode.&lt;br&gt;
For details of this command, please refer to “ZBasic Programming Manual”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'save robotic arm parameters into Table array in order starting from TableNum
TABLE(TableNum,Top_R,Under_R,Top_L,Under_L,OneCirPules_J1,OneCirPules_J2,OneCirPules_J3,Offset_X,Offset_Y,Offset_Z,OneCirPules_J4)
'select axes
BASE(Axis_J1,Axis_J2,Axis_J3,Axis_J4) 
'build robotic arm forward kinematics
CONNFRAME(FrameType,TableNum,Axis_Vx,Axis_Vy,Axis_Vz,Axis_J4)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the building succeeds, joint axes’ MTYPE (current motion type) will become 33. “manual” also can be used here. Now, only virtual-axis can be operated by processing technology commands. That is, the trajectory edited before moves in the Cartesian coordinate system (here, take virtual axis 10, 11, 12 as the example), joint axis will automatically calculate how to do joint motion in the joint coordinate system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xjxkqygnh1eavbyxey8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xjxkqygnh1eavbyxey8.png" alt="Image description" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqg18eydvv4uczxuaoos.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqg18eydvv4uczxuaoos.png" alt="Image description" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. How to Operate?
&lt;/h2&gt;

&lt;h4&gt;
  
  
  (1) Edit the Program
&lt;/h4&gt;

&lt;p&gt;ZDevelop (RTSys) supports hybrid programming among Basic, HMI, and PLC. This routine matches Basic with HMI. For HMI, it can select “control” to drag and place for interacting the interface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhg9qvmmscdq5jtc58ukd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhg9qvmmscdq5jtc58ukd.png" alt="Image description" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this routine, define global SUB subfunction in BAS file at first, that is, edit sub-function’s function needs (project source codes can be referred at the end of this article), then use the control to bind, please note all controls’ actions select “calling function”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwc8w0xiea1e88jryue2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwc8w0xiea1e88jryue2k.png" alt="Image description" width="800" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A. Understand the Needs&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;--Condition--&lt;/em&gt;&lt;br&gt;
Delta robotic arm builds the inverse kinematics, and take the origin position as the reference to determine one safe height.&lt;br&gt;
&lt;em&gt;--Basic Actions--&lt;/em&gt;&lt;br&gt;
a. Delta moves up to above the fixed material in one certain safe height.&lt;br&gt;
b. Delta moves down, opens OP port to get the material by “vacuum suction”.&lt;br&gt;
c. Delay to move up to the safe height.&lt;br&gt;
d. Move to fixed 2*2 disk position.&lt;br&gt;
e. Down to disk position, close OP to place the material.&lt;br&gt;
f. Repeat above, until the disk is full.&lt;br&gt;
B. Process the Codes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'starting flag position 1
StartFlag = 1
LOCAL SafeHigh,i
'safe height
SafeHigh = DPOS(Axis_VList(2))-25
'row and colume
LOCAL Row,Col
'fixed material getting position
LOCAL SrcBorrow_X,SrcBorrow_Y,SrcBorrow_Z
SrcBorrow_X = 5
SrcBorrow_Y = 5
SrcBorrow_Z = SafeHigh-20
'select virtual axis
BASE(Axis_VList(0),Axis_VList(1),Axis_VList(2))
'set processing speed, acceleration, and deceleration
SPEED = SpeedVList(0)
ACCEL = AccelV(0)
DECEL = DecelV(0)
'open the continuous interpolation
MERGE = ON
'each on, temporary total numbers cleared 
TmpSum = 0
'move to the safe height (reference for origin position)
MOVEABS(0,0,SafeHigh)
FOR Col=1 TO 2
    FOR Row=1 TO 2
        'move to the position where is above the material placing position
        MOVEABS(SrcBorrow_X,SrcBorrow_Y,SafeHigh)
        'down to material getting place
        MOVEABS(SrcBorrow_X,SrcBorrow_Y,SrcBorrow_Z)
        'open OP to suck for getting the material
        MOVE_OP(8,ON)
        'delay
        MOVE_DELAY(300)
        'up to safe height
        MOVEABS(SrcBorrow_X,SrcBorrow_Y,SafeHigh)
        'move to the position where is above the disk that is for placing materials
        MOVEABS(-5*Row,5*Col,SafeHigh)
        'down to disk material placing position
        MOVEABS(-5*Row,5*Col,SrcBorrow_Z)
        'close OP to place the material
        MOVE_OP(8,OFF)
        'delay
        MOVE_DELAY(300)
        'up to safe height
        MOVEABS(-5*Row,5*Col,SafeHigh)
        'temporary total is added automatically
        TmpSum = TmpSum+1
    NEXT
NEXT
'wait until all axes stop
WAIT UNTIL IDLE(Axis_VList(0)) AND IDLE(Axis_VList(1)) AND IDLE(Axis_VList(2))
DELAY(10)
RAPIDSTOP(2)
DELAY(10)
'starting flag position 0
StartFlag = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  (2) Debug &amp;amp; Analyze
&lt;/h4&gt;

&lt;p&gt;A.Download the program into controller, then click &lt;strong&gt;“RTSys” – “Tool” – “Plugin” – “XPLC SCREEN”.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F565yl1ir8qcrdjrq4j4h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F565yl1ir8qcrdjrq4j4h.png" alt="Image description" width="538" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;B. In appeared interaction interface, select &lt;strong&gt;“Forward”&lt;/strong&gt; mode in main interface “mode” (robotic arm mode).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxx0c3v127gdi7o79qqcf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxx0c3v127gdi7o79qqcf.png" alt="Image description" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;C. After forward building, open Zmotion Robotic Arm Solution “ZRobotView”, click “connect”, one “connect to controller” window appears, then select controller connection method (serial port or ethernet). Here, we select ethernet, it only needs to select controller IP, then click “connect”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnebi9xb3we36keuoqbwo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnebi9xb3we36keuoqbwo.png" alt="Image description" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;D. Now, it shows current robotic arm type in the above, and robotic arm structural parameters that are saved in Table all can be checked in this simulation tool, and corresponding robotic arm model will be built.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjz9cx9t668rkl3ezlcux.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjz9cx9t668rkl3ezlcux.png" alt="Image description" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E. Open ZDevelop (RTSys) again, click *&lt;em&gt;“SCOPE” *&lt;/em&gt;(oscilloscope). In the “scope” window, please select XYZ mode, that is, obverse the effect in 3D. For data source, select DPOS (demand position) here, and select axis No. of virtual axes. When all these parameters are set, click “stop” – “start” – “trigger”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvp5we4jrw3533mg06ohi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvp5we4jrw3533mg06ohi.png" alt="Image description" width="800" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;F. Switch to interaction interface, select “inverse” mode to build the inverse kinematics, then click “ON” to process needed technologies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwh0he48zommarnkr0n4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwh0he48zommarnkr0n4.png" alt="Image description" width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;G. Return our programming software (ZDevelop / RTSys). In oscilloscope interface, processing effect is shown.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffaypcl6a3lhokyz7d043.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffaypcl6a3lhokyz7d043.png" alt="Image description" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can be seen Delta robotic arm always keeps moving up and down in one certain safe height in the process of getting and placing the material. In this way, real processing can be stable.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Develop EtherCAT Motion Control by LabView</title>
      <dc:creator>ZMOTION CONTROLLER</dc:creator>
      <pubDate>Tue, 29 Oct 2024 10:08:32 +0000</pubDate>
      <link>https://dev.to/zmotion_controller/develop-ethercat-motion-control-by-labview-284p</link>
      <guid>https://dev.to/zmotion_controller/develop-ethercat-motion-control-by-labview-284p</guid>
      <description>&lt;p&gt;If you master PC Labview knowledge, you can develop EtherCAT motion control and capture data in real-time easily.&lt;br&gt;
Let's see how to do that.&lt;br&gt;
Here, take one &lt;a href="http://www.zmotionglobal.com/pro_list_83.html" rel="noopener noreferrer"&gt;EtherCAT Motion Controller&lt;/a&gt; as the example.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. How to Develop Motion Control by LabVIEW?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  (1) Build LabVIEW Project
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i6blezcgpjqa5ttco2a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i6blezcgpjqa5ttco2a.png" alt="Image description" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  (2) Download "zauxdll" folder of LabVIEW Vi function library into PC, then copy it into "LabVIEW/user.lib".
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.zmotionglobal.com/download_list_15.html" rel="noopener noreferrer"&gt;Labview function library file&lt;/a&gt; and corresponding development examples can be obtained.&lt;/p&gt;

&lt;h3&gt;
  
  
  (3) PC Function | Related Interfaces
&lt;/h3&gt;

&lt;p&gt;Zmotion provides general API function, it includes all kinds of host computer languages.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A. ZAux_OpenEth(): connection&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3d8tfcb61qfawe30w6d8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3d8tfcb61qfawe30w6d8.png" alt="Image description" width="625" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;B. ZAux_Direct_GetTable: get data from table, and import oscillocope data source&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84f2f1we7n2izltk5zpa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84f2f1we7n2izltk5zpa.png" alt="Image description" width="624" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;C. ZAux_Direct_GetDpos: get DPOS (demand position)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9t7vlq7be4ubatakpk1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9t7vlq7be4ubatakpk1.png" alt="Image description" width="627" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;D. ZAux_Direct_GetMspeed: get feedback speed&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0up37x1hk9uuthjvhka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0up37x1hk9uuthjvhka.png" alt="Image description" width="625" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;E. ZAux_Direct_GetVpSpeed: get planning speed&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frt2v8ccp34qzrfl9arof.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frt2v8ccp34qzrfl9arof.png" alt="Image description" width="625" height="856"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;F. ZAux_Direct_GetMpos: get MPOS (measurement position)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmr5m3ttktftoijt7kdz4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmr5m3ttktftoijt7kdz4.png" alt="Image description" width="625" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;G. ZAux_Direct_Cam: do eletronic cam motion&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpqnjqc295wppv16m9xta.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpqnjqc295wppv16m9xta.png" alt="Image description" width="628" height="887"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  (4) How to Get Real-Time Data
&lt;/h3&gt;

&lt;p&gt;A. creat new vi in front board, and right click the mouse to select "control" to do UI designning, as it is shown in the below, the left is "connection" interface, the right is planning position of oscilloscope.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwa7k4owrwr20trjib2g6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwa7k4owrwr20trjib2g6.png" alt="Image description" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;B. add "while" loop in added frame through mouse, then add "event structure" in "while", and right click to choose "add event branch", the "timeout" event, then get current needed data and import them into oscilloscope.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fszgoch38ex4ye03mle7i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fszgoch38ex4ye03mle7i.png" alt="Image description" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;C. select event structure, and right-click to select "add event branch". In "while" structure, when the handle is blank, it will automatically get current controller IP, then use "Z Aux Open Eth.vi" function to connect to controller.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ntxj8fa0jsdjeg6ofxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ntxj8fa0jsdjeg6ofxf.png" alt="Image description" width="800" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;D. select event structure, and right-click to select "add event branch", the "disconnect" value changing, then use "Z Aux Close.vi" function to disconnect the connection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffpdo19shj3k76vvde9cg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffpdo19shj3k76vvde9cg.png" alt="Image description" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E. select event structure, and right-click to select "add event branch", the "trigger" value changing, then use "Z Aux Trigger.vi" function to trigger oscillscope to capture the data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggn6vjh75qx6nercrb30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggn6vjh75qx6nercrb30.png" alt="Image description" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;F. select event structure, and right-click to select "add event branch", the "ON SCOPE " value changing, then use "Z Aux Execute.vi" function to call "SCOPE" command to open data acquisition, and save them into table register.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzje5yqfp5tn67rf5r53h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzje5yqfp5tn67rf5r53h.png" alt="Image description" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91bt18xyj40t5u067hbn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91bt18xyj40t5u067hbn.png" alt="Image description" width="622" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;G. select event structure, and right-click to select "event", the "XY Graphic:" mouse changing . Then in this event branch, the coordinate position of the mouse within the corresponding range of the XY oscilloscope and the XY2 oscilloscope is read in real time and displayed on the interface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjvv5lj18nlwuovh00uyx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjvv5lj18nlwuovh00uyx.png" alt="Image description" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfhja7galkn98fq1fgdm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfhja7galkn98fq1fgdm.png" alt="Image description" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;H. select the condition structure. When the sine motion button is pressed, the two sine motions execute the two electronic cam motion commands in the sequence of tiling. Use the "Z Aux Cam.vi" function to move corresponding electronic cam motions according to data that has been loaded in table register in advance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ios35f68n4r9fnq8q88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ios35f68n4r9fnq8q88.png" alt="Image description" width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Debug &amp;amp; Watch
&lt;/h2&gt;

&lt;p&gt;Compile the routine, and connect to ZDevelop / &lt;a href="https://www.zmotionglobal.com/pro_info_282.html" rel="noopener noreferrer"&gt;RTSys&lt;/a&gt; at the same time. Then run one "SIN" waveform trajectory through the corresponding single-axis routine. When the motion is running, capture the real-time data through LabVIEW oscillocope and ZDevelop oscilloscope synchronously.&lt;/p&gt;

&lt;h3&gt;
  
  
  (1) Algorithm Command: generate SIN waveform data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DIM  num_p,scale,m,t   'define variable
num_p=100
scale=500
FOR p=0 TO num_p
    TABLE(p,((-SIN(PI*2*p/num_p)/(PI*2))+p/num_p)*scale) 'save cam motion parameters into table
NEXT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (2) Waveform Comparison
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A. ZDevelop and LabVIEW captures DPOS demand position.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;--ZDevelop Oscilloscope Waveform--&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3nrxjijm0aufe9osbvli.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3nrxjijm0aufe9osbvli.png" alt="Image description" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;--LabVIEW Oscilloscope Waveform--&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0pmixtvuiqxdfayfihgw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0pmixtvuiqxdfayfihgw.png" alt="Image description" width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can be seen they are consistent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. ZDevelop and LabVIEW captures VP_SPEED.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyp2ngoj8sgzlaygodbat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyp2ngoj8sgzlaygodbat.png" alt="Image description" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, their waveforms are the same.&lt;/p&gt;

&lt;p&gt;That's all, thank you for your reading -- &lt;a href="https://www.zmotionglobal.com/support_info_131.html" rel="noopener noreferrer"&gt;EtherCAT Motion Controller LabVIEW Motion Control Development &amp;amp; Real-Time Data Reading. &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article is edited by ZMOTION, here, share with you, let's learn together.&lt;/p&gt;

&lt;p&gt;Note: Copyright belongs to Zmotion Technology, if there is reproduction, please indicate article source. Thank you.&lt;/p&gt;

&lt;p&gt;Have a good day, best wishes, see you next time.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>labview</category>
    </item>
    <item>
      <title>How to Develop EtherCAT Motion Controller on ROS (2)</title>
      <dc:creator>ZMOTION CONTROLLER</dc:creator>
      <pubDate>Tue, 22 Oct 2024 08:37:29 +0000</pubDate>
      <link>https://dev.to/zmotion_controller/how-to-develop-ethercat-motion-controller-on-ros-2-1bln</link>
      <guid>https://dev.to/zmotion_controller/how-to-develop-ethercat-motion-controller-on-ros-2-1bln</guid>
      <description>&lt;p&gt;In last article, we have known ROS background, how to install ROS Melodic by Ubuntu18.04, and two ROS programming examples. Please visit &lt;a href="http://www.zmotionglobal.com/support_info_129.html" rel="noopener noreferrer"&gt;“How to Develop EtherCAT Motion Controller on ROS (1)”&lt;/a&gt; for details.&lt;/p&gt;

&lt;p&gt;Then, today, the second part is coming, that is, how to configure Zmotion dynamic library environment, and how one single-axis of &lt;a href="http://www.zmotionglobal.com/pro_list_83.html" rel="noopener noreferrer"&gt;EtherCAT motion controller&lt;/a&gt; on &lt;a href="https://en.wikipedia.org/wiki/Robot_Operating_System" rel="noopener noreferrer"&gt;ROS&lt;/a&gt; is.&lt;/p&gt;

&lt;p&gt;Still, the hardware takes &lt;a href="http://www.zmotionglobal.com/pro_info_135.html" rel="noopener noreferrer"&gt;ZMC432-V2&lt;/a&gt; &amp;amp; &lt;a href="http://www.zmotionglobal.com/pro_info_268.html" rel="noopener noreferrer"&gt;ZMC408CE&lt;/a&gt;. They can be used in offline or online occasions.&lt;/p&gt;

&lt;p&gt;For development, both use one same set of API function, C, C++, C#, LabVIEW, Python, Delphi all can be used, and mainstream platforms and operation systems all are valid, which means it is easy and convenient to develop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jmy09p6tlpxnasq23wo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jmy09p6tlpxnasq23wo.png" alt="Image description" width="800" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Configure Zmotion Dynamic Link Library Environment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  (1)   Add Dynamic Link Library
&lt;/h3&gt;

&lt;p&gt;New build folder "lib" under "content" -- zmotion(catkin_ws/src/zmotion/) of program package, and save dynamic link library "libzmotion.so".  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9zb9j0r3v24kbslbu3s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9zb9j0r3v24kbslbu3s.png" alt="Image description" width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxv3zfvirixmc7vxl8sg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxv3zfvirixmc7vxl8sg.png" alt="Image description" width="800" height="572"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A. add the third party path (under build) in CMakeLists.txt&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;link_directories(
lib
${catkin_LIB_DIRS}
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;B. also, link dynamic link library in CMakeLists,txt file(when calling the link libaray, remember to remove lib and .so)&lt;br&gt;
&lt;code&gt;target_link_libraries(talker ${catkin_LIBRARIES} zmotion)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;(2)   Add Library Function “zmcaux.cpp”, “zmotion.h”, “zmcaux.h”&lt;/p&gt;

&lt;p&gt;A. add zmcaux.cpp file into "catkin_ws/src/zmotion/src"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fznn9jx4xrwtur31n7mrq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fznn9jx4xrwtur31n7mrq.png" alt="Image description" width="800" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;B. add head file "zmotion.h and zmcaux.h" into "catkin_ws/src/zmotion/include/ zmotion"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3eh4efn7uf7528axghac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3eh4efn7uf7528axghac.png" alt="Image description" width="800" height="575"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;C. and add these three library files in CMakeLists.txt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;add_executable(talker
src/talker.cpp
src/zmcaux.cpp
include/zmotion/zmotion.h
include/zmotion/zmcaux.h
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;D. modify head file's quote, like below image (need to fill corresponding address of "include" file, zmotion is the name of program package)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include "zmotion/zmotion.h"
#include "zmotion/zmcaux.h"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpz32i797w353mpzidoaf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpz32i797w353mpzidoaf.png" alt="Image description" width="593" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Zmotion Controller Single-Axis Motion by ROS
&lt;/h2&gt;

&lt;p&gt;“talker” node achieves axis 0 motion, and real time sends the position to “listener” node, then modifies "talker.cpp":&lt;/p&gt;

&lt;h3&gt;
  
  
  (1) Add Handle &amp;amp; Head File
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include "zmotion/zmotion.h"
#include "zmotion/zmcaux.h"
ZMC_HANDLE g_handle=NULL;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (2) Connect to Motion Controller Through EtherNET
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ZMC_LinuxLibInit();
//EtherNET (Ethernet) to link
char ipaddr[16] = {"192.168.0.11"};
int x =ZAux_OpenEth(ipaddr,&amp;amp;g_handle); //***ZMC
ROS_INFO("connect to controller through Ethernet:%d",x);//Return 0 -- success
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (3) Single-Axis Motion
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ZAux_Direct_SetSpeed(g_handle, 0, 200); //set axis 0 motion speed as 200units/s
ZAux_Direct_SetAccel(g_handle, 0, 2000); //set axis 0 acceleration as 2000units/s/s
ZAux_Direct_SetDecel(g_handle, 0, 2000); //set axis 0 deceleration as 2000units/s/s
ZAux_Direct_SetSramp(g_handle, 0, 100); //set axis 0 S curve time as 100ms
ZAux_Direct_Single_Move(g_handle, 0, 300); //axis 0 moves 100 units that relates to current position
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (4) Send Real-Time Position to “listener” Node
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;float piValue;
while (ros::ok())
{
    std_msgs::Float64 msg;
    ZAux_Direct_GetMpos(g_handle, 0, &amp;amp; piValue);//read time
    msg.data = piValue;
    //output, used to replace prinf/cout
    ROS_INFO("Position is: %f", msg.data);
    chatter_pub.publish(msg);
    ros::spinOnce();
    //sleep, make publishment frequency as 10Hz
    loop_rate.sleep();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (5) Compile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ~/catkin_ws/
catkin_make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (6) Run the Program
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//open one new end station
roscore
//open another new end station
cd ~/catkin_ws/
rosrun zmotion talker
//open another new end station
cd ~/catkin_ws/
rosrun zmotion listener
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Following is the running effect, real-time output position:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdqhqk0tkuokvmt3g93a5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdqhqk0tkuokvmt3g93a5.png" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In addition, it can be seen that axis 0 is running S curve motion from the oscilloscope.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fynybfoftihriorvq4gvv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fynybfoftihriorvq4gvv.png" alt="Image description" width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's all, thank you for your reading -- &lt;a href="https://www.zmotionglobal.com/support_info_130.html" rel="noopener noreferrer"&gt;How to Develop EtherCAT Motion Controller on ROS (2)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have a good day, best wishes, see you next time.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>ros</category>
    </item>
    <item>
      <title>How to Develop EtherCAT Motion Controller on ROS (1)</title>
      <dc:creator>ZMOTION CONTROLLER</dc:creator>
      <pubDate>Fri, 18 Oct 2024 05:56:19 +0000</pubDate>
      <link>https://dev.to/zmotion_controller/how-to-develop-ethercat-motion-controller-on-ros-1-3gi1</link>
      <guid>https://dev.to/zmotion_controller/how-to-develop-ethercat-motion-controller-on-ros-1-3gi1</guid>
      <description>&lt;p&gt;It can be referred from the title, this article will talk about “How to Develop EtherCAT Motion Controller on ROS”. And here takes ZMC432-V2 EtherCAT Motion Controller as the example.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What Is ROS ?
&lt;/h2&gt;

&lt;p&gt;ROS (robot operating system) is one operating system (secondary operating system) after opening source for robots. The main aim is to promote code reuse ration in the field of robotic R&amp;amp;D.&lt;/p&gt;

&lt;p&gt;ROS is a processing frame of distributed type (also can be called as Nodes), then execution files can be designed independently and they can loosen couple while running. In addition, these processes can be encapsulated into data packages (Packages) and stack (Stacks) for sharing and distributing.&lt;/p&gt;

&lt;p&gt;What's more, ROS supports joint system of code library, then cooperation also can be distributed. In this way, this kind of design (from file system level to community level) makes it possible to independently determine development and implement work. All above functions are achieved through ROS basic tools.&lt;/p&gt;

&lt;p&gt;Simply, ROS as a kind of flexible operating system, it is really random on system nodes, they can be located in different PC, even in different Ethernet. Then, we can use one Arduino as one node to post message, and use one laptop as one node to subscribe above information and use one phone as one node to drive motor. Therefore, it can be seen ROS can be applied in all kinds of occasions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frkppzjwv1uag317065u6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frkppzjwv1uag317065u6.png" alt="Image description" width="698" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  (1)    ROS Main Features
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A. Distributed &amp;amp; Point to Point&lt;/strong&gt;&lt;br&gt;
The point to point design of ROS and mechanisms such as service and node managers can disperse the real-time computing pressure brought by functions of PC vision and audio recognition, which can adapt to the challenges encountered by multi-robots.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figvdmcjl6edw3x6cdw96.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figvdmcjl6edw3x6cdw96.png" alt="Image description" width="541" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. Multiple Program Languages&lt;/strong&gt;&lt;br&gt;
ROS supports several kinds of programming languages, such as, C++, Python, Octave, and LISP. Also, it includes multiple kinds of interfaces of other languages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwots9c9tsa4x9np75ry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwots9c9tsa4x9np75ry.png" alt="Image description" width="654" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C. Simplification &amp;amp; Integration&lt;/strong&gt;&lt;br&gt;
Systems built by ROS are modular, and codes in each module can be compiled independently. And "simplification" theory can be easily achieved through "CMake" tool (for compiling).&lt;br&gt;
And complex codes are encapsulated into the library by ROS. It only builds some application programs to show library, which means it allows simple codes that exceed prototype to be transplanted and reused.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;D. Rich Tool Package&lt;/strong&gt;&lt;br&gt;
To manage complicated ROS software framework, we use a lot of small tools to compile and run all kinds of ROS components. Then, the kernel is designed, namely, it is not to build a huge development and running environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnvl55u62ypxfjbluklhb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnvl55u62ypxfjbluklhb.png" alt="Image description" width="500" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E. Free &amp;amp; Open Source&lt;/strong&gt;&lt;br&gt;
All source codes of ROS are released in public.&lt;/p&gt;
&lt;h3&gt;
  
  
  (2)    ROS Applications
&lt;/h3&gt;

&lt;p&gt;In recent years, domestic and foreign robot enterprises, driverless enterprises, and drone enterprises (DJI drones) all have joined the ROS. Now actually many enterprises need engineers who knows or masters ROS knowledge. Then it can be known ROS is popular increasingly. Please see below ROS typical applications.&lt;br&gt;
A. “Boss" in robot controllers -- KEBA , their controllers support ROS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyileqhlew4pwe412amc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyileqhlew4pwe412amc.png" alt="Image description" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;B. Robonaut 2 developed based on ROS by USA NASA has been already working on the International Space Station.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsubea1qbvlosbrd81h7t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsubea1qbvlosbrd81h7t.png" alt="Image description" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;C. The bottom layer of Baidu's Apollo unmanned vehicle is developed based on ROS. It can be found on github (apollo-platform).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffij1qvfa48ovqnahobql.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffij1qvfa48ovqnahobql.png" alt="Image description" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;D. ROS-I prepares to cooperate with Microsoft and BMW to develop a set of automation solutions (Reference: A ROS-Industrial Collaboration with Microsoft and BMW).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58f8kekoiu40aznsk8y4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58f8kekoiu40aznsk8y4.png" alt="Image description" width="657" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E.  Many industrial robotic arms use ROS system. Among them, the 5th anniversary video officially released by ROS-I at the end of 2017 is full of robots in the four major families. The KUKA youbot robot in the picture below is developed by using the ROS system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6q2k40qlg3r9f98c5unv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6q2k40qlg3r9f98c5unv.png" alt="Image description" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  2. How to Install the Software ?
&lt;/h2&gt;

&lt;p&gt;This part mainly talks about the detailed process of installing ROS Melodic on Ubuntu 18.04 (this article takes Ubuntu 18.04 as an example, the same is true for others, and it does not affect the use of motion controller).&lt;/p&gt;
&lt;h3&gt;
  
  
  (1)    Set “sources.list”
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo sh -c '. /etc/lsb-release &amp;amp;&amp;amp; echo "deb
http://mirrors.ustc.edu.cn/ros/ubuntu/ $DISTRIB_CODENAME main" &amp;gt;
/etc/apt/sources.list.d/ros-latest.list'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  (2)    Set “key” (key is updated)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key
421C365BD9FF1F717815A3895523BAEEB01FA116
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feftlvgmemast2cf670j3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feftlvgmemast2cf670j3.png" alt="Image description" width="680" height="150"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  (3)    Update “package” (maybe a long time, please wait a moment)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;$ sudo apt-get update&lt;/code&gt;&lt;br&gt;
At this time, it may meet following questions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrzkg9znwhup4xmgr0sj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrzkg9znwhup4xmgr0sj.png" alt="Image description" width="543" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Solution is following, enter in end:&lt;br&gt;
&lt;code&gt;$sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key F42ED6FBAB17C654&lt;br&gt;
$ sudo apt-get update&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zu06382s8oehttqc1vq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zu06382s8oehttqc1vq.png" alt="Image description" width="544" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When “Reading package lists … Done” appears, which means updating succeeds.&lt;/p&gt;
&lt;h3&gt;
  
  
  (4)    Install “ROS melodic” (full version)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;$ sudo apt-get install ros-melodic-desktop-full&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  (5)    Initialize “rosdep”
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$sudo rosdep init
$rosdep update
$echo "source /opt/ros/melodic/setup.bash" &amp;gt;&amp;gt; ~/.bashrc
$ source ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Effects:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F53esrk7g2whp6g6wuifl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F53esrk7g2whp6g6wuifl.png" alt="Image description" width="546" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gvqr60y869a9e64gtk6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gvqr60y869a9e64gtk6.png" alt="Image description" width="545" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you meet following problems when input the instruction "sudo rosdep init":&lt;br&gt;
A. sudo: rosdep: command not found&lt;br&gt;
Enter in the terminal: sudo apt install rospack-tools&lt;br&gt;
B. ERROR:  cannot download default sources list from: &lt;a href="https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/sources.list.d/20-default.list" rel="noopener noreferrer"&gt;https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/sources.list.d/20-default.list&lt;/a&gt; Website may be down.&lt;br&gt;
--enter "sudo gedit /etc/hosts" in the terminal, then open hosts file--&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlopabei3bdsuv10am29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlopabei3bdsuv10am29.png" alt="Image description" width="535" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;--add "199.232.28.133 raw.githubusercontent.com" in the file, and new file added as follow--&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feeb2laqvniq7bfw1o0m1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feeb2laqvniq7bfw1o0m1.png" alt="Image description" width="547" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;--save file and exit--&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh8dz2kz60ceg720elki3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh8dz2kz60ceg720elki3.png" alt="Image description" width="692" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;--execute “sudo rosdep init” in the terminal, then problem is solved--&lt;/p&gt;
&lt;h3&gt;
  
  
  (6)    test whether ROS is installed successfully or not
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;$ roscore&lt;/code&gt;&lt;br&gt;
If it is successful, like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7hznnp9a6j0t9ps7y5v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7hznnp9a6j0t9ps7y5v.png" alt="Image description" width="547" height="525"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. ROS Programming Examples
&lt;/h2&gt;

&lt;p&gt;There are mainly two ROS routines, “message publish” and “subscription”.&lt;/p&gt;
&lt;h3&gt;
  
  
  (1)    Build One ROS Work Space
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$mkdir -p ~/catkin_ws/src
$cd ~/catkin_ws/
$ catkin_make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  (2)    Create One ROS Program Package (zmotion is the package name, it can be defined as others)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$cd ~/catkin_ws/src
$catkin_create_pkg zmotion std_msgs roscpp
$cd ~/catkin_ws
$ catkin_make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  (3)    After Creating the Program Package, “source ~ / catkin_ws / devel / setup.bash is required in each running, otherwise the file cannot be found.
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enter in the terminal:
$ gedit ~/.bashrc
add at the end of the file and save
$ source ~/catkin_ws/devel/setup.bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  (4)    New Build One Node File
&lt;/h3&gt;

&lt;p&gt;Create a src directory in the zmotion package directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ~/catkin_ws/src/zmotion   //enter the ZMotion package path
$ mkdir -p src   //new build the src folder for saving c++ program
$ cd src/   // enter the src folder path
$ touch talker.cpp   //create a new publishment message node cpp file
$ touch listener.cpp   //create a new subscription message node cpp file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (5)    Edite “Publish Node” (talker.cpp)
&lt;/h3&gt;

&lt;p&gt;Functions to be achieved:&lt;br&gt;
--initialize ROS system&lt;br&gt;
--publish message of std_msgs/Float64 on chatter topic&lt;br&gt;
--publish the message in 10 times/s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include "ros/ros.h"
#include "std_msgs/Float64.h"
#include &amp;lt;sstream&amp;gt;
int main(int argc, char **argv)
{
//Initialize ROS, name remapping (unique), it must be base name, excluding/
ros::init(argc, argv, "talker"); 
//build one handle for node of processing, the first built NodeHandle is the initialization node.
ros::NodeHandle n;
//tell host computer publish one std_msgs message in chatter topic
//main computer will subscribe all nodes of chatter topic, parameter means the size of published array (input firstly, then output)
ros::Publisher chatter_pub = n.advertise("chatter", 1000);
ros::Rate loop_rate(10);  //self-cycle frequency
int count = 0;
while (ros::ok())
{
std_msgs::Float64 msg;
             msg.data = count*1.0;
             //output, replace prinf/cout
             ROS_INFO("Position is: %f", msg.data); 
chatter_pub.publish(msg);
ros::spinOnce();
             //sleep, make publish frequency is 10Hz
             loop_rate.sleep();
             ++count;
           }
           return 0;
         }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (6)    Edit “Subscript Node” (listener.cpp)
&lt;/h3&gt;

&lt;p&gt;Functions to be achieved:&lt;br&gt;
--initialize ROS system&lt;br&gt;
--subscript message of chatter topic&lt;br&gt;
--enter self-cycle, waiting for message&lt;br&gt;
--message arrived, call chatterCallback() function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include "ros/ros.h"
#include "std_msgs/Float64.h"
//callback function
void chatterCallback(const std_msgs::Float64::ConstPtr&amp;amp; msg)
{
ROS_INFO("I heard: %f", msg-&amp;gt;data);
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");
ros::NodeHandle n;
//tell master to subscribe chatter topic message.
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
ros::spin(); //self-cycle frequency
return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (7)    Modify “CMakeLists.txt”
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;A. Open the path of program package "zmotion(catkin_ws/src/zmotion)", find the file "CMakeLists.txt".&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lgjsexvs9p71qc46216.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lgjsexvs9p71qc46216.png" alt="Image description" width="653" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;B. The lowest version is modified as 2.8.3&lt;/em&gt;&lt;br&gt;
&lt;code&gt;cmake_minimum_required(VERSION 2.8.3)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;C. Find the file "find_package", and add the dependent package "message_generation".&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
message_generation
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;D. Make sure "generate_message" that is called.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;generate_messages(
DEPENDENCIES
std_msgs
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;E. Make sure dependent of this message is added in dependent when running.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;catkin_package(
# INCLUDE_DIRS include
# LIBRARIES beginner_tutorials
# CATKIN_DEPENDS roscpp std_msgs
# DEPENDS system_lib
CATKIN_DEPENDS message_runtime
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;F. Modify the configuration under "build".&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flz2yiiw1c4filbtsiwgz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flz2yiiw1c4filbtsiwgz.png" alt="Image description" width="595" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;--comment "include" in include_directories.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3fs3zicc03jy9tpdefhs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3fs3zicc03jy9tpdefhs.png" alt="Image description" width="593" height="122"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;include_directories(
include
${catkin_INCLUDE_DIRS}
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;--add below codes in assigned position, following codes can be added in "build" randomly. It is better to add in relative positions for good appearance. It takes effect as long as it is added in the "build".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;add_executable(talker src/talker.cpp)
add_executable(listener src/listener.cpp)
add_dependencies(talker $zmotion_generate_messages_cpp)//Zmotion is package name
target_link_libraries(talker
${catkin_LIBRARIES}
)
target_link_libraries(listener
${catkin_LIBRARIES}
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2pwauk30zzfy4s6vhqg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2pwauk30zzfy4s6vhqg.png" alt="Image description" width="692" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;a. at last, list full CMakeLists.txt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cmake_minimum_required(VERSION 2.8.3)
project(zmotion)
find_package(catkin REQUIRED COMPONENTS
  roscpp
  std_msgs
  message_generation
)
## Generate added messages and services with any dependencies listed here
generate_messages(
   DEPENDENCIES
   std_msgs
)
###################################
## catkin specific configuration ##
###################################
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES zmotion
# CATKIN_DEPENDS roscpp std_msgs
# DEPENDS system_lib
CATKIN_DEPENDS message_runtime
)
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
  include
  ${catkin_INCLUDE_DIRS}
)
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(talker src/talker.cpp)
add_executable(listener src/listener.cpp)
## Rename C++ executable without prefix
add_dependencies(talker $zmotion_generate_messages_cpp)
## Specify libraries to link a library or executable target against
target_link_libraries(talker
   ${catkin_LIBRARIES}
)
target_link_libraries(listener
   ${catkin_LIBRARIES}
)

b. modify “package.xml” file.
&amp;lt;!-- build dependent. Select one between following two, or both are entered --&amp;gt;
&amp;lt;build_depend&amp;gt;message_generation&amp;lt;/build_depend&amp;gt;
&amp;lt;build_export_depend&amp;gt;message_generation&amp;lt;/build_export_depend&amp;gt;
&amp;lt;!-- Execute dependent, below must be added: --&amp;gt;
&amp;lt;exec_depend&amp;gt;message_runtime&amp;lt;/exec_depend&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;c. Compile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ~/catkin_ws
$ catkin_make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;d. Run the Program&lt;br&gt;
--open one new end station, turn on the ROS system--&lt;br&gt;
&lt;code&gt;$ roscore&lt;/code&gt;&lt;br&gt;
--open one new end station, run “publish node”--&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ~/catkin_ws   //enter work widget content
$ rosrun zmotion talker   //run “publish node” program
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;--open one new end station, run “subscript node”--&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ~/catkin_ws
$ rosrun zmotion listener
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;--Result--&lt;br&gt;
&lt;em&gt;results of “Publish Node”&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO] [WallTime: 1314931831.774057] Position is: 1.000000
[INFO] [WallTime: 1314931832.775497] Position is: 2.000000
[INFO] [WallTime: 1314931833.778937] Position is: 3.000000
[INFO] [WallTime: 1314931834.782059] Position is: 4.000000
[INFO] [WallTime: 1314931835.784853] Position is: 5.000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;results of “Subscript Node”&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO] [WallTime: 1314931970.262246] I heard: 1.000000
[INFO] [WallTime: 1314931971.266348] I heard: 2.000000
[INFO] [WallTime: 1314931972.270429] I heard: 3.000000
[INFO] [WallTime: 1314931973.274382] I heard: 4.000000
[INFO] [WallTime: 1314931974.277694] I heard: 5.000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ABOUT ZMOTION&lt;br&gt;
That's all, thank you for your reading -- &lt;a href="https://www.zmotionglobal.com/support_info_129.html" rel="noopener noreferrer"&gt;How to Develop EtherCAT Motion Controller on ROS (1)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ros</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
