Simulating a serial device with SITL

Hello,

I have a device that sends out 4 comma separated values at 9600 baud. I want to grab them with Serial5 on Pix 4(I’m assuming Serial5 is UART & I2C B first 3 pins), and forward them into the ground station as a mavlink package. Before I start flashing the Pix I’m trying to get this working in simulator.
I’m using Ubuntu 20.04 virtual machine for SITL.
I start the simulator as follows:
sim_vehicle.py -v ArduCopter -A “–uartF=/dev/ttyS1”
I set Serial5 protocol to “none” and baud to 9600. However when I try to connect to /dev/ttyS1 with ‘screen’ or simple python script I get an I/O error. My user is in the dialout group.

This is the python script I’m using:
#!/usr/bin/python
import serial,time,sys
try:
ser=serial.Serial(“/dev/ttyS1”,9600)
print(ser.name)
while True:
read_serial=ser.readline()
print(read_serial.rstrip(“\n”))
time.sleep(2)
except KeyboardInterrupt:
ser.close()
sys.exit()

I’m going to write a simple python program that generates the 4 comma separated values and sends them to SITL. But I simply can’t do that right now because I’m not able to connect to SITL via serial.

I also tried the script that decodes mavlink messages with no luck:

Am I understanding correctly that when I start SITL with a virtual serial port attached to it and connect to it with ‘screen’ I should at least see some gibberish(heartbeat package when i set the serial protocol to mavlink1 or 2) ? Right now screen just terminates.

Right now it seems that maybe Ubuntu is blocking it but dmesg output is empty…

Thank you for your time,

Andri

2 Likes

Hello,

I’ve been tackling the same problem again and with some debug results.

Setup:

In the first terminal I set up a virtual terminal pipe between /dev/pts/3 and /dev/pts/4 at 9600 baud. They are in fact working as I can check that with screen or cat.

$: socat -d -d pty,raw,echo=0,b9600 pty,raw,echo=0,b9600

Whether this command is 100% correct is irrelevant because even if baud doesn’t match or something There should be some gibberish displayed.

What this command does is the following: if I send data over to /dev/pts/3 it is displayed in /dev/pts/4 and it works both ways.

In the second terminal I run mavlink packet processing script I found on the forums. Which is mentioned in the previous post:

$:python mavtest.py /dev/pts/4

In the third terminal I just echo some random data in order to show that the pipe actually works:
$:echo b"data" > /dev/pts/3

Now when I start the SITL simulation in the forth terminal I see literally no data coming in, I think it should at least send a heartbeat package but it’s silent.

$: sim_vehicle.py -v ArduCopter -A “–uartB=uart:/dev/pts/3,9600”

When I echo manually again I see that the pipe actually works.

I need all of this to virtually simulate a serial device because it’s mission critical(hydrogen fuel cell tank percentage and error codes) and I’d like to test this in simulation before flashing it blindly into my PX4.

I’ll attach a video of described process. Sorry for the flickering, screen recording on wayland is horrible.

Thank you for your attention,

Andri

So what I’ve noticed in my debug sessions. First of all this --uartF=… flag is not processed at all. When I run sim_vehicle.py:

SIM_VEHICLE: “/home/andri/ardupilot/Tools/autotest/run_in_terminal_window.sh” “ArduCopter” “/home/andri/ardupilot/build/sitl/bin/arducopter” “-S” “–model” “+” “–speedup” “1” “–uartF=uart:/dev/pts/6,9600” “–defaults” “/home/andri/ardupilot/Tools/autotest/default_params/copter.parm” “-I0”

So I did grep around the whole source directory and found that uartF flag is processed by:
ardupilot/libraries/AP_HAL_SITL/SITL_cmdline.cpp

However these cases are empty(lines 358-364):

case CMDLINE_UARTA:
case CMDLINE_UARTB:
case CMDLINE_UARTC:
case CMDLINE_UARTD:
case CMDLINE_UARTE:
case CMDLINE_UARTF:
case CMDLINE_UARTG:

Now I know from sim_vehicle.py script output that the binary run by it is:

/home/andri/ardupilot/build/sitl/bin/arducopter

When I edit SITL_cmdline.cpp and add a simple print to the case when uartF is specified, it does recompile but nothing is printed when run with sim_vehicle.py script.

When I run that binary manually, my debug prints appear. So I think the documentation is wrong? I should implement the simulation of uart on my own then as this is a nice feature to have.

hello,

the CMDLINE_UART* aren’t empty … .they just call the same function :

_uart_path[opt - CMDLINE_UARTA] = gopt.optarg;

Where do you look ? it won’t print into the sim_vehicle window but in the xterm window where SITL is running … there are no difference between manually launch SITL and with sim_vehicle.py …

Now when I start the SITL simulation in the forth terminal I see literally no data coming in, I think it should at least send a heartbeat package but it’s silent.

No by default you don’t have anything output on a port … I you want some mavlink message you should ask for some … but no idea yet on how to do it on serial5

Thank you for your reply.

What I actually need to achieve is uart5 to grab simple serial input and the autopilot should grab the values and process them. But first I need to figure out how serial is connected to ardupilot.

Sorry for my rookie mistake… indeed the ‘break’ statement appears after UARTH… I’ll dig deeper from this line.

Thank you again for your attention.

I did get uartF working now. I found the necessary clues from libraries/AP_HAL_SITL/UARTDriver.cpp.
There is a comment that uart string should be formated as such:

uart:/dev/ttyUSB0:57600

I used comma to separate the device and baudrate…

When I set the protocol to mavlink1/2 on SERIAL5(in QGroundControl) it starts sending out HEARTBEAT packages which I can successfully see from the mavlink package testing script listening on the other end of the tunnel(/dev/pts/4).

Now I’m going to try to send raw values to autopilot and go forward from there.

Hey, I’m trying to do the same. Any updates? Did you get it working?