cancel
Showing results for 
Search instead for 
Did you mean: 

How do I synchronize received UART data ?

johngj
Senior

I am trying to receive a frame containing 10 bytes of serial data, each frame is transmitted at a 100ms rate.

However, as the UART can start receiving the 10 byte frame at any point in time, the received data is becoming out of sync. 

How do I sync the UART peripheral so that it always starts receiving at the start of the 10 byte frame ?

Below is a scope capture of the 10 bytes of serial data:

johngj_0-1706805151387.png

Below is a scope capture of the 10 bytes of serial data being sent at a 100ms rate:

johngj_1-1706805208495.png

I am using the STM32 Nucleo-64 development board with STM32L433RC MCU. 

Its as if I need to monitor the serial line with a timer, in order to detect the period when the serial line is high for say 50ms and use this timer to enable and disable the UART peripheral.  But there must be a better way to do this ?

The UART is configured as shown below and the rx buffer is a size of 10.

johngj_2-1706805851655.png

johngj_3-1706805879295.png

johngj_4-1706805905455.png

The 10 bytes are transmitted by a electronic speed controller, used for radio control applications and contains the following data:

Byte 0: Temperature
Byte 1: Voltage high byte
Byte 2: Voltage low byte
Byte 3: Current high byte
Byte 4: Current low byte
Byte 5: Consumption high byte
Byte 6: Consumption low byte
Byte 7: Rpm high byte
Byte 8: Rpm low byte
Byte 9: 8-bit CRC

 

 

 

 

23 REPLIES 23

Thanks Karl

 

I see you call process_telemetry but no where do i see that you are saving the data to the SD card? 

I haven't implemented this yet and still working out how to do it

I used this example to make a start...

https://controllerstech.com/sd-card-using-spi-in-stm32/ 

I want to write the data as a binary file as this is more efficient than writing as an ASCII

So I am having to research how FAT works in order to be able to do this efficiently


When you say the data is out of sync, do you mean that the packet contains some data from one packet and data from another packet? 

Yes that's correct

I downloaded openlager from git but have no idea how you use it in Cube IDE.

If I 'Open projects from file system....' and point to the openlagger folder, everything opens but its not possible to build.

If I create a new STM32 project and add the folder to the project then I get lots of build errors

How do I use openlager in Cube IDE for the NUCLEO-L433RC-P ?

 

Well if you're getting out of sync data and not saving the data to the SD card yet, then calling process_telemtry from inside an interrupt is your problem. You never do any processing inside an interrupt. You set a flag and exit the interrupt.

What's probably happening is while you're processing the data inside of the interrupt, the UART is starting to miss bytes as new packet is being received. 

Now your processing isn't much and be done within microseconds, but somehow it's taking longer than it should.  You're using the same buffer so the current packet you're processing is being overwritten with some new partial packet bytes.

You should use a ring buffer so while one queue is being processed, the 2nd packet is being saved to another queue.

See this project https://github.com/karlyamashita/ParseTelemetryData/wiki

 

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

It works correctly when I use the HAL_UARTEx_ReceiveToIdle_IT function (as suggested by KMill).  The project is attached for reference.

I don't bother decoding the telemetry anymore (i.e. the process_telem function), instead I just write the 10 bytes of serial data directly to the SD card each time the packet is received. 

I will need to implement some post processing (using MATLAB, Python etc) to read the packets from the SD card, then decode each packet into the measurements and finally check the CRC.

At the moment my code just saves 4 packets (i.e. 4 x10 bytes) of serial data to the SD card.  When I open the file on the SD card it shows the 4 packets (I have highlighted each packet red or blue)...

johngj_1-1707230633687.png

This is still WIP because I still need to implement:

1. Timestamp

I need to add a time stamp to each packet.  I was going to use the RTC and convert the date and time to UNIX (EPOCH) 32 bit, but now I'm not so sure.  Firstly UNIX time precision is in seconds, but the serial packets are currently sent at a 100ms so the UNIX time stamp would be the same for every 10 packets.  Theres also no point in storing the year, month and day for every packet received !  

2. SD card sector

The code currently writes to the SD card each time 10 bytes of serial data is received.  I don't know much about SD cards and FAT, I believe data is written in blocks of 512 bytes.  In which case I would be better to only write to the SD card after I have received enough data to write to a sector on the SD card.  I dont know how SD cards work when writing bytes that are not aligned to the sector boundary either.  It obviously takes time to write to each sector, so theres no point writing 10 bytes at a time and I believe it also wears the SD card out quicker ?

3. Continuous datalog file or split files

I know in car dashcams, the video files are split up into individual files (usually in terms of time).  I might need to implement the same, somehow

4. SD card full, overwrite old logs

When the SD card is full I will need to overwrite logs, somehow

5. Start and stop the logging

At the moment the logging is stopped after 4 packets have been received, I only did it like this because the f_close function needs to be called to close the file.  This needs to change so that some other external event stops the logging and calls the f_close function e.g. no serial data received for a set time, or a button press, or monitoring of a  supply voltage etc

 

I might have to create new posts for help for items 1 to 4