5 years ago.

What is the best way to read serial data and parse to float?

I want to be able to send 3 values to my mbed device and then parse them into 3 variables. example input: 12.13,31.031,-0.13 The deliminator can be space instead of a comma if it is easier to work with.

From what i understand i need to read the serial buffer into a string. Then parse the string to get my variables.

I've come across sscanf() and strtok() with atof(), sscanf() seems to be far simpler to use that the strtok() and atof() combination, is there a significant cost to cpu usage using sscanf() instead?

(I'm using a F411RE at 96MHz and i doubt im pushing it close to its limit.)

Another issue is some people use interrupts while others use it in there while(true) loop with

if(pc.readable()>0) {serial stuff}

I would like to be doing other stuff while not reading the serial (i.e reading angle data off a mpu6050), so would using the interrupt be a better solution for my case?

I'd prefer the easier option at the expense of cpu time, given the cost isn't too high.

Can this be done with RPC api?

1 Answer

5 years ago.

If things will always be the same format then sscanf() is the easier approach.

Strtok() and atof() is a lot more flexible since you can change the expected format based on the values in earlier fields or handle empty fields.

If you want to do anything else at the same time then use an interrupt to capture the serial data.

In the example below the serial interrupt collects the data and then when it receives a new line character it attempts to parse it for the 3 values. If that works it updates the values of some global variables and sets a flag indicating that there is new data from the serial port.

When the main loop isn't busy with something else it can then check for new serial data.

If you need to read from the mpu6050 at a regular rate then I'd recommend using a ticker to read the values and then use a similar method of setting a flag for the main loop when there is new data. That way the main loop isn't collecting any data directly, that is all done on interrupts. All the main loop does is constantly check for new data and handle it as it arrives.

volatile bool newData = false;
volatile float inputs[3];

onSerialRx() {

  static char serialInBuffer[32]; 
  static int serialCount = 0;

 while (pc.readable()) { // in case two bytes are ready
   char byteIn = pc.getc();
   if ( (byteIn == 0x0D) || ( (byteIn == 0x0A)) { // if an end of line is found
    serialInBuffer[serialCount] == 0;                 // null terminate the input
    float x,y,z;
    if (sscanf(serialInBuffer,"%f,%f,%f",&x,&y,&z) == 3) { // managed to read all 3 values
      inputs[0] = x;
      inputs[1] = y;
      inputs[2] = z;
      newData = true;
    serialCount = 0; // reset the buffer
   } else {
    serialInBuffer[serialCount] = byteIn;            // store the character
    if (serialCount<32)                                      // increase the counter.

main () {
  while (true) {
    if (newData){  
      newData = false;
      pc.printf("Got %.3f, %.3f, %.3f\n\r",inputs[0],inputs[1],inputs[2]);

    // other stuff (nothing that will take longer than the time between serial messages)



This doesn't even compile.

posted by Ian Wolf 24 Aug 2017

You're right. It doesn't compile, it's missing the lines to define the serial port and include the mbed library. Lines which the person posting the question clearly already had in their code.

It also has one error of an excessive bracket which the compiler tells you the correct line to fix and is a clear and obvious copy and paste error once you are looking at that line. And there is a warning about a lack of return type for a function which can be ignored but is also trivial to fix if you want to.

If you had asked for help I would have updated the code to fix these issues but since you seem to enjoy complaining I'll not do that so you can complain some more about the lack of help.

posted by Andy A 25 Aug 2017


posted by Deddy Welsan 14 Dec 2018