Help talking to uart bus servos in 6 axis robotic arm

MrChips

Joined Oct 2, 2009
34,889
I agree that the selling point of ESP32 is wireless. I vote for something other than ESP32.
For this application I would not use software UART. It is not more efficient than HW UART.

How many UARTs in total do you need?
 

Thread Starter

-live wire-

Joined Dec 22, 2017
959
I agree that the selling point of ESP32 is wireless. I vote for something other than ESP32.
For this application I would not use software UART. It is not more efficient than HW UART.

How many UARTs in total do you need?
Two. One for USB communication between the microcontroller and the PC. And the second one is for communicating with all of the servos. All servos must be individually given an ID, then connected to the same data line and then all write to servo commands start by addressing a specific servo ID. The read from servo commands come back on the same data line but I think start with the servo they are from.

Probably. The pin out you have posted here conflicts with the one at the Amazon link:

View attachment 272293
This one calls out all three UARTs.
So if I use GPIO 10 to the servo data wire, I can use hardware serial between the ESP32 and the servos, while using hardware serial for the USB communication? And then in my code I just use Serial1 for servos and Serial for USB?
 

Thread Starter

-live wire-

Joined Dec 22, 2017
959
Update guys, all the conflicting serial stuff was resolved and I now got the servos to take write commands from the ESP32 over Serial2. However, on both Serial2 and Serial0, sometimes write commands are ignored and dont seem to go thru. This can be seen in the inconsistency in which motors rotate when.

My only idea here is that it could be a 3.3V logic issue where it needs 5V signal to work consistently so I'm gonna try a 3.3V to 5V logic board.
 

MrChips

Joined Oct 2, 2009
34,889
I just had a quick look at the LX-225 servo User Manual.
The LX225 is designed to be daisy-chained using a single UART TX/RX, i.e. UART signal is relayed from one servo to the next.
Baud is 115200
Default ID is 1. You need to change the IDs so that each servo has a unique ID.
It says working voltage is 6-8.4V.
 

Thread Starter

-live wire-

Joined Dec 22, 2017
959
I just had a quick look at the LX-225 servo User Manual.
The LX225 is designed to be daisy-chained using a single UART TX/RX, i.e. UART signal is relayed from one servo to the next.
Baud is 115200
Default ID is 1. You need to change the IDs so that each servo has a unique ID.
It says working voltage is 6-8.4V.
Yes I know, I have assigned each servo an ID 1 through 4 individually and then daisy chained them together in the arm already. Also they are being powered by a 7.5V power supply with a common ground to the ESP32.

This is a part of my code so you can get an idea of what I'm doing. However, the issue (which happened even when it was using Serial not Serial2) is that sometimes it will not move all of the 4 motors at once, but will ignore some of the commands.

I was refering to the signal from Serial2 being 3.3V and that it may need to be stepped up to 5V with a logic level converter. I will try that now.
1658883803317.png
 

Thread Starter

-live wire-

Joined Dec 22, 2017
959
UPDATE:

The logic level shifter (3.3V to 5V) combined with the ESP32 Serial2 TX (pin 17) seems to work great for some write commands and fixes a lot of issues (such as not all of the motors always responding to commands).

But I'm still tryna figure out a few of the other write commands and how to do any of the read commands. I can't find any sample code and I don't understand what to do based on the documentation either. Is there a library that does these functions for me, or at least some sample code for some of these functions?

The important functions I need to use that I know exist but cannot implement are:
- reading the servo position (for initial calibration, I know that the servo is closed loop internally when you write it to a position)
- writing the angle offset to allow it to have 360 degree motion
-writing the mode (there are two modes: 1. continuous rotation w/ set velocity and 2. set positions in set amount of time). this is particularly important for the 5:1 geared servo that must make multiple full rotations (the reduced output also has a limit switch)

Thank you everyone for your help here BTW!
 

Ya’akov

Joined Jan 27, 2019
10,259
UPDATE:

The logic level shifter (3.3V to 5V) combined with the ESP32 Serial2 TX (pin 17) seems to work great for some write commands and fixes a lot of issues (such as not all of the motors always responding to commands).

But I'm still tryna figure out a few of the other write commands and how to do any of the read commands. I can't find any sample code and I don't understand what to do based on the documentation either. Is there a library that does these functions for me, or at least some sample code for some of these functions?

The important functions I need to use that I know exist but cannot implement are:
- reading the servo position (for initial calibration, I know that the servo is closed loop internally when you write it to a position)
- writing the angle offset to allow it to have 360 degree motion
-writing the mode (there are two modes: 1. continuous rotation w/ set velocity and 2. set positions in set amount of time). this is particularly important for the 5:1 geared servo that must make multiple full rotations (the reduced output also has a limit switch)

Thank you everyone for your help here BTW!
This part is critical, the servo bus is half duplex. It doesn’t have two ports, one for RXD and one for TXD. Instead, it uses one port and switches function so to use the read commands you need to send the command then switch the MCU from TXD to RXD and listen to the answer.

1658904607039.png
The schematic shows using two of a 74H126’s line drivers to do the switching. It requires using 2 GPIO pins of the MCU (or one pin and an inverter) to select TX or RX. While it doesn’t say so anywhere, it appears they are using RS485 rather than RS232. If this is true the ESP32 can use half duplex RS485 with its own driver so that the extra hardware and software to handle the switching isn’t needed.

I haven’t used RS485 with the ESP32 so I am not sure if there is a library for the Arduino to simplify this but you can use the API directly if needed. There is documentation available on how to make your own calls directly to unsupported functions in the Arduino IDE.

Alternatively, Hiwonder sell a controller board that is designed to do this (debugger) among other things so it is one possible route. It isn’t very expensive at ~$13.00 so it might make your life easier since it also includes debugging functionality.
 

Ya’akov

Joined Jan 27, 2019
10,259
So a little digging suggests that RS485 with the ESP32 is a bit dodgy. Here is a C example of using it without external hardware under FreeRTOS (which, by the way, does seem the right way to go overall, though it requires a different programming environment).

In general, the consensus on ESP32 RS485 support is to use an external RS485 driver like the MAX485. This can be found quite cheaply on module form like these for about a buck a piece. Here is an Arduino tutorial on using it.

The main differences between RS323 and RS485 relevant to you is that RS485 (can be) a two wire connection running in half duplex in which the receiver and transmitter swapping is done automatically by drivers; and the date levels are ±5V instead of the ±12V of RS232. Of course the UARTs on the MCU are going to be fixed at whatever VDD is.

So if the MCU is using 3V3 that’s all you have to work with. Most of the time the true RS232 is given short shrift and TTL levels, or less, are used and work. But, RS485 is likely to be unreliable at <5V as you may be seeing. RS485 actually makes sense in this application being an industrial standard.

I suspect that a good first effort, if not a permanent solution is the Hiwonder debugger board I mentioned above. There is also this more expensive driver board with a lot more functionality that can be used with an external MCU.
 

Thread Starter

-live wire-

Joined Dec 22, 2017
959
This part is critical, the servo bus is half duplex. It doesn’t have two ports, one for RXD and one for TXD. Instead, it uses one port and switches function so to use the read commands you need to send the command then switch the MCU from TXD to RXD and listen to the answer.

The schematic shows using two of a 74H126’s line drivers to do the switching. It requires using 2 GPIO pins of the MCU (or one pin and an inverter) to select TX or RX. While it doesn’t say so anywhere, it appears they are using RS485 rather than RS232. If this is true the ESP32 can use half duplex RS485 with its own driver so that the extra hardware and software to handle the switching isn’t needed.

I haven’t used RS485 with the ESP32 so I am not sure if there is a library for the Arduino to simplify this but you can use the API directly if needed. There is documentation available on how to make your own calls directly to unsupported functions in the Arduino IDE.

Alternatively, Hiwonder sell a controller board that is designed to do this (debugger) among other things so it is one possible route. It isn’t very expensive at ~$13.00 so it might make your life easier since it also includes debugging functionality.
Hmm so if I buy this board then I can connect the board then I can connect the ESP32 Serial2 (pins 16 and 17) to RX and TX of the board and then talk both ways?
1658943409121.png
 

Ya’akov

Joined Jan 27, 2019
10,259
This board seems like my best bet for 2 way communication ngl, and its pretty cheap so I think I'll get it and work on the other parts while I am waiting for it to arrive.
The MAX485 modules are not a bad option either, they are very widely used so a lot of help is available but the debugging board would be useful in any case since it allows using the computer to talk to the servos.
 

Thread Starter

-live wire-

Joined Dec 22, 2017
959
As the debugging board is getting here, I can still work on anything that requires write commands, just not that requires read commands. If you guys could help me figure out how to send the commands for the write functions I would greatly appreciate it.

This is most of the documentation I have for all the commands. I only really know how to do SERVO_MOVE_TIME_WRITE because they give some sample code for how to implement it. I cannot find a library that has the other functions I need such as:
- SERVO_OR_MOTOR_MODE_WRITE
- SERVO_ANGLE_LIMIT_WRITE
- SERVO_ANGLE_OFFSET_WRITE

My best guess is maybe I need to make a byte array formatted in a specific way according to the datasheet, but I'm not 100% sure what the format is. I think I then just write that array to the serial. I could probably try to figure it out but if theres a library that already makes the right arrays with the right bytes and sends them over serial for me it would probably save me a bit of time and work better/faster.

This is the one function (besides the writeID function) that I could find in the sample code:

Code:
#define LOBOT_SERVO_FRAME_HEADER         0x55
#define LOBOT_SERVO_MOVE_TIME_WRITE      1

//serial2
#define RXD2 16
#define TXD2 17
//-
byte LobotCheckSum(byte buf[])
{
  byte i;
  uint16_t temp = 0;
  for (i = 2; i < buf[3] + 2; i++) {
    temp += buf[i];
  }
  temp = ~temp;
  i = (byte)temp;
  return i;
}
void LobotSerialServoMove(HardwareSerial &SerialX, uint8_t id, int16_t position, uint16_t time)
{
  byte buf[10];
  if(position < 0)
    position = 0;
  if(position > 1000)
    position = 1000;
  buf[0] = buf[1] = LOBOT_SERVO_FRAME_HEADER;
  buf[2] = id;
  buf[3] = 7;
  buf[4] = LOBOT_SERVO_MOVE_TIME_WRITE;
  buf[5] = GET_LOW_BYTE(position);
  buf[6] = GET_HIGH_BYTE(position);
  buf[7] = GET_LOW_BYTE(time);
  buf[8] = GET_HIGH_BYTE(time);
  buf[9] = LobotCheckSum(buf);
  SerialX.write(buf, 10);
}
 

Thread Starter

-live wire-

Joined Dec 22, 2017
959
PLS HELP WTF I have 4 servos in the arm and 2 not in the arm, all of that same model, one of them I just opened today so i know its not fried. IVE TRIED EVERYTHING and i cant even get ANY of the servos to move anymore despite using the exact same code as before that was working great.

I tested the wiring and it turned out that although the buck converter was used within spec and was outputting 7.5V unloaded, it couldnt supply any current under load (it could yesterday so it broke some time in between). I replaced it with a buck board that I have confirmed works under load to supply the 7.5V.

I have confirmed that there is a signal coming out of the ESP32 pin and I have confirmed that the 3.3V to 5V logic level converter board is working. I have tried using multiple different hardware serial ports and checked my pinout and connections all multiple times. I have also tried using an arduino mega although on the arduino mega I did use Serial2 to talk to the servos not Serial (this should be fine and it worked before on the esp32).

Literally none of the servos will move with the exact same code (which basically just calls LobotSerialServoMove), and from what I can tell the exact same setup. WTF is going on like I just don't understand.
 

Thread Starter

-live wire-

Joined Dec 22, 2017
959
Please help, all 6 servos are only adressable by ID 254 which is reserved to refer to all servos connected to the data line regardless of their ID. None of the 6 respond to ID 1,2,3, or 4 despite the fact that one was out of the box and should have the default ID of 1, and the servos in the arm should still be programmed to have ID 1,2,3,4. I also never remember having a program set the ID to anything outside of 1-4.
 
Top