'(embedded) How to read data from uart (Python+C)

I need to transmit data through UART from different sensors. I need to form packet with data from sensors on microcontroller. Then transmit it through uart. and then decode it on laptop. For 1 sensor i have a code:

    while (1)
  {
      get_Temperature();
      HAL_Delay(2000);
      char buffer[100];
      seg = Temp[0];   //here our temperature
      sprintf(buffer, "%d",seg); //transform temperautre to string
      HAL_UART_Transmit(&huart2, (uint8_t*)buffer, strlen(buffer), 1000); //string transmit
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

For decode it on laptop i have a code(python with pyserial):

cons = wox.read_all().decode("utf-8")

*in loop And my output is a value of temperature in string format:

24
24
25
24

depends on temperature of the sensor.

I can use the second sensor with another value Temp[1]

But i need to form packet with that data and decode it on laptop. How can i do it?



Solution 1:[1]

You might use delimiters to separate and carry the data in a single message and you should also use a delimiter for the end (or start, or both) of the data rather than relying on the delay to separate "messages". You might later want the data at a much higher rate or streaming, and "24,3224,32" would be ambiguous. For example

sprintf(buffer, "%d,%d\n", Temp[0], Temp[1] ) ;

Then the output would be clearly delimited:

24,32<newline>
24,32<newline>
...

Then at the receiver (in Python - not my area of expertise), you can use read line semantics (message = wox.readline().decode("utf-8")?) to get the entire message rather than relying on any specific timing.

A more flexible alternative, that would be extensible to more sensors of different types, outputting at different intervals in multiple threads, would be to tag the data with its sensor ID. For example, you might independently have:

sprintf( buffer, "T0:%d\n", Temp[0] ) ;

and

sprintf( buffer, "T1:%d\n", Temp[0] ) ;

Or even an accelerometer with:

sprintf( buffer, "AC:%d,%d,%d\n", x, y, z ) ;

So the output stream might look like:

AC:24,2,33<newline>
AC:24,2,33<newline>
AC:24,2,33<newline>
AC:24,2,33<newline>
T1:33<newline>
AC:24,2,33<newline>
AC:24,2,33<newline>
AC:24,2,33<newline>
AC:24,2,33<newline>
T0:24<newline>
...

Where the messages are free to arrive in any order, and at any frequency. Of course if multi-threaded, you'd probably want a single thread actually outputting to the UART with sensor threads placing messages in a queue, or otherwise ensure the independent messages were correctly serialised and not "interleaved".

You might split out sensor type from sensor instance so you could extend to any number for sensors of a particular type, so rather then say T0:, T1: and AC: you might have T#0:, T#1: and AC#0: for example followed by comma delimited parameters then <newline>.

If synchronisation/timing is critical and you have a source of time (relative or absolute), you might even add a timestamp to the message; e.g.:

sprintf( buffer, "$%lu,T0:%d\n", tick_ms(), Temp[0] ) ;

to the output message might look like:

$1256,T1:33<newline>
$1256,T0:55<newline>
$3256,T1:34<newline>
$3256,T0:54<newline>

The specific delimiters are arbitrary - your design.

If you want a great deal of flexibility and compatibility you could even output the data as an XML or JSON schema. A bit heavyweight for the embedded end perhaps, but there are no end of parsers available for Python to handle that, and the schema would be publishable to allow others to easily parse your data.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1