Struggling to use MX-28AR with Arduino

Hello everyone,

I have been trying to work with Dynamixels for a while now, and I thought I was making progress, but I have hit a wall. I am not sure what I am doing wrong, but hopefully I can find some help here.

I have a Dynamixel MX-28AR connected to an Arduino Nano through a MAX13488E translator chip. This is the smallest solution I could come up with, and for communications it works well so far.

The problem I am having is this: I am trying to use the PING command to check if the Dynamixel is connected, but it is behaving erratically. Most of the time, even when it is unplugged, it reports that it is connected and I do not understand why. This functionality is integral to what I am trying to do, and if anyone could offer some help it would be immensely helpful.

Here is the code I have written so far:

#include <SoftwareSerial.h>               // Software serial library, necessary to communicate with the Dynamixel

int         MX28_Tx = 2;                  // Software Serial Tx-Out to MX-28AR
int         MX28_Rx = 3;                  // Software Serial Rx-In from MX-28AR
// The Arduino is connected to the Dynamixel using a MAX13488E chip. This translates between TTL and RS-485

word        Response[10];                 // This is an array of 10 bytes. Whenever the Dynamixel Responds, it responds with some number of bytes, usually 6, but can be more. 10 just to be safe.
byte        ID1 = 1;                      // Holds the ID of the Dynamixel
byte        Error;                        // Contains the Error Bits. There are 8 possible error bits, so 1 byte is enough to store it.         
byte        Checksum;                     // This holds the calculated checksum
byte        Ping_Status;                  // The connection status of the Dynamixel

SoftwareSerial DXL(MX28_Rx, MX28_Tx);   // (Rx, Tx) Sets up the software serial port for communicating with the MX-28 Dynamixel servo

void setup() {

  Serial.begin(115200);         // Sets the PC serial port Baud Rate
  DXL.begin(57600);             // Sets the Dynamixel servo port Baud Rate   
  
}

void loop() {

Ping_Status = Ping(ID1); // Ping the Dynamixel

}


// This is the function to ping the Dynamixel
byte Ping(byte ID) // Pings the Dynamixel to see if it is present. If it is present, the checksum will match, if not, it will fail
  {
    DXL.write(0xFF);        // Header byte 1
    DXL.write(0xFF);        // Header byte 2
    DXL.write(ID);          // Dynamixel ID
    DXL.write(0x02);        // Length of Packet (Only 2 for Ping Command)
    DXL.write(0x01);        // Ping type of instruction
    DXL.write(lowByte(~(ID + 0x02 + 0x01))); // Checksum. This is the NOT (~) of the SUM of everything else.

    DXL.flush();            // Waits for the serial transmission to finish

    delay(5);                // Wait for Dynamixel to respond
        
    if (DXL.available()) // If the Dynamixel has sent a response
    
    { 
          for(int n=0; n<8; n++) // Read 8 bytes 
          {
            Response[n] = DXL.read(); // and put them into the response array
          }
    }

    // The checksum of the response is always the lowest byte of the NOT (~) of the ID, Length, Error, and Parameters Added Together. 
    Checksum = lowByte(~(Response [2] + Response [3] + Response [4]));

    /*   
    Serial.print ("Header 1: ");
    Serial.println(Response[0], HEX);
    Serial.print ("Header 2: ");
    Serial.println(Response[1], HEX);
    Serial.print ("ID: ");
    Serial.println(Response[2], HEX);
    Serial.print ("Length of Packet: ");
    Serial.println(Response[3], HEX);
    Serial.print ("Error: ");
    Serial.println(Response[4], HEX);
    Serial.print ("Checksum Received: ");
    Serial.println(Response[5], HEX);
    Serial.print ("Checksum Calculated: ");
    Serial.println(Checksum, HEX);
    */      
          
    if (Response [5] == Checksum && Response [2] == ID) // If the calculated checksum matches the actual checksum and the Dynamixel returns the correct ID, let me know
       {
          Serial.println("Checksum Matches, Dynamixel Found!");
          return (1);
       }

    else
       {
          Serial.println("Checksum Error, Dynamixel Not Found!");
          return (0);
       }       
    }

Thanks in advance!

Hi @Saaif88 ,

The returned Status Packet from DYNAMIXEL ID1 is a 6 byte packet as below.
Is there a particular reason of reading 8 bytes?

H1 H2 ID LEN ERR CKSM
0xFF 0xFF 0x01 0x02 0x00 0xFC

Also, DYNAMIXEL returns the status packet as soon as it receives the instruction so it could take less than 5 ms.
In DYNAMIXEL SDK, as soon as TX is completed from the buffer, RX gets ready to receive the packet.

Maybe clearing the Response array before getting data could help you to verify you are correctly getting data from DYNAMIXEL.

Hi @ROBOTIS-Will, thank you for your help. While you are correct that the packet should be 6 bytes, that is not the problem in this case.

The problem was that I had the code in the wrong place. Originally, I was reading the response, and then printing it REGARDLESS of whether it was changed or not. This is what the old code was:

    if (DXL.available()) // If the Dynamixel has sent a response
{ 
      for(int n=0; n<8; n++) // Read 8 bytes 
      {
        Response[n] = DXL.read(); // and put them into the response array
      }
}

// Do checks here, OUTSIDE of the IF statement. This is WRONG.
if (Response [5] == Checksum && Response [2] == ID) // If the calculated checksum matches the      actual checksum and the Dynamixel returns the correct ID, let me know
   {
      Serial.println("Checksum Matches, Dynamixel Found!");
      return (1);
   }

But what the code SHOULD actually be is:

      if (DXL.available()) // If the Dynamixel has sent a response
{ 
      for(int n=0; n<8; n++) // Read 8 bytes 
      {
        Response[n] = DXL.read(); // and put them into the response array

// Do stuff HERE, inside of the IF statement
if (Response [5] == Checksum && Response [2] == ID) // If the calculated checksum matches the actual checksum and the Dynamixel returns the correct ID, let me know
   {
      Serial.println("Checksum Matches, Dynamixel Found!");
      return (1);
   }

      }
}

Hopefully that helps someone in the future!

1 Like