How to Move Dynamixel ax18 with Teensy 4.x

Mardana

Member
I am trying to control a Dynamixel AX-18A servo using Teensy 4.1 via Serial2 (TX: pin 8, RX: pin 7). For half-duplex communication, I am using IC HD74LS241P as a buffer between Teensy and Dynamixel.

However, I ran into a problem where the servo did not respond to the commands I sent. I've tested the same code on Blackpill's STM32F4, and there the servo can move correctly.

The following are some of the things that I have checked:

  • Baudrate is set to 1,000,000 bps.
  • IC HD74LS241P:
    I used HD74LS241P to set up half-duplex communication.
    The DIR (direction control) pin is controlled for switching between TX and RX.
    Power Supply for Dynamixel is enough (using 12V 5A adapter).
    Code to send commands to the servo:
The Full Code
C++:
#include <Dynamixel2Arduino.h>

#define DXL_SERIAL Serial2
#define DEBUG_SERIAL Serial // Make sure this corresponds to the debugging port
const uint8_t DXL_DIR_PIN = 27;
const float DXL_PROTOCOL_VERSION = 1.0;
Dynamixel2Arduino dxl(DXL_SERIAL, DXL_DIR_PIN);

void setup() {
  DEBUG_SERIAL.begin(115200);
  while (!DEBUG_SERIAL);

  dxl.begin(1000000);
  dxl.setPortProtocolVersion(DXL_PROTOCOL_VERSION);

  // Wait a few seconds to make sure everything is ready
  delay(3000);

  // Make sure the servo is in the correct mode
  dxl.torqueOff(19);
  dxl.setOperatingMode(19, OP_POSITION);
  dxl.torqueOn(19);

  // Try to set the initial position
  if (dxl.setGoalPosition(19, 63, UNIT_DEGREE)) {
    DEBUG_SERIAL.println("Starting position successfully set to 63 degrees");
  } else {
    DEBUG_SERIAL.println("Failed to set the starting position");
  }
}

void loop() {
  delay(3000);
  if (dxl.setGoalPosition(19, 63, UNIT_DEGREE)) {
    DEBUG_SERIAL.println("Successfully set position to 63 degrees");
  } else {
    DEBUG_SERIAL.println("Failed to set position to 63 degrees");
  }

  delay(3000);
  if (dxl.setGoalPosition(19, 165, UNIT_DEGREE)) {
    DEBUG_SERIAL.println("Successfully set position to 165 degrees");
  } else {
    DEBUG_SERIAL.println("Failed to set position to 165 degrees");
  }
}

Here's the circuit
skematik.jpg

I have also tried some other libraries such as Dynamixel Serial from :
Dynamixel Serial Zach Shiner

and BioloidSerial from :
BioloidSerial KurtE
but it doesn't work either, where my dynamixel servo doesn't move.

does anyone have any Library suggestions and examples of the code used and how the circuit you used.
 
As was mentioned in other thread, the teensy is not 5v tolerant.

I have used several different ways, to connect, including

I have also done it using level shifter like on the other thread you posted on this morning.

I have also lived on the risky side and connected directly to tx pin of uart and hoped the servos would not output 5 v…

edit if you look at the robotis circuit for their their shirlds
and look at their schematic they mention it is for 5v and to use level shifter…
 
Last edited:
As was mentioned in other thread, the teensy is not 5v tolerant.

I have used several different ways, to connect, including

I have also done it using level shifter like on the other thread you posted on this morning.

I have also lived on the risky side and connected directly to tx pin of uart and hoped the servos would not output 5 v…

edit if you look at the robotis circuit for their their shirlds
and look at their schematic they mention it is for 5v and to use level shifter…
Thank you in advance for the various discussions you have shared in this forum. I have also read some of the related topics that you answered, such as:

Teensy 4.0 dan Dynamixel page 1
Teensy 4.0 dan Dynamixel page 2
Dynamixel and Half-duplex serial usage on Teensy4.1
Rs485 halfduplex for Dynamixel with Teensy 3.1 without external Buffer chip
Trying out a Teensy 3.1 on a PhantomX Hexapod (or maybe Quad)

However, I still don't fully understand the discussion, as I am still a beginner in electronics and programming. Therefore, I would like to share my experience and ask for advice in order to understand and solve the problems I faced.

The circuit I used
1. Initial Experiment​
  • I tried connecting the TX pin of the Teensy 4.1 to the logic level shifter, then to the Data pin of the Dynamixel, but the servo did not respond.
  • I also tried connecting the TX directly to the Dynamixel Data pin, but after a while, my Teensy 4.1 crashed. I suspect this is because the Teensy 4.1 cannot receive 5V on the RX, or there may be other errors in my circuit.
2. Experiment with IC 74LS241​
  • I tried connecting the TX and RX pins on the Teensy directly to IC 74LS241, as I saw in some references, but the servo still did not respond.
  • I also added a logic level shifter between TX and RX on the Teensy to IC 74LS241, but the results remained the same.
3. Measurement of Output Voltage from IC 74LS241​
I tried to measure the voltage coming out of IC 74LS241 to the Dynamixel Data pin, and the results are as follows:​
  • 8V input to IC → ~6V output to Data Dynamixel.
  • 5V input + 10K resistor → ~5V output to Data Dynamixel.
  • 5V input without 10K resistor → ~1.5V - 3V output to Data Dynamixel.
However, despite this voltage difference, the servo still does not move.
Attempted Program Code

1. Using Dynamixel2Arduino Library​
  • I tried the sample code from basic -> position_mode, but it didn't work.
2. Using Dynamixel_Serial Library​
  • I tried the code example from Move_in_Servo_mode, but the servo did not respond.
  • I also tried editing some parts of the code in the library, but it still failed.
3. Using the BioloidSerial Library​
  • I encountered an error during compilation, tried to fix it, but still failed.
4. Using Code Without Library (Directly Send Serial Buffer)​
  • This code works on STM32F407VXX and STM32F401 Blackpill with the same circuit, but does not work on Teensy 4.1.
5. Trying Other Libraries​
  • Some compiled successfully but still did not drive the servo.
  • Some failed to compile.
Questions
  1. Is IC 74LS241 the right buffer for half-duplex communication with Dynamixel AX-18A using Teensy 4.1?
  2. Can IC 74LS241 be used together with Teensy 4.1 to drive a Dynamixel AX-18A servo? If it can, how to connect and use it properly?
  3. Is there a possibility that Teensy 4.1 is not compatible with the communication method I am using? If so, how can I customize the connection and code?
  4. Are there any proven libraries and code samples to control the Dynamixel AX-18A using Teensy 4.x?
  5. Are there any errors in voltage settings or logic levels that cause communication to fail?

In your opinion, is there a proper circuit and code or library that I can use so that I can move the servo using teensy 4.x?
Thank you for helping to answer the problem I'm having right now.
 
Last edited:
  • I also tried connecting the TX directly to the Dynamixel Data pin, but after a while, my Teensy 4.1 crashed. I suspect this is because the Teensy 4.1 cannot receive 5V on the RX, or there may be other errors in my circuit.
If you connected a pin supplying 5V to the Teensy you at the very least probably destroyed that pin.
It is possible that you did further damage to the Teensy. Other than the 5V input pin you CANNOT put 5V on any other pin without damaging the Teensy in some way.
It's likely that your attempts to further use the Teensy failed because you destroyed that pin.
 
The Teensy 4 controller is only 1.8V internally I think, 3.3V is its I/O voltage - put another way its a 1.8V processor that's 3.3V tolerant! This is why 5V can easily destroy the whole chip.
 
@Mardana - Sorry, it is sometimes difficult to debug some of this, without exact, I tried This hardware, showing exact hook ups, with this Software
showing full code... As there are lots of variables.

Like using Teensy 4 Half duplex support on TX bin with the library like: Dynamixel2Arduino
As did you do the class override, like I mentioned in some of the posts, where for example the setup code switches the Teensy into half duplex,
and then possibly do stuff with switching from TX mode to RX, most likely just a flush to wait until TX completes...

With all of these cases, I always end up using a Logic Analyzer to see what is going on. I have few of them from Saleae. That way for example,
I can see if the command is actually sending some data out on the DXL bus. Without this, I would end up using another processor or potentially just to an RX pin of a different Serial port, and try sending command and see if I receive data on that port and the data looks valid.
Like hex dump the actual packet...

If that worked would try sending data from other board, back to teensy, and see if it receives anything on the RX pin, then I have a clue
that the hardware is probably working and the like. I would then try a ping operation and see if that responds...

But first step probably is to verify that your Teensy especially the pins that you may have subjected to over voltage are working.
 
@Mardana - Sorry, it is sometimes difficult to debug some of this, without exact, I tried This hardware, showing exact hook ups, with this Software
showing full code... As there are lots of variables.

Like using Teensy 4 Half duplex support on TX bin with the library like: Dynamixel2Arduino
As did you do the class override, like I mentioned in some of the posts, where for example the setup code switches the Teensy into half duplex,
and then possibly do stuff with switching from TX mode to RX, most likely just a flush to wait until TX completes...

With all of these cases, I always end up using a Logic Analyzer to see what is going on. I have few of them from Saleae. That way for example,
I can see if the command is actually sending some data out on the DXL bus. Without this, I would end up using another processor or potentially just to an RX pin of a different Serial port, and try sending command and see if I receive data on that port and the data looks valid.
Like hex dump the actual packet...

If that worked would try sending data from other board, back to teensy, and see if it receives anything on the RX pin, then I have a clue
that the hardware is probably working and the like. I would then try a ping operation and see if that responds...

But first step probably is to verify that your Teensy especially the pins that you may have subjected to over voltage are working.
Thank you for the answers you have provided. I'm starting to understand what to do, but I still don't fully understand about half-duplex, is there a simpler language to explain half duplex? If I use that mode, will it affect other serial communications?
Please correct me if I misunderstand this concept:
At the moment, all I have to do is try to use the code and circuit that I previously successfully used on the STM32. The steps I will take:
  1. I will send the data from the STM32 through IC 74LS241 (buffer/driver), which is then passed to the logic level before entering Teensy.
  2. I will capture the received data output using the RX pin on the Teensy.
  3. After that, I will try to send data from Teensy using the same code. This data will go through the logic level, then to IC 74LS241 before being sent to the STM32.
  4. I will compare the data sent by STM32 and Teensy, whether the results are the same or different.
  5. I will also test by sending data from Teensy to STM32 through the same path, to make sure if the data received by STM32 matches what is sent.
  6. Conversely, I will also try to send data from the STM32 to the Teensy to see if the communication goes well.
In this experiment, I have two main questions:
1. If the received data is different, what should I do to fix it?​
2. If the received data is the same, but the servo does not move, are there any additional steps I need to take?​
I plan to do this experiment in the next two days (as I am still waiting for a new microcontroller after the previous one broke). If anyone has already tried this method, I would really appreciate your help, suggestions, and solutions.
Thank you very much! 🙏
 
If you connected a pin supplying 5V to the Teensy you at the very least probably destroyed that pin.
It is possible that you did further damage to the Teensy. Other than the 5V input pin you CANNOT put 5V on any other pin without damaging the Teensy in some way.
It's likely that your attempts to further use the Teensy failed because you destroyed that pin.
Thank you for the explanation! I really appreciate this information. I will be more careful in the future not to damage Teensy again. If there are any additional suggestions to prevent similar mistakes, I am very open to hearing them. 😊🙏
 
Thank you for the explanation! I now better understand why 5V voltage can damage Teensy 4. I will be more careful in handling I/O voltage so as not to damage the chip. Thanks for the insight and advice! 🙏😊
The Teensy 4 controller is only 1.8V internally I think, 3.3V is its I/O voltage - put another way its a 1.8V processor that's 3.3V tolerant! This is why 5V can easily destroy the whole chip.
 
In this experiment, I have two main questions:
1. If the received data is different, what should I do to fix it?2. If the received data is the same, but the servo does not move, are there any additional steps I need to take?
Before, I try to answer these, I thought maybe should step back a second and give a little more background information.

Half Duplex: The Dynamixels use half duplex Serial to communicate. That is that there is only one data wire between them and likewise the host. Only one thing can talk on the wire at a time. The host is typically the master of this, in that it will typically send a request out to one or more servos and in many/most/all circumstances the servos will send back a response. Note, there are some differences in protocols between their protocol 1 and protocol 2. Since you mentioned AX-18 they use protocol 1. With half duplex, the dxl pin is pulled high by the host, and when the servos respond, their response for a high state leaves the signal high and low state will pull the signal down...

How to do Half duplex on a teensy Serial port:
Note: there is additional information up on the PJRC website page: https://www.pjrc.com/teensy/td_uart.html

a) Use external hardware that take RX, TX and a direction pin and converts the signal to half duplex.
The typical way I use this on the Teensy, is to use the support that was added to the Teensy Serial objects, originally for
RS485, where you use the Serial method: transmitterEnable to tell the board which pin you are using for controlling the DIR pin like:
Code:
 port_.begin(baud_);
    port_.transmitterEnable(dir_pin_);

What this does, is to by default have the direction pin set for RX mode, and if your code does any writes to the Serial port, it switches
the DIR pin to TX mode, and leaves this in TX mode as long as it is still sending data out, when it receives the transmit complete
state and queue is empty, it will switch back to RX mode.

b) The Teensy board supports half duplex on the Serial ports, where both the sending and receiving are done on the TX pin.
I have actually simply connected the TX pin from teensy to the DXL wire and controlled the servos. For experimenting, I have simply
cut a servo extension wire logically in half, cut out the power line just to be safe and then connected up either male or female jumper ends to the signal and GND and connected thos up to my T3.x or 4.x and plug the bioloid connector into a hub. I also connected power up to the hub...
However this has the servos communicating at 3.3v where spec says 5v, so sometimes I use a bidirectional level shifter. But note not all level shifters work well for all things. ...

To set the Serial port into half duplex you do something like:
Code:
port_.begin(baud_, SERIAL_HALF_DUPLEX);
The Serial code then works more or less the same way as a) above in that it defaults to rx mode...

Using Dynamixel2Arduino with this, needed some glue between their version of half duplex and ours. Last time I played with this was maybe 4 years ago. Where @mjs513 and I were playing with a Hexapod (18+ servos).

You can see our port handler code that was setup to handle a) or b) above in the code:
Which includes:
Code:
#if defined(TEENSYDUINO)
class TeensySerialPortHandler : public DYNAMIXEL::SerialPortHandler
{
  public:
    TeensySerialPortHandler(HardwareSerial& port, const int dir_pin = -1)
      : SerialPortHandler(port, dir_pin), port_(port), dir_pin_(dir_pin) {}
    virtual void begin(unsigned long baud) override
    {
      baud_ = baud;

      if (dir_pin_ != -1) {
        port_.begin(baud_);
        port_.transmitterEnable(dir_pin_);
      } else {
        port_.begin(baud_, SERIAL_HALF_DUPLEX);
      }

      setOpenState(true);
    }

    virtual void end(void) override
    {
      port_.end();
      setOpenState(false);
    }

  private:
    HardwareSerial& port_;
    const int dir_pin_;
    uint32_t baud_;
};


Dynamixel2Arduino dxl;
TeensySerialPortHandler dxl_port(DXL_SERIAL, DXL_DIR_PIN);

and later on it has:
Code:
dxl.setPort(dxl_port);
  dxl.begin(DXL_BAUD);

===
Now back to your questions.

1) You need to figure out why? Could be wrong baud rate, could be wiring issue. Wires too long, for example if you are using
18 servos and each one connect to the next one, the end one the signal has to travel a long way. Where if you use some hubs, you can
shorten that.

Multiple servos - Run into issues if multiple ones have the same ID. For example, plugging in two new ones that have address #1. Sometimes with the AX servos, I would run into for some reason one or more servos would reset their ID back to 1. With the Phoenix code, I ended up not using ID #1 and the startup code would look for all of the expected servos and if one was missing and Servo ID #1 existed, I assumed that
it must be the missing one and changed it's ID...

2) Why it might not move.
a) Packet is wrong - could be, you are sending protocol 2 and servo expectes protocol 1
b) you don't have proper power to the servo.
c) multiple servos with same ID
d) Servo is in error state, if I remember correctly this would have a blinking LED. That is if the set fails, you should get the error
code and see what it is: I think it is one of these two APIS
Code:
uint8_t getLastStatusPacketError() const;
DXLLibErrorCode_t getLastLibErrCode() const;

You can then try to reboot the servo: something like: dxl.reboot(id);

Good luck
 
Back
Top