Main application architecture for robotics

Hello everyone.

For the context of this topic, I am robotics software engineer, used to “high level” software on linux (with lot of CPU, memory, threads, etc).

I am developping a sensor+actuators board with a STM32H7 as main controller.

The STM32 has to read a dozen of sensors (on I2C, UART, analog), send data and received orders @50Hz from a computer, and has to write on a SD Card + update PWM + write on UART.

Each sensor has a different refresh time, some sensors push data, some sensors has to be triggered (for instance trigger ADC, wait, read), each sensor has a different refresh rate (from 1 to 500 Hz).

Actuator loop has to be as real-time as possible @ 50Hz (to update PWM outputs + send UART command).

As I said previously, my past experiences directed me to mbed as this framework is simple and easy to use (for me at least), and the few tests I have done with some sensors are successful.

So I may have newbie questions, but I want to have pointers or answers on this points, based on your embedded developpers skill exeperience that I don’t have (yet). I think my 'high level" linux developper approach is not the good one here.

  1. Since there are a lot of sensors, is a multithread approach can be considered ? (Like 1 thread per task or per refresh rate?)

  2. If I have one single loop, reading each sensors when it’s time, it means that all functions calls have to return as fast as possible (+non blocking call). A lot of sensors drivers I have tested have sleep times in them (for instance: trigger ADC read, wait 1ms, read result), which is not possible in that case. What are the good practices here ?

  3. I will have a lot of TX UART to stream all data to a computer periodically. I can not block the main thread with that. Is there a UART TX-queue or send buffer or something like this on mbed ? If I have to do this myself, is a thread the good solution ?

Thank you ! :slightly_smiling_face:

If I have one single loop, reading each sensors when it’s time, it means that all functions calls have to return as fast as possible (+non blocking call). A lot of sensors drivers I have tested have sleep times in them (for instance: trigger ADC read, wait 1ms, read result), which is not possible in that case. What are the good practices here ?

I’ve ran into stuff like this too, it’s annoying. You basically have two options here. First, you can run the driver in its own thread, so that other useful stuff can happen during the sleep time. However, you wiill have to be careful that the driver isn’t still using anything (e.g. keeping a chip select pin high, or keeping an I2C bus locked) during the sleep time, or you might cause issues. Option two is to modify the driver to split it into things that happen before and after the sleep time. E.g. change getMeasurement() to startMeasurement() and getMeasurementResults() which you can call later to get the result data.

I will have a lot of TX UART to stream all data to a computer periodically. I can not block the main thread with that. Is there a UART TX-queue or send buffer or something like this on mbed ? If I have to do this myself, is a thread the good solution ?

This is what MBed OS 6 BufferedSerial is made for! You used to need a 3rd party library (MODSERIAL) for this functionality, but now an (interrupt-based) background serial transmitter is built in to the OS.

Thanks @MultipleMonomials.

When the number of sensors is going high, the second option is, I think, better, too avoid painful thread/lock/bus synchronization.

The thing is, it is still difficult for me (lack of experience) to choose between the 2 options, which is why I am asking pros and cons of both solutions.

I’ll have a look thanks (I was still on MBed OS 5).