title: How to control a robotic arm with arduino via uart (WLKATA STUDIO Mirobot)
body: <p>I am currently trying to control my robotic arm with my arduino using the uart interface. I have connected GND, Vin, Rx and Tx to the controller of the robot arm. I also got the library for the robot arm. But there were errors in it which I could correct.
  Now I wanted to start the program but it always breaks off at the same point, namely when he wants to perform the first movement. You can find the code example and more informations <a href="https://document.wlkata.com/?doc=/multifunctional-extender-box-user-manual/4-extender-box-function/" rel="nofollow noreferrer">here</a></p>
  <p>My Arduino sketch looks like</p>
  <pre><code>/*
   * Use Serial2 serial port to communicate with the manipulator
   */
  
  #include &lt;Mirobot.h&gt;  // Include header file
  UART_Mirobot myrobot; // Create a robotic arm object
  
  void setup(){
    Serial.begin(9600); // Initialize the serial port at the baud rate of 9600
    myrobot.serialInit(2);  // Set Serial2 to communicate with the manipulator at baud rate of 115200；
    myrobot.setSerialMonitoring(ON);  // Enabling Serial Port Monitoring
    while(myrobot.getStatus() != Idle &amp;&amp; myrobot.getStatus() != Alarm); // Determine whether the robotic arm can receive commands
    myrobot.sendMsg(&quot;$H&quot;,OFF); // The robotic arm reset
    while(myrobot.getStatus() != Idle); // Wait for the robotic arm to complete reset and become idle
    myrobot.setMoveSpeed(3000); // Set the maximum movement speed of the manipulator at 3000
    myrobot.moveJoints(-90,10,-90,60,10,10);  // Control the manipulator to move 1-6 axis to (-90°, 10°, -90°, 60°, 10°, 10°) position
    myrobot.zero(); // The manipulator moves to its initial position
    myrobot.movePose(198,0,230.05,0,-60,0); // Control the end of the manipulator to move to XYZ（198,0,230.05），RPY（0,-60,0）position
    myrobot.movePose(0,-100,-100,0,60,0,INC,MOVL);  // Control the end of the manipulator in coordinate mode with relative position of linear interpolation motion
    myrobot.movePose(250,0,100,0,0,0);
    myrobot.moveArc(200,0,100,60,ABS,CCW);  // control manipulator moves along a section of arc (inferior arc) with a radius of 60mm at the tangent point xyz (200,0,100) with the current coordinate point;
    myrobot.gripper(ON);  // gripper open
    myrobot.timedPause(2.5);  // waiting 2.5s
    myrobot.gripper(OFF);
    myrobot.zero();
    myrobot.timedPause(0.5);
    myrobot.runFile(&quot;test&quot;);  // Run the Gcode file &quot;test.gcode&quot; stored in the controller.
    myrobot.homing(2);
  }
  
  void loop(){
  
  }
  </code></pre>
  <p>The Mirobot library are</p>
  <pre><code>#include &quot;Mirobot.h&quot;
  
  class HardwareSerial;
  HardwareSerial *serial;
  
  UART_Mirobot::UART_Mirobot(){
  }
  
  void UART_Mirobot::serialInit(int serialPort){
    commMode = 0;
    mirobotSerialPort = serialPort;
    switch(mirobotSerialPort){
      case 0: serial = &amp;Serial; break;
      case 1: serial = &amp;Serial1; break;
      case 2: serial = &amp;Serial2; break;
      case 3: serial = &amp;Serial3; break;
      default:serial = &amp;Serial; break;
    }
    serial-&gt;begin(115200);
  }
  
  void UART_Mirobot::setSerialMonitoring(bool mode){
    serialMonitoringMode = mode;
  }
  
  void UART_Mirobot::homing(int homingMode){
    setCmdTimeout(30000);
    switch(homingMode){
      case 1: sendMsg(&quot;$H1\nF2000&quot;); break;
      case 2: sendMsg(&quot;$H2\nF2000&quot;); break;
      case 3: sendMsg(&quot;$H3\nF2000&quot;); break;
      case 4: sendMsg(&quot;$H4\nF2000&quot;); break;
      case 5: sendMsg(&quot;$H5\nF2000&quot;); break;
      case 6: sendMsg(&quot;$H6\nF2000&quot;); break;
      case 7: sendMsg(&quot;$H7\nF2000&quot;); break;
      default: sendMsg(&quot;$H\nF2000&quot;); break;
    }
    setCmdTimeout(10000);
  }
  
  void UART_Mirobot::setMoveSpeed(int velocity){
    mirobotVelocity = velocity;
    sendMsg(&quot;F&quot; + String(velocity));
  }
  
  void UART_Mirobot::setJumpPara(int height){
    String strCmd = &quot;$49=&quot; + String(height);
    sendMsg(strCmd);
  }
  
  void UART_Mirobot::timedPause(float seconds){
    String strCmd = &quot;G04 P&quot;;
    String strPara = String(seconds,3);
    sendMsg(strCmd + strPara);
  }
  
  void UART_Mirobot::zero(){
  //  sendMsg(&quot;$M&quot;);
    sendMsg(&quot;M21 G90 G01 X0 Y0 Z0 A0 B0 C0&quot;);
  }
  
  void UART_Mirobot::moveJoints(float j1, float j2, float j3, float j4, float j5, float j6, bool motionMode){
    String strCmd = &quot;M21 G00 &quot;;
    if(motionMode) strCmd.concat(&quot;G90 &quot;);
    else strCmd.concat(&quot;G91 &quot;);
    String strParam = &quot;X&quot;+String(j1, 2)+&quot; Y&quot;+String(j2, 2)+&quot; Z&quot;+String(j3, 2)+&quot; A&quot;+String(j4, 2)+&quot; B&quot;+String(j5, 2)+&quot; C&quot;+String(j6, 2);
    strCmd.concat(strParam);
    sendMsg(strCmd);
  }
  
  void UART_Mirobot::movePose(float x, float y, float z, float rx, float ry, float rz, bool motionMode, int pathMode){
    String strCmd = &quot;M20 &quot;;
    switch(pathMode){
      case MOVJ: strCmd.concat(&quot;G00 &quot;); break;
      case MOVL: strCmd.concat(&quot;G01 &quot;); break;
      case JUMP: strCmd.concat(&quot;G05 &quot;); break;
      default: strCmd.concat(&quot;G00 &quot;); break;
    }
    if(motionMode) strCmd.concat(&quot;G90 &quot;);
    else strCmd.concat(&quot;G91 &quot;);
    String strParam = &quot;X&quot;+String(x, 2)+&quot; Y&quot;+String(y, 2)+&quot; Z&quot;+String(z, 2)+&quot; A&quot;+String(rx, 2)+&quot; B&quot;+String(ry, 2)+&quot; C&quot;+String(rz, 2);
    strCmd.concat(strParam);
    sendMsg(strCmd);
  }
  
  void UART_Mirobot::moveArc(float x, float y, float z, float r, bool motionMode, int pathMode){
    String strCmd = &quot;M20 &quot;;
    if(motionMode) strCmd.concat(&quot;G90 &quot;);
    else strCmd.concat(&quot;G91 &quot;);
    if(pathMode) strCmd.concat(&quot;G02 &quot;);
    else strCmd.concat(&quot;G03 &quot;);
    String strParam = &quot;X&quot;+String(x, 2)+&quot; Y&quot;+String(y, 2)+&quot; Z&quot;+String(z, 2)+&quot; R&quot;+String(r, 2);
    strCmd.concat(strParam);
    sendMsg(strCmd);
  }
  
  void UART_Mirobot::gripper(int gripperStatus){
    if(gripperStatus) sendMsg(&quot;M3 S40&quot;);
    else sendMsg(&quot;M3 S60&quot;);
  }
  
  void UART_Mirobot::softGripper(int softGripperStatus){
    if(softGripperStatus == ON) sendMsg(&quot;M3 S1000&quot;);
    else if(softGripperStatus == GRAB) sendMsg(&quot;M3 S500&quot;);
    else sendMsg(&quot;M3 S0&quot;);
  }
  
  void UART_Mirobot::pump(int pumpStatus){
    if(pumpStatus == ON) sendMsg(&quot;M3 S1000&quot;);
    else if(pumpStatus == BLOW) sendMsg(&quot;M3 S500&quot;);
    else sendMsg(&quot;M3 S0&quot;);
  }
  
  void UART_Mirobot::pwmWrite(int pwm){
    String strPara = &quot;S&quot; + String(pwm);
    sendMsg(&quot;M3 &quot; + strPara);
  }
  
  void UART_Mirobot::moveConveyor(float d, bool motionMode){
    sendMsg(&quot;$45=0&quot;);
    String strCmd = &quot;G01 &quot;;
    if(motionMode) strCmd.concat(&quot;G90 &quot;);
    else strCmd.concat(&quot;G91 &quot;);
    String strPara = &quot;D &quot; + String(d, 2);
    sendMsg(strCmd + strPara);
  }
  
  void UART_Mirobot::moveRail(float d, bool motionMode){
    sendMsg(&quot;$45=1&quot;);
    String strCmd = &quot;G01 &quot;;
    if(motionMode) strCmd.concat(&quot;G90 &quot;);
    else strCmd.concat(&quot;G91 &quot;);
    String strPara = &quot;D &quot; + String(d, 2);
    sendMsg(strCmd + strPara);
  }
  
  void UART_Mirobot::setCmdTimeout(long cmdTimeout){
    mirobotCmdTimeout = cmdTimeout;
  }
  
  void UART_Mirobot::sendMsg(String gcode, bool check){
    if(commMode == 0){
      while(serial-&gt;read() &gt;= 0){};
      if(serial == &amp;Serial||serialMonitoringMode == 0) serial-&gt;println(gcode);
      else{
        serial-&gt;println(gcode);
        Serial.println(&quot;Send message: &quot; + gcode);
      }
      unsigned long rtime = millis();
      strMsg = &quot;&quot;;
      while(strMsg.indexOf(&quot;ok&quot;)&lt;0&amp;&amp;strMsg.indexOf(&quot;State&quot;)&lt;0&amp;&amp;check&amp;&amp;strMsg.length()!=2){
        //如果串口中有数据则全部读取
        if(serial-&gt;available()) strMsg += serial-&gt;readString();
        //如果等待结束符超时则跳出
        if((millis()-rtime)&gt;=(mirobotCmdTimeout)){
          strMsg = &quot;---Timeout---&quot;;
          break;
        }
        delay(100);
      }
      if(serial != &amp;Serial&amp;&amp;serialMonitoringMode == 1){
        Serial.print(&quot;Mirobot: &quot;);
        Serial.println(strMsg);
      }
    }
    else{
      String rs485Cmd =&quot;@&quot; + address + gcode;
      while(Serial1.read() &gt;= 0){};
      Serial1.println(rs485Cmd);
      if(serialMonitoringMode == 1){
        Serial.print(&quot;RS485 message: &quot;);
        Serial.println(rs485Cmd);
      }
      unsigned long rtime = millis();
      strMsg = &quot;&quot;;
      while(strMsg.indexOf(&quot;ok&quot;)&lt;0&amp;&amp;strMsg.indexOf(&quot;State&quot;)&lt;0&amp;&amp;check&amp;&amp;strMsg.length()!=2){
        //如果串口中有数据则全部读取
        if(Serial1.available()) strMsg = Serial1.readString();
        //如果等待结束符超时则跳出
        if((millis()-rtime)&gt;=(mirobotCmdTimeout)){
          strMsg = &quot;---Timeout---&quot;;
          break;
        }
        delay(100);
      }
      if(serialMonitoringMode == 1){
        Serial.print(&quot;Received: &quot;);
        Serial.println(strMsg);
      }
    }
  }
  
  int UART_Mirobot::getStatus(){
    sendMsg(&quot;o103&quot;);
    int Status;
    if(strMsg.indexOf(&quot;Offline&quot;)&gt;=0 || strMsg.indexOf(&quot;0&quot;)&gt;=0) Status = Offline;
    else if(strMsg.indexOf(&quot;Idle&quot;)&gt;=0 || strMsg.indexOf(&quot;1&quot;)&gt;=0) Status = Idle;
    else if(strMsg.indexOf(&quot;Alarm&quot;)&gt;=0 || strMsg.indexOf(&quot;2&quot;)&gt;=0) Status = Alarm;
    else if(strMsg.indexOf(&quot;Run&quot;)&gt;=0 || strMsg.indexOf(&quot;5&quot;)&gt;=0) Status = Run;
    else if(strMsg.indexOf(&quot;Busy&quot;)&gt;=0 || strMsg.indexOf(&quot;4&quot;)&gt;=0) Status = Busy;
    else Status = Offline;
    return Status;
  }
  
  void UART_Mirobot::runFile(String fileName){
    while(getStatus() != Idle &amp;&amp; getStatus() != Alarm);
    String strCmd = &quot;o111&quot; + fileName;
    sendMsg(strCmd);
    delay(1000);
    while(getStatus() != Idle);
  }
  
  /*****************************************/
  
  void RS485_Mirobot::rs485Init(int add, long baudRate){
    commMode = 1;
    address = String(add);
    if(address.length()&lt;2) address = &quot;0&quot; + address;
    Serial1.begin(baudRate);
  }
  </code></pre>
  <p>The header file is here:</p>
  <pre><code>#ifndef _MIROBOT_H_
  #define _MIROBOT_H_
  
  #include &lt;Arduino.h&gt;
  
  #define MOVJ 1
  #define MOVL 2
  #define JUMP 3
  
  #define ABS 1
  #define INC 0
  
  #define CW 1
  #define CCW 0
  
  #define ON 1
  #define OFF 0
  #define GRAB 2
  #define BLOW 2
  
  #define Offline 0
  #define Idle 1
  #define Alarm 2
  #define Run 5
  #define Busy 4
  
  class UART_Mirobot{
    public:
      UART_Mirobot();
      void serialInit(int serialPort = 0);    //设置与Mirobot通信的串口（0/Serial; 1/Serial1; 2/Serial2; 3/Serial3)
      void setSerialMonitoring(bool mode);    //设置开启串口监视，通过Arduino串口监视器查看
      void setCmdTimeout(long cmdTimeout);   //设置每条指令发送后超时等待的时间（单位：毫秒ms）
      void homing(int homingMode = 0);    //控制机械臂归零（0/$H：快速归零；1/$H1：1轴归零；2/$H2：2轴归零；3/$H3：3轴归零；4/$H4：4轴归零；
                                          //5/$H5：5轴归零；6/$H6：6轴归零（需对应硬件支持）；7/$H7：滑轨归零；
      void zero();    //机械臂初始位置
      void setMoveSpeed(int velocity);    //设置机械臂运动速度
      void setJumpPara(int height);   //设置JUMP门型轨迹抬起高度
      void timedPause(float seconds);   //暂停等待（单位：秒s）
      
      void moveJoints(float j1, float j2, float j3, float j4, float j5, float j6, bool motionMode = ABS);   //角度模式运动
      void movePose(float x, float y, float z, float rx, float ry, float rz, bool motionMode = ABS, int pathMode = MOVJ);   //坐标模式运动
      void moveArc(float x, float y, float z, float r, bool motionMode = ABS, int pathMode = CW);   //圆弧插补运动
      
      void gripper(int gripperStatus);    //舵机夹爪状态
      void softGripper(int softGripperStatus);    //三指柔爪状态
      void pump(int pumpStatus);    //气泵状态
      void pwmWrite(int pwm);   //pwm（控制器黄色接口）输出，范围：0~1000
  
      void moveConveyor(float d, bool motionMode = ABS);    //传送带运动控制
      void moveRail(float d, bool motionMode = ABS);    //滑轨运动控制
  
      int getStatus();  //获取机械臂工作状态，0/1/2/3/4/5： 0机械臂离线 1正常 2锁定 3复位中 4设备忙 5运行中 
      void runFile(String fileName);  //运行控制器中存储的Gcode文件
      void sendMsg(String gcode, bool check = ON);
  
    protected:
      bool commMode;
      int mirobotSerialPort = 0;
      bool serialMonitoringMode = 1;
      int mirobotVelocity = 2000;
      long mirobotCmdTimeout = 10000L;
      void mirobotReceived();
      String strMsg = &quot;&quot;;
      String address;
  };
  
  class RS485_Mirobot: public UART_Mirobot{
    public:
      void rs485Init(int add = 1, long baudRate = 115200);
  
  };
  
  
  
  #endif
  </code></pre>
  <p>This is how i connected my Arduino with the Controller of the Robot arm:
  <a href="https://i.stack.imgur.com/9vhBq.jpg" rel="nofollow noreferrer">Controller with the UART Port</a>
  Colors: Brown = 5V, White = GND, Yellow = Rx, Green = Tx</p>
  <p><a href="https://i.stack.imgur.com/Z731O.jpg" rel="nofollow noreferrer">This is how i connected the UART wires from the controller to my arduino. Brown = 5V, White = GND, Yellow = Tx2 (Pin 16), Green = Rx2 (Pin 17)</a></p>
  <p>The Contoller is connected to the robotic arm with an IDC Cable (but with the uart wire and without the usb wire)<a href="https://i.stack.imgur.com/XXjou.jpg" rel="nofollow noreferrer">4</a></p>
  <p><a href="https://i.stack.imgur.com/4OBkE.jpg" rel="nofollow noreferrer">This is how the Robotic arm looks like</a></p>
  <p>What I tried so far: I tried switching the uart ports on the arduino (Rx1,Tx1,Rx3,Tx3 etc.)
  I also tried to do a simple sketch with 1-2 moving actions but that didnt work either.</p>
  <p>[This ist how the serial monitoring looks like]. Luckly the robot arm can communicate with my arduino but at some point the communication cuts off.<a href="https://i.stack.imgur.com/9EfBx.jpg" rel="nofollow noreferrer">6</a>
  The Robotic arm sends the info in which state he is right now like Idle, Offline, Alarm or Run.</p>
  <p>What is expected: the robot should correctly execute the commands given to it by the Arduino.</p>
  <p>The result: The robot always stops at the same place and then only gives timeouts and he doesnt execute any commands given to him.</p>
  <p>If you need the function descriptions for the Robotic arm with arduino feel free to contact me bc I cant upload pdf-files on stackoverflow!</p>
  <p>If you have any questions or u didnt understand something feel free to ask me!!</p>
  <p>EDIT: Forgot to say that there is a &quot;error, sensor data checksum error!&quot;</p>
  <p>Should i try replacing the uart cable with another one?</p>
  <p>Sry for my bad english!!</p>