Dynamixel Arduino Shield cannot find connected motors (XM430)

Issue:

The example Arduino sketches cannot find any of the connected dynamixel servo motors.

I have an Arduino Uno r3 with a Dynamixel Arduino Shield, with a XM430-W350-T connected. A Robotis 12V power supply is connected to both the shield and the arduino, with the shield’s power jumper off. When turning on the power switch, the motor’s LED shortly lights up in red, then goes off. Uploading sketches works fine (e.g., scan_dynamixels.ino), but none of them are able to find or control the motor. I have the UART switch on during upload and off afterwards, then resetting the Arduino. The serial debug does work, via the RS485 UART port using a FTDI232 serial debugger.

Setup:
PXL_20240802_132405927

Software: latest scan_dynamixel.ino from DynamixelShield library (0.2.6) with Dynamixel2Arduino (0.7.0).

Serial output:

SCAN BAUDRATE 2000000
SCAN PROTOCOL 1
SCAN BAUDRATE 57600
SCAN BAUDRATE 115200
SCAN BAUDRATE 1000000
SCAN BAUDRATE 2000000
SCAN BAUDRATE 3000000
SCAN PROTOCOL 2
SCAN BAUDRATE 57600
SCAN BAUDRATE 115200
SCAN BAUDRATE 1000000
SCAN BAUDRATE 2000000
SCAN BAUDRATE 3000000
Total 0 DYNAMIXEL(s) found!

My issue is very similar to: https://forum.robotis.com/t/dynamixel-does-not-execute-uploaded-example-code-with-arduino/958

I tried:

  • with external 12V power supply (Robotis) and without (with jumper on to get 5V from Arduino)
  • three different motors, all XM430-W350-T, including one that works perfectly fine in a Turtlebot3
  • two different Arduino Unos from different suppliers
  • reinstalling the Arduino IDE on a new location with fresh library installs

Now what? Could it be an issue with the shield itself?


DYNAMIXEL Servo: XM430-W350-T (3 different ones)


DYNAMIXEL Controller: Dynamixel Arduino Shield


Software Interface: arduino (on Ubuntu 24.04)

From my experience “scan” and “ping” do not work properly anymore with Arduino. Can you just try to access and move the DXL directly with Set Goal Position? Don’t rely on what scan and ping tell you.

Unfortunately that also doesn’t work. Just calling setGoalPosition or setGoalVelocity to ID 1 does not do anything.

Below is my setup:

  1. DXL Shield is powered by 12 V PS to its Terminal Block. VIN Jumper is disconnected.
  2. UNO-R3 is powered by USB cable.
  3. I am using a 2XL-430 actuator.

UNO-R3-Setup

Below is the Arduino sketch I used. It is based on the example sketch “position_mode.ino” but I stripped out all the macros and DEBUG_SERIAL stuff.

#include <Dynamixel2Arduino.h>
#define DXL_SERIAL   Serial
const int DXL_DIR_PIN = 2; // DYNAMIXEL Shield DIR PIN
const uint8_t DXL_ID = 1;
const float DXL_PROTOCOL_VERSION = 2.0;

Dynamixel2Arduino dxl(DXL_SERIAL, DXL_DIR_PIN);

//This namespace is required to use Control table item names
using namespace ControlTableItem;

void setup() {
  // put your setup code here, to run once:
  
  // Set Port baudrate to 1000000bps matching my 2XL-430's with DYNAMIXEL baudrate.
  dxl.begin(1000000);
  // Set Port Protocol Version. This has to match with DYNAMIXEL protocol version.
  dxl.setPortProtocolVersion(DXL_PROTOCOL_VERSION);
  // Get DYNAMIXEL information
  dxl.ping(DXL_ID);

  // Turn off torque when configuring items in EEPROM area
  dxl.torqueOff(DXL_ID);
  dxl.setOperatingMode(DXL_ID, OP_POSITION);
  dxl.torqueOn(DXL_ID);

  // Limit the maximum velocity in Position Control Mode. Use 0 for Max speed
  dxl.writeControlTableItem(PROFILE_VELOCITY, DXL_ID, 30);
}

void loop() {
  // put your main code here, to run repeatedly:
  
  // Please refer to e-Manual(http://emanual.robotis.com/docs/en/parts/interface/dynamixel_shield/) for available range of value. 
  // Set Goal Position in RAW value
  dxl.setGoalPosition(DXL_ID, 1000);

  int i_present_position = 0;
  float f_present_position = 0.0;

  while (abs(1000 - i_present_position) > 10)
  {
    i_present_position = dxl.getPresentPosition(DXL_ID);
  }
  delay(1000);

  // Set Goal Position in DEGREE value
  dxl.setGoalPosition(DXL_ID, 5.7, UNIT_DEGREE);
  
  while (abs(5.7 - f_present_position) > 2.0)
  {
    f_present_position = dxl.getPresentPosition(DXL_ID, UNIT_DEGREE);
  }
  delay(1000);
}

Below is a little video clip showing how this sketch runs - don’t forget to switch the UART switch to the DXL side, and turn on power to the DXL SHIELD and also push the RESET button on the UNO-R3 to restart the downloaded sketch:

Hopefully this sketch will work for you too. If not, there is a good chance that the DXL SHIELD is acting up somehow.

Thanks, @roboteer. Unfortunately, your sketch also doesn’t work for me.

As you got a hardware serial debugger, can you unplug the Dxl Shield from Uno R3 and just test its pins 0 and 1 to see if “Serial” is working properly as a UART port? Have you tested this configuration before?

Hello @roboteer, I have the same problem as the poster above. Maybe someone can help me out. I have managed to control a Dynamixel XL430-W250 with an Arduino UNO R3, but not the R4. I was trying to figure out why the R4 doesn’t work, and now all of a sudden the R3 doesn’t work either.
I really don’t know what to do, I’ve proven that the UART works on the R3 and that it is sending signals fine. All of a sudden the motor just doesn’t want to respond. I have tried using all different baud rates and scanning for different IDs, but nothing has worked which is very strange considering it worked completely fine before.
I have been using the R4 as a debugging tool that reads over the software serial so that I can understand what’s going on. Here is my code for both arduinos:

Arduino UNO R3

/*******************************************************************************
* Copyright 2016 ROBOTIS CO., LTD.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/

#include <DynamixelShield.h>

#define BAUDRATE 57600 // Any Supported Protocol

#if defined(ARDUINO_MINIMA)
  #define DEBUG_SERIAL Serial
  #define DXL_SERIAL Serial1
  #define DXL_DIR_PIN 2
#elif defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_MEGA2560)
  #include <SoftwareSerial.h>
  SoftwareSerial soft_serial(7, 8); // DYNAMIXELShield UART Connector RX/TX
  #define DEBUG_SERIAL soft_serial
  #define DXL_SERIAL Serial
#elif defined(ARDUINO_SAM_DUE) || defined(ARDUINO_SAM_ZERO)
  #define DEBUG_SERIAL SerialUSB    
#else
  #define DEBUG_SERIAL Serial
#endif

const uint8_t DXL_ID = 1;
const float DXL_PROTOCOL_VERSION = 2.0;

DynamixelShield dxl(DXL_SERIAL, DXL_DIR_PIN);

//This namespace is required to use Control table item names
using namespace ControlTableItem;

void setup() {
  // For Uno, Nano, Mini, and Mega, use UART port of DYNAMIXEL Shield to debug.
  DEBUG_SERIAL.begin(115200);

  // Set Port baudrate to 57600bps. This has to match with DYNAMIXEL baudrate.
  dxl.begin(57600);
  delay(100);
  
  // Set Port Protocol Version. This has to match with DYNAMIXEL protocol version.
  dxl.setPortProtocolVersion(DXL_PROTOCOL_VERSION);

  // Debugging initialisation of Serial communication.
  debugSerial();
  delay(600);

  // Scanning for other baud rates on communication lines.
  scanBaud();
  delay(600);

  // Get DYNAMIXEL information
  pingScan(DXL_ID);
  delay(600);

  // Turn off torque when configuring items in EEPROM area
  dxl.torqueOff(DXL_ID);
  dxl.setOperatingMode(DXL_ID, OP_POSITION);
  dxl.torqueOn(DXL_ID);
}

void loop() {  
  // Please refer to e-Manual(http://emanual.robotis.com/docs/en/parts/interface/dynamixel_shield/) for available range of value. 
  // Set Goal Position in RAW value
  dxl.setGoalPosition(DXL_ID, 512);
  delay(600);
  // Print present position in raw value
  DEBUG_SERIAL.print("Present Position(raw)    : ");
  DEBUG_SERIAL.println(dxl.getPresentPosition(DXL_ID));
  delay(600);

  // Set Goal Position in DEGREE value
  dxl.setGoalPosition(DXL_ID, 5.7, UNIT_DEGREE);
  delay(600);
  // Print present position in degree value
  DEBUG_SERIAL.print("Present Position(degree) : ");
  DEBUG_SERIAL.println(dxl.getPresentPosition(DXL_ID, UNIT_DEGREE));
  delay(600);
}

void scanBaud() {
  const int32_t baud[10] = {2000000, 1000000, 500000, 400000, 250000, 200000, 115200, 57600, 19200, 9600};
  const int8_t baud_len = 10;
  int8_t index = 0;
  uint8_t read_baudrate = 0;

  for(index = 0; index < baud_len; index++){
  // Set Port baudrate.
  DEBUG_SERIAL.print("SCAN BAUDRATE ");
  DEBUG_SERIAL.println(baud[index]);    
  dxl.begin(baud[index]);
  delay(100);
  if(dxl.ping(DXL_ID)) {
    DEBUG_SERIAL.print("ID : ");
    DEBUG_SERIAL.print(DXL_ID);
    DEBUG_SERIAL.println(", Ping Succeed");
    DEBUG_SERIAL.print("Set New Baudrate:");
    DEBUG_SERIAL.println(BAUDRATE);
    dxl.setBaud(DXL_ID, BAUDRATE);
    dxl.begin(BAUDRATE);
    // dxl.setPortProtocolVersion(DXL_PROTOCOL_VERSION);
    break;
    }
  }
  DEBUG_SERIAL.println("--------------------------");
}

void debugSerial() {
  // DEBUG INFO
  DEBUG_SERIAL.println("~~~~~~~~~~~~~~~~~~~~~~~~~~");
  delay(100);
  DEBUG_SERIAL.print("DXL_SERIAL               : ");
  DEBUG_SERIAL.println(DXL_SERIAL);
  delay(100);
  DEBUG_SERIAL.print("DXL_DIR_PIN              : ");
  DEBUG_SERIAL.println(DXL_DIR_PIN);
  delay(100);
  DEBUG_SERIAL.print("DXL_PROTOCOL_VERSION     : ");
  DEBUG_SERIAL.println(DXL_PROTOCOL_VERSION);
  delay(100);
  DEBUG_SERIAL.println();
  delay(100);
  DEBUG_SERIAL.print("Booting");
  for(int i = 0; i < 15; i++) {
    //delay(100);
    DEBUG_SERIAL.print(".");
  }
  DEBUG_SERIAL.println(".");
  DEBUG_SERIAL.println("--------------------------");
}

void pingScan(int ID) {
  bool b_ping = dxl.ping(ID);
  bool b_scan = dxl.scan();

  DEBUG_SERIAL.print("DXL Ping Status: ");
  DEBUG_SERIAL.println(b_ping);
  delay(100);
  DEBUG_SERIAL.print("DXL Scan Status: ");
  DEBUG_SERIAL.println(b_scan);
  delay(100);
  DEBUG_SERIAL.println("--------------------------");
}

Arduino R4 Minima

String inputString = "";     // A string to hold incoming data from Serial11
bool stringComplete = false; // Whether the string is complete

void setup() {
  // Start Serial (USB) for debugging, 9600 baud rate for this test
  Serial.begin(9600);
  while(!Serial);
  Serial.println("Starting Serial Test");

  // Start Serial1 (UART) for communication, 115200 baud rate for this test
  Serial1.begin(115200);
}

void loop() {
  // Check if any data is available from Serial11
  if (Serial1.available()) {
    // Read incoming characters until we hit a newline character
    while (Serial1.available()) {
      char inChar = (char)Serial1.read();
      inputString += inChar;  // Append the character to the input string

      // If a newline is detected, the string is complete
      if (inChar == '\n') {
        stringComplete = true;
        break;
      }
    }
  }

  // When a complete line is received, print it
  if (stringComplete) {
    Serial.print("Received from Serial1: ");
    Serial.print(inputString);  // Print the entire string received from Serial1

    // Clear the input string and reset for the next line
    inputString = "";
    stringComplete = false;
  }
}

Back in April 2024, I also found that I could not use UNO R4 although its Serial1() seemed to work fine at Full-Duplex, please see this post:

In general, I have stopped using that group of #define statements, and just set the DIR_DXL_PIN appropriately. I also have stopped using ping() and scan() from the D2A library as sometimes they worked for me and sometimes, they don’t. I just send direct DXL commands to my DXLs as I know their IDs anyway.

I did find that UNO R3 worked for me with DXLs, see previous item in this same post:

Thanks for your help @roboteer. I appreciate the reply to my post. In the end I have made a great departure from what I originally intended to do. It seems that I might have destroyed the Dynamixel Shield that I was using by shorting the power lines because connecting it to an oscilloscope shows some very strange behaviour. However, in the spirit of trying desperately to get a solution, I have now succeeded in adapting the Dynamixel2Arduino library to be compatible with SoftwareSerial, specifically the SoftwareSerialWithHalfDuplex library. If anyone is interested I could share my code so that it can be improved because I am far from best practices myself.

I will soon make my own hardware solution so that I can implement half-duplex on the Arduino R4 Minima without the shield.

1 Like

That would be great :ok_hand: