1
\$\begingroup\$

I am building a robot using LX-225 intelligent servos.

These servos communicate using a half-duplex UART. Using a controller, it is possible to control the servos with an Arduino (among other MCUs.) All this controller does is take the full-duplex UART data from the Arduino and send it to the servos, it then reads the reply from the servos and sends that data back to the Arduino. You can also control the servos using an app and and a USB cable, but that's not important for me.

This is how the communication between the controller and servo looks like

This is what the communication between the controller and servo looks like.

Now we come to the issue at hand. I would like to control the servos using just the Arduino. While it is possible to send a command to the servo, the servo reads said command and does what is asked (e.g. move to a certain position,) when the Arduino sends a request for some information, like the current position of the servo, the servo replies, but the Arduino doesn't receive any information, or at least it's not reading anything (Serial.available() returns 0.)

To be able to use half-duplex on the Arduino, I simply connected RX and TX together. I figured that if I delete the data that are looped back, it will be fine, but maybe that's not the case.

Arduino to Servo Controller Pinout

Arduino to Servo directly Pinout

This is what the pinout looks like in both cases. The controller is basically a 74HC126D integrated circuit with a bunch of resistors and stuff, mainly for power management. The other IC you can see in the picture of the controller is for the USB to UART translation.

This is the communication between the Arduino and the servo - the servo replies, however the waveform is different than with the controller.

This is the communication between the Arduino and the servo - the servo replies, but the waveform is different than with the controller.

Below, I have pasted the code I use for the Arduino. It works when I connect it through the controller to the servo but not when it is connected directly to the servo (s.available() > 0 is never true.) The only thing the code does is take bytes sent from a Raspberry Pi 0W and send them on a different serial line to the servos/controller. This works, the commands are sent as expected, it's just that the Arduino doesn't recognize the reply.

#include <SoftwareSerial.h>

SoftwareSerial s (3, 2);

byte rpi_buffer[15];
int rpi_counter = 0;

byte servo_buffer[15];
int servo_counter = 0;

void setup() 
{
  Serial.begin(115200);
  s.begin(115200);
  s.listen();
}

void loop() 
{
  rpi_counter = 0;
  while(Serial.available() > 0)
  {
    rpi_buffer[rpi_counter] = Serial.read();
    //Serial.println("rpi writing");
    rpi_counter++;
  }
  if(rpi_counter > 0)
  {
    int j = rpi_counter;
    byte b_array[j];
    
    for(int i = 0; i < j; i++)
    {
      b_array[i] = rpi_buffer[i];
    }
    s.write(b_array, j);
    s.end();
    s.begin(115200);
    s.listen();
  }

  servo_counter = 0;
  while(s.available() > 0)
  {
    servo_buffer[servo_counter] = s.read();
    //Serial.println("servo writing");
    servo_counter++;
  }
  if(servo_counter > 0)
  {
    int j = servo_counter;
    byte b_array[j];
    
    for(int i = 0; i < j; i++)
    {
      b_array[i] = servo_buffer[i];
    }

    Serial.write(b_array, j);
  }
} 

The idea behind the s.end(), s.begin(115200) and s.listen() is that it will clear the buffer that receives the data, which were just sent (due to the RX and TX being connected together.)

Could someone please tell me if this is an electronic issue that I don't know about (like that it's not ok to just connect RX and TX together), or if it's something with the code?

An explanation would be much appreciated if I have commited some terrible mistake with the electronics or code, I am only a hobbyist.

\$\endgroup\$
1
  • \$\begingroup\$ Start by setting up your oscilloscope correctly. I'm sure you don't have 50-60 V on your UART, but we cannot guess what voltage it actually is. \$\endgroup\$
    – Klas-Kenny
    Sep 18, 2022 at 13:27

2 Answers 2

1
\$\begingroup\$

Yes, it's as simple as you said, you can't simply connect TX and RX together.

TX will always be either a high or low output, so when communication is idle, TX pin will keep the pin in high idle state and servo can't pull the wire down.

The point of half-duplex is that the medium is shared and all devices can freely communicate on the bus. Therefore, having the Arduino TXD pin always as an output that drives the bus, it will prevent other devices from driving the bus.

A simple solution is to just configure the TXD pin to be not an output when transmission is not needed. How exactly to achieve that is out of scope, because every MCU has a different way of doing it.

\$\endgroup\$
0
\$\begingroup\$

thanks very much @Justme for the suggestion, I looked into separating the TX pin from RX, and this design worked for me:
TX separation from RX using two P-channel mosfets and two 4k7 resistors

Basically I used two P-channel mosfets and two 4k7 resistors, and that works fine. It can be found on this website: https://docs.majerle.eu/projects/lwow/en/latest/user-manual/hw-connection.html#id1

Thanks again

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I don't see if this answers your original question. It's more like a forum answer explaining what you did instead, but this is a Q&A site. And those are not P channel FETs, they would not work. And you chose a hardware solution instead of adding a couple of lines of code. \$\endgroup\$
    – Justme
    Sep 20, 2022 at 15:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.