Robust serial communication with sensor module

Hello,

I’d like to set up a robust, bug free serial communication with a radar module, which can continously report data of an object, which meets the filtering parameters (e.g. object is within a specified range). The default report interval of the module is ~65ms, so the code should process data as fast as it can (however a simple speed report is not that long, so the RX buffer will not be filled so easily). The final code has to be validated with some measurements regarding the timing.

The main idea is to receive the speed data of the detected object, but with a safe approach. So if the report is not exactly the default report somehow (e.g starts with a timestamp, or magnitude is reported before the speed), get the right value anyway. I tried to write the code with this in mind, I added as much comment to explain what was my intention with certain instructions. I hope you get the idea. The module can save the parameters itself, unfortunately not all what is needed. The continous range report is switched on by default , but the switch off state cannot be saved. So to prepare for a reset situation, if range report starts (intended or unintended reset occured) this is used to set all the necessary parameters which were not saved permanently. Another good to have is the Blank Report, I chose comma ‘,’ for this purpose. If no object is detected, the module will continously report a comma with the above mentioned ~65ms. I’m intended to use this as a communication “watchdog” and reset the sensor module if comma is not received. This is not fully implemented yet.

I started with Serial Input Basics - Example 5 (thanks for the detailed description to @Robin2).

I added the basic message types to the beginning of the code. The sketch works as expected based on the early tests (not field test though, so I can’t tell how accurately yet). The “online” parameter setting also, after I inject a reset, the needed parameters are set. As I said I’d like this to be as reliable as can, this is why I ask for help, to get rid of every possible bug in early phase.

Could you point out where the communincation can go wrong with this code?

Thanks in advance.

radarRxTx_wo_debug.ino (10.4 KB)

You seem to have made a lot of changes to the code in Serial Input Basics - why? I have the feeling you are trying to do stuff in the function recvMsgFromRadar() that should really be done elsewhere.

You need to post a link to the datasheet for the radar module you are using. Without knowing in detail how it works it is impossible to comment on your code.

...R

You are right. Example 5. was not a good reference, because it uses recvWithStartEndMarkers(), my code only uses the endMarker to detect the end of the message.

I added the "comma check" in the receive function, because I think it belongs there. Received character is available (rc), and only the timer is refreshed based on the logic. I don't think these basic checks slow down the receive process considerably.

Module API document. However it is not too specific regarding the exact messages it sends, that is why I added them in the beginning of the code.

amazed:
You are right. Example 5. was not a good reference, because it uses recvWithStartEndMarkers(), my code only uses the endMarker to detect the end of the message.

Then all you need to do is use the recvWithEndMarker() function.

I added the "comma check" in the receive function, because I think it belongs there. Received character is available (rc), and only the timer is refreshed based on the logic. I don't think these basic checks slow down the receive process considerably.

It's not a question of whether it slows the process. It's whether it makes it work incorrectly, or just makes it unnecessarily complex.

If each message is terminated with a CR/LF then you should just use the standard recvWithEndMarker() function and parse the parts after the full message has been received. Among other things that allows you to view what has actually been received before you try parsing it.

...R

PS ... I wonder if the manufacturer has another document that describes the data format?

If each message is terminated with a CR/LF then you should just use the standard recvWithEndMarker() function and parse the parts after the full message has been received. Among other things that allows you to view what has actually been received before you try parsing it.

Okay, how should the code know what's been received if not by parsing, and identify the string in it? The code does what you mentioned, parses the received full message (ended with LF), identifies the string in it and based on that decides what to do with the following number(s).

amazed:
Okay, how should the code know what's been received if not by parsing, and identify the string in it?

You did not read carefully what I wrote in Reply #3. Of course you need to parse the data - but do it AFTER the full message has been received.

Breaking a program project into a series of short single-purpose functions makes the code much easier to develop and debug. The purpose of recvWithEndMarker() is to receive a message - not to parse it.

...R

I don't get where my misunderstanding comes from. The recvMsgFromRadar() function in the code does not parse the data. It receives Full line messages, then indicates if one has arrived. You mean the comma check? Two consequtive comma chatacter is thrown away, that is true. But apart from the fact that the radar is alive, the commas don't carry any information.

You will need to combine the recvWithEndMarker() with parts of example 5 ( parseData() and maybe showParsedData() ).

The simplest way is probably to remove the complete recvWithStartEndMarkers() function from example 5 and add the recvWithEndMarker() function.

amazed:
You mean the comma check? Two consequtive comma chatacter is thrown away, that is true.

That may ultimately be necessary but I would not do it in the recvWithEndMarker() function. It just complicates a simple function for no additional value.

And the reason for the consecutive commas is probably to signal that a value has been omitted - so don't throw away potentially useful information.

...R

sterretje:
The simplest way is probably to remove the complete recvWithStartEndMarkers() function from example 5 and add the recvWithEndMarker() function.

I agree. I have been assuming that is what the OP has been doing - but it would not be the first time I was wrong.

...R

If you want "a robust, bug free serial communication", I suggest you look at my tutorial Text I/O for the Real World

It uses my SafeString library to replace the low-level c-string methods with functions that check for overflow and out of range indexing. It catches your programming errors and prints detailed error messages so you can find them.
It gives you the ease of use of Arduino Strings but using fixed memory and can easily wrap char* data returned by libraries.

The Reading and Parsing GPS data example, shows you how to include detailed error checking and handles empty/missing fields (i.e. data,,moredata, . . )
The toInt(int i) and toFloat(float f) methods in the SafeString library are much more robust then the standard Arduino/c-string methods and return false if the string is not a valid number, otherwise return true and update the argument (i or f). SafeString toInt() returns false for "5a" where as Arduino/c-string return 5

That tutorial also includes sections on adding extra rx buffering and secitons on adding non-blocking Serial output so you don't miss data while debugging.

SafeString library also include a loopTimer so you can check the processing delays in your code.
See my tutorial on Multi-tasking in Arduino for detailed examples of doing multiple tasks where time is important.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.