9 years, 1 month ago.

How do I improve data acquisition by using serial communication?

Hello!

I'm trying to do some data acquisition from 17 variables of a system I created. The microcontroller collects information from 4 force resistors and 1 gyroscope and send them to a interface (created with MS Visual Studio) by using printf(). Then, the interface read the information sent by the printf() and show it. For this, I've created a pattern. However, the microcontroller sends the information in asynchronous way. To explain better, I'll give an example:

The microcontroller collects information from 4 force resistence sensors. Then it sends the information by using printf():

prinft("F1=%.4fF2=%.4fF3=%.4fF4=%.4f", force1, force2, force3, force4);

However, the interface receives data like this:

F1=1.0098F2=2.78 (1st stream)

08F3=0.0000F (2nd stream)

4=1.9832 (3rd stream)

Instead of just one stream:

F1=1.0098F2=2.7808F3=0.0000F4=1.9832.

How can I solve this problem?

1 Answer

9 years, 1 month ago.

The issue is nothing to do with the mbed, it's how windows is handling the serial data. It has no way of knowing when the data ends and so when your program requests the serial data the system waits a short time and then passes whatever data it's got to your program for processing.

It's the job of your program in visual studio to put the messages back together again.

This is a lot easier if each of your messages has a little more standard formatting. e.g. start and end markers, start each line with a $ and end it with a '/n'. You can then ignore all the data until you see a $ (in case you started listening in the middle of a message), collect everything into one big buffer until you see \n and then process the data in the buffer knowing you have a single full message. If you only ever need 4 values then scanf fill work to extract the numbers from the string but if you need more flexibility then consider using ',' or some other single character if instead of using Fn= between each value. That way you can use something like strtok or it's c# equivalent string.split() to split the input line into individual values.

You didn't say if the PC end was c, c++, c# or something else but most systems provide a method to request a line from the serial port rather than reading however many bytes are waiting. That way the system handles grouping all the data together until it sees a '/n' and passes it in a single bundle to your application.

Accepted Answer

Dear Andy,

I suspected about this. However, I already had these ideas you gave me. I tried separators such as ';', '\n', '=' and ','. I'm using C#, but I don't know a function which ignores all data until I see any separator. Do you know?

My code logic is:

By supposing that my data is:

$1.8988;2.9348;0.0874;0.9831\n

But my supervisory is receiving data combos messed up such as:

31\n$1.8988;2.9348;0.0874;0.9831\n$1.8988;2.9348;0.087

It will not interpret the data till it begins with '$'. That takes many iterations which is not supposed to be since it's in real-time supervisory.

Do you know any function I can use?

Thank you, I appreciate your attention!

posted by Antonio Totorica 18 Jun 2015

If you're using the c# serialPort class then ReadTo('$'); followed by ReadLine(); should give you the next complete line.

Or the bare bones method, don't expect the input from the system to start with a $. Check each character in the input in turn until you find the start character and then use substring to discard the junk at the start.

If you get an incomplete line at the end of the input keep it and add it to the start of the next string you get.

posted by Andy A 18 Jun 2015

Ok! I will try to do it.

Once more, thanks for your attention!

posted by Antonio Totorica 18 Jun 2015