Table of content:
Send and receive data from servomotors
The NanoPi NEO4 has five 3.3V UART that can go up to 1.5 Mbauds/s. Two of these UART are used by the gigabit Ethernet controler and one is used by the Bluetooth1.
The printed circuit boards connect all
Herkulex DRS-0101 on NanoPi serial port /dev/ttyS4
(UART4, 40-pin, GPIO1).
The debug UART (UART2, 8-pin, GPIO3) is unused.
Initial set-up
To make everything go smoothly, you need to set each servomotors identifier and make sure they are communicating at 500 000 bauds/s. This can be done manually by connecting one servomotor at a time. You may want to use a software like Herkulex Manager to ease this process.
This indexing is the same in the URDF and offers an easier way to transfer a simulated control agent to the real robot.
Max baud-rate
Herkulex DRS-0101 are able to communicate in series as fast as 0.667 Mbauds/s. Nevertheless RK3399 boards are unable to communicate at that baud-rate as their base baud-rate is 1.5 Mbaud/s3. So 0.5 Mbaud/s is a good compromise (divided by 3 rather than 2.25).
Server-side
With ser2net
To ease development, ser2net
can be used to publish
this serial port to a TCP socket.
Then, this TCP socket can be used one the same network, on a computer connected to the robot or locally.
sudo apt install ser2net
sudo systemctl enable ser2net
Then edit /etc/ser2net.conf
and replace the last lines with
2000:raw:600:/dev/ttyS4:500000 8DATABITS NONE 1STOPBIT
This will publish /dev/ttyS4
with a baud-rate of 500 000 baud/s,
and some common serial configuration to 0.0.0.0:2000
.
Now, you may restart the service with sudo systemctl restart ser2net
.
Note
If you improperly disconnect the socket too many times,
then you may need to restart ser2net
service to clean up dead sockets.
With socat
It is possible to achieve the same result with a socat
relay.
socat tcp-listen:2000,reuseaddr,fork file:/dev/ttyS4,raw,nonblock,waitlock=/tmp/s0.lock,echo=0,b500000
tcp-listen:2000
makes socat listen on TCP 2000.
The serial TTY is open as raw
to pass input and output unprocessed,
nonblock
to open in nonblocking mode,
echo=0
to disable local echo,
b500000
to set the baud-rate.
You may also consider using UDP to achieve faster commands,
socat udp-recvfrom:2000,fork file:/dev/ttyS4,raw,nonblock,echo=0,b500000
You may have to write a Systemd service unit to establish these relays at boot,
edit /etc/systemd/system/socat-tcp.service
:
[Unit]
Description=Socat TCP to ttyS4 relay
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/socat tcp-listen:2000,reuseaddr,fork file:/dev/ttyS4,raw,nonblock,waitlock=/tmp/s0.lock,echo=0,b500000
Restart=on-failure
[Install]
WantedBy=multi-user.target
Client-side
A client implementation is available at https://github.com/erdnaxe/kraby/blob/master/gym_kraby/utils/herkulex_socket.py.
This client is able to control the robot and get positions, velocities and speeds from all servomotors.
You can send a demo choreography to 10.42.0.1:2000
with:
python -m gym_kraby.utils.herkulex_socket
The robot will reset to its neutral position, then will receive position commands each 50 ms and will finally reset to its neutral position.
How slow is it?
The biggest bottleneck in this implementation is the data collecting. All servomotors need to be manually pulled one at a time to get all positions, velocities and torques. This takes approximatively:
- between 100 and 140 ms at 115 200 bauds/s with a TCP connection over WiFi
- between 60 and 100 ms at 500 000 bauds/s with a TCP connection over WiFi
- between 35 and 50 ms at 500 000 bauds/s with a local TCP connection
For the command it is much faster as it can be done using only one
S_JOG
packet2.
-
“NanoPi NEO4.” FriendlyARM Wiki. October 2019. ↩
-
“Herkulex DRS-0101/DRS-0201 User Manual.” Version 1.00, March 2011. ↩
-
“RK3368 device-tree”, lines 388-398. Linux Kernel source code. April 2020. ↩