Help needed with parsing a serial string or array

27 Aug 2010 . Edited: 27 Aug 2010

I am trying to parse a string (it may be an array, I havent a clue what the diffrence is).

Its composed of 6 diffrent numeric values. the first 4 values are 3 digits long, while the last 2 are 4 digits each. there is nothing seperating the values, so the string will look like so: 11122233344455556666 with a line feed at the end.

 

I need to chop it up and store it in 6 variables. I have came up with the following but cant get it to work.

 

 

#include "mbed.h"



Serial pc(USBTX, USBRX);  // USBTX - Tranmit on USB  USBRX - receive on USB

int main()
{
   
   
    
// Set the Serial variables
   pc.baud(9600);
   pc.format(8, Serial::None, 1);

    pc.printf ("helloworld\n");

float thingy, one, two , three, four, five, six;

 while(1){
pc.scanf("%f","%f","%f","%f","%f","%f", &one, &two, &three, &four, &five, &six);


thingy = one;

pc.printf ("%f\n", thingy);

}
}

I am trying to printf the variable "thingy" to test if the string s being parsed. I get nothing back in in my terminal program, but I do get "hello world" that I put into the code before my while loop.

 

 

Any help is welcomed.

27 Aug 2010

Your data is a string; a string is an array of characters.

You're nearly there. The problem is that you know how long each substring is, but the computer doesn't. You need to specify the length of each numeric string in your scanf format.

If you replace your current pc.scanf line with

pc.scanf(data, "%3f%3f%3f%3f%4f%4f", &one, &two, &three, &four, &five, &six);

it should work fine.

27 Aug 2010

WOW!

Thanks a bunch, it totally works now! I have been working on this for months (little bits at a time) and couldnt get anything to happen. I should have asked a long time ago.

27 Aug 2010

I'm glad I could help. Do ask if you get stuck - we all learn from each other here.

27 Aug 2010

If the numbers are integers, you could save some processing time and use integers instead of floats. Use '%d' format specifier to parse an integer.

20 Nov 2010

Hello again,

I had the following code working. I added a simple pwm to test a motor controller. I somehow killed my mbed and had to replace it. After getting the new mbed, I added more to my code because I thought it was working. I now cant get it to parse and change the pwm value or printf anything. I tested the simple srial demos and they work just fine. I reduced my code to just a simple scanf-printf program and cant get it to work.

 

#include "mbed.h"




int main()
{

 
// Set the Serial variables

 Serial pc(USBTX, USBRX);  // USBTX - Tranmit on USB  USBRX - receive on USB
 pc.baud(9600);
 pc.format(8, Serial::None, 1);
 
 
 // Serial xbee(p9, p10);  // tx, rx   
//  xbee.baud(9600);
 // xbee.format(8, Serial::None, 1);

        pc.printf("I'm alive!");




    


   
//variables

    float mtrl, mtrrt;  
    int lx, ly, rx, ry, btn,  dir;
    
//pin constants
    DigitalOut mtctl(p26); //motor controller power
    PwmOut lpwm(p22); //PWM for left motors
    PwmOut rpwm(p21); //PWM for right motors
    DigitalOut rfor(p28); //right forward enable
    DigitalOut lfor(p30); //left forward enable
    DigitalOut rrev(p27); //right reverse enable
    DigitalOut lrev(p29); //left reverse enable
    
    
    
    
    while(1) // infinite while loop. to be changed to contitional statement that will only run if valid serial data is present.
    {pc.printf("I'm alive!");
         // xbee.scanf( "%3d%3d%3d%3d%4d%4d\n", &lx, &ly, &rx, &ry, &dir, &btn);
          //xbee.getc();
            pc.scanf( "%3d%3d%3d%3d%4d%4d", &lx, &ly, &rx, &ry, &dir, &btn);
           
           mtctl = 1;
   
   
    //math for pwm dutycycle
    mtrl = (ly * .00125);
    mtrrt = (ry * .00125);
    
    lpwm.period_ms(0.5);
    lpwm.pulsewidth_ms(mtrl);
    
    rpwm.period_ms(0.5);
    rpwm.pulsewidth_ms(mtrrt);
           
     
    
     
   pc.printf ("left y%f,motor%f\n", ly, mtrl);
   //pc.printf ("motor%f\n", mtrl);    
    }
}
The code above doesnt work.

and the following will not work as well

 

#include "mbed.h"




int main()
{

 

 Serial pc(USBTX, USBRX);  // USBTX - Tranmit on USB  USBRX - receive on USB
 pc.baud(9600);
 pc.format(8, Serial::None, 1);
 
 
        pc.printf("I'm alive!");




    


   
//variables

    float mtrl, mtrrt;  
    int lx, ly, rx, ry, btn,  dir;
    
    
    
    
    while(1) // infinite while loop. to be changed to contitional statement that will only run if valid serial data is present.
    {

 pc.scanf( "%3d%3d%3d%3d%4d%4d", &lx, &ly, &rx, &ry, &dir, &btn);
           
     
    
     
   pc.printf ("left y%f,motor%f\n", ly, mtrl);
   //pc.printf ("motor%f\n", mtrl);    
    }
}

20 Nov 2010

Take a look at the format specifiers in your printf() function.

You have specified 2 floats (two "%f"), but as actual arguments you have provided an integer (ly) and a float (mtr1).

Try this instead (note the first specifier is changed from "%f" to "%d")

pc.printf ("left y%d,motor%f\n", ly, mtrl);
28 Nov 2010

Thanks IIian,

I fixed the error you pointed out but it didnt help. I stumbled across what caused the serial problem; I had to move

Serial pc(USBTX, USBRX);
above main.

With that fixed I ran ino the next problem. I'm making a remotely controlled wheeled rover using labview to control it. I am having more trouble parsing the string still. It seems to me that the mbed is skipping or ignoring the end of line character.

Does anyone know what I should be sending to the mbed to mark the EOL and the proper C syntax so the mbed will not sip the EOL char?

 

Thanks again everyone!

-Bill

28 Nov 2010

Glad you found a solution for the problem with Serial object location. I'm not familiar with mbed yet so I can't say why it doesn't work if defined as a local variable.

 

For your other problem - scanf() is a high-level function, so it is normal for it to ignore delimiter characters (EOL in particular). If you need a special handling of characters like EOL, you should use some of the lower-level functions of Serial class. Take a look at putc()/getc(), which writes/reads a single character, or gets(), which reads a single line. But in this case, you will need to store fetched characters in your own buffer, and later parse its content to extract the actual numbers.

 

Hope this helps.

-Ilian

29 Nov 2010

Wonderful! Thanks again Ilian.

I'm really new to programming and relly appreciate the help.

I'm not really sure how to pass the string into an array to be parsed. I think it woud be something like this:

char mystring [21];

int data [21];

int lx, ly, rx, ry, btn,  dir;

gets(mystring);

data = mystring (%d3%d3%d3%d3%d4%d4, &lx, &ly, &rx, &ry, &btn,  &dir;);
but it doesnt work and is the best I can come up with after searching for several hours in my books and on cplusplus.com. My lack of experience with programming is keeping be from seeing the solution to this.

 

Thanks again for the help and patience!

29 Nov 2010

Argh! I've been banging my head against this problem for 6 hours straight. I'm just cant wrap my head around this.

Can anyone point me in the right direction with a sample of how to pass a string using gets to a buffer or similar and parse the chars as ints?

Sorry about copping out and asking to have my hand held. I'm just too new at programming.

29 Nov 2010

Hi Bill,

I'm guessing you are looking for something like this:

#include "mbed.h"

char str[] = "123456789123456789123456789";

int main() {
    int r[6];
    int n = sscanf(str, "%3d%3d%3d%3d%4d%4d", &r[0], &r[1], &r[2], &r[3], &r[4], &r[5]);
    if(n != 6) {
        error("Only read %d items", n);
    }
    
    printf("Results:\n");
    for(int i=0; i<6;i++) {
        printf("r[%d] = %d\n", i, r[i]);
    }
}

which gives the results:

Results:
r[0] = 123
r[1] = 456
r[2] = 789
r[3] = 123
r[4] = 4567
r[5] = 8912

Simon

21 Dec 2010

Thanks Simon, The example above worked great. The only problem is, I had a completely different problem than I first thought. After reading what felt like every post in this forum, I tripped over the answer. Since the mbed serial function is not buffered and blocking one, I had to change my lab view code. I had to make Labview wait for a message from the mbed before its transmits. before it was just continually sending a string non stop and the mbed would pick up the string in the middle of a transmit until it got a LF. I made the mbed send the serial message needed for Labview to send right before it enters the scanf function. That finally solved my self induced problem. On top of issue I had above, I could not get my Xbee modules to work. I found out that the regulator on my breakout board from Sparkfun will not supply enough current to my Xbee XSC 900 modules. So when my regulator comes in and I get it installed I'll post a vid and pics of my rover.

Thanks for the help. I learn more here than I do from the C++ books I have, and its way more fun!