serial.getc() problem

21 Sep 2010

I have 2 mbed and I am testing this code to simulate a binary GPS protocol. I need to get from the GPS somethig like this:

0xB5 0x62 0x01 0x05 ....{ 26 bytes}...0x47 0xF8

This is the code:

#include "mbed.h"



Serial pc(USBTX, USBRX);  // USBTX - Tranmit on USB  USBRX - receive on USB
Serial gps(p28, p27);  // tx, rx

int byte1=0xB5;
int byte2=0x62;
int byte3=0x00;
int byte4=0x11;
int byte5=0x00;
int byte6=0x00;
int byte7=0x11;
int byte8=0x00;
int byte9=0x00;
int byte10=0x00;
int byte11=0x11;
int byte12=0x00;
int byte13=0x00;
int byte14=0x00;
int byte15=0x00;
int byte16=0x00;
int byte17=0x00;
int byte18=0x11;
int byte19=0x00;
int byte20=0x22;

int main()
{    
// Set the Serial variables
   gps.baud(38400);
   wait(0.1);
   while(1) {
       gps.printf ("%c",byte1);
       gps.printf ("%c",byte2);
       gps.printf ("%c",byte3);
       gps.printf ("%c",byte4);
       gps.printf ("%c",byte5);
       gps.printf ("%c",byte6);           
       gps.printf ("%c",byte7);
       gps.printf ("%c",byte8);
       gps.printf ("%c",byte9);
       gps.printf ("%c",byte10);
       gps.printf ("%c",byte11);
       gps.printf ("%c",byte12);
       gps.printf ("%c",byte13);
       gps.printf ("%c",byte14);
       gps.printf ("%c",byte15);
       gps.printf ("%c",byte16);
       gps.printf ("%c",byte17);
       gps.printf ("%c",byte18);
       gps.printf ("%c",byte19);
       gps.printf ("%c",byte20); 

       wait(1);
   }
}

The other mbed (receiver) has this code:

#include "mbed.h"



Serial pc(USBTX, USBRX);  // USBTX - Tranmit on USB  USBRX - receive on USB
Serial gps(p28, p27);  // tx, rx
int MTK_payload_length_hi=26;
int MTK_payload_counter=0; 


//---unit refresh rate-----
char hz10[] = "$PMTK220,100*2F\r\n";
char hz4[] = "$PMTK220,250*29\r\n";
char hz1[] = "$PMTK220,1000*1F\r\n";

//---baud rates----------
char baud1[] = "$PMTK251,4800*14\r\n";
char baud2[] = "$PMTK251,9600*17\r\n";
char baud3[] = "$PMTK251,19200*22\r\n";
char baud4[] = "$PMTK251,38400*27\r\n";

//---NMEA protocols--------
char RMC[] = "$PGCMD,16,1,0,0,0,0*6B\r\n";
char VTG[] = "$PGCMD,16,0,1,0,0,0*6B\r\n";
char GSA[] = "$PGCMD,16,0,0,1,0,0*6B\r\n";
char GSV[] = "$PGCMD,16,0,0,0,1,0*6B\r\n";
char GGA[] = "$PGCMD,16,0,0,0,0,1*6B\r\n";
char BIN[] = "$PGCMD,16,0,0,0,0,0*6A\r\n";

void ini_gps() {
    gps.baud(38400);
    wait(0.1);
    pc.printf(BIN);
    pc.printf(hz1);
    gps.printf(BIN);
    wait(0.1);
    gps.printf(hz1);
    wait(0.1);
} 

void decode_gps(void) {
    int numc;
    char data;
    static int GPS_step=0;
    numc= gps.readable();    
    if (numc>0) {
        for (int i=0; i<numc ;i++){            
            data = gps.getc();  
            switch(GPS_step){
                case 0:
                    if(data==0xB5){                       
                        pc.printf("0x%X\n\r",data);
                        GPS_step++;
                        break;
                        }
                case 1:
                    if(data==0x62){
                        GPS_step++;                        
                        pc.printf("0x%X\n\r",data);
                        }
                    else {
                        GPS_step=0;
                        }
                        break;
                case 2:
                    pc.printf("0x%X\n\r",data);                                       
                    GPS_step++;
                    break;
                case 3:
                    pc.printf("0x%X\n\r",data);                    
                    GPS_step++;
                    MTK_payload_counter=0;                    
                    break;
                case 4:
                   if (MTK_payload_counter<MTK_payload_length_hi) {
                        pc.printf("0x%X\n\r",data);                                                
                        MTK_payload_counter++;
                    
                        if (MTK_payload_counter==MTK_payload_length_hi) {
                            GPS_step++;
                            }
                            }
                            
                        break;
                case 5:
                    pc.printf("0x%X\n\r",data);                    
                    GPS_step++;
                    break;
                case 6:
                    pc.printf("0x%X\n\r",data);                                                             
                    GPS_step=0;                    
                    break;
                }
           }
      }
}
int main(){
    ini_gps();
    wait(0.1);
    pc.printf("comienzo programa\r\n");
    while(1){
    decode_gps();
    }
 }
And this is what i get:

0xB5
0x62
0x0
0x11
0x0
0x0
0x11
0x0
0x0
0x0
0x11
0x0
0x0
0x0
0x0
0x0
0x0
0x11       (byte18)
0xB5
0x62
0x0
0x11
0x0
0x0
0x11
0x0
0x0
0x0
0x11
0x0
0x0
0x0        (byte14)
0xB5     (at this point is repeated)
0x62
0x0
0x11

......

 

I never get to the last byte. why??  thanks in advance

21 Sep 2010

Dear Mr.Jose

I think the program has two problems.

  1. The program use printf functions. But it's really slow. So the received serial data will be lost.
  2. Serial::readable() returns 1 if there is a character available to read else 0. (It's only 1 or 0!)

You can use a BufferedSerial class if you want it.SerialGPS

Please see "How's that interrupt-driven UART coming on ?" for more information.

Regards

Shin.

21 Sep 2010

Dear Shin

Thanks for your response. It was the "printf" functions. As you said it was very slow. I made a simple change to the code and put the function printf only to know if the last byte recieved was 0x22 and it worked.

Thanks for the program too!! I will have a look over it.

Jose

21 Sep 2010

#include "mbed.h"



Serial pc(USBTX, USBRX);  // USBTX - Tranmit on USB  USBRX - receive on USB
Serial gps(p28, p27);  // tx, rx
int MTK_payload_length_hi=26; //original 26
int MTK_payload_counter=0; 
char msg[32];

//---unit refresh rate-----
char hz10[] = "$PMTK220,100*2F\r\n";
char hz4[] = "$PMTK220,250*29\r\n";
char hz1[] = "$PMTK220,1000*1F\r\n";

//---baud rates----------
char baud1[] = "$PMTK251,4800*14\r\n";
char baud2[] = "$PMTK251,9600*17\r\n";
char baud3[] = "$PMTK251,19200*22\r\n";
char baud4[] = "$PMTK251,38400*27\r\n";

//---NMEA protocols--------
char RMC[] = "$PGCMD,16,1,0,0,0,0*6B\r\n";
char VTG[] = "$PGCMD,16,0,1,0,0,0*6B\r\n";
char GSA[] = "$PGCMD,16,0,0,1,0,0*6B\r\n";
char GSV[] = "$PGCMD,16,0,0,0,1,0*6B\r\n";
char GGA[] = "$PGCMD,16,0,0,0,0,1*6B\r\n";
char BIN[] = "$PGCMD,16,0,0,0,0,0*6A\r\n";

void ini_gps() {
    gps.baud(38400);
    wait(0.1);
    pc.printf(BIN);
    pc.printf(hz1);
    gps.printf(BIN);
    wait(0.1);
    gps.printf(hz1);
    wait(0.1);
} 

void decode_gps(void) {
    
    char data;
    static int GPS_step=0;
    while (gps.readable() != 1); // wait for the first byte  
    for (int i=0; i<32 ;i++){  //read the next 32bytes (I know it)
         data = gps.getc();  
            switch(GPS_step){
                case 0:
                    if(data==0xB5){                       
                        msg[0]=data;
                        GPS_step++;
                        break;
                        }
                case 1:
                    if(data==0x62){
                        GPS_step++;                        
                        msg[1]=data;
                        }
                    else {
                        GPS_step=0;
                        }
                        break;
                case 2:
                    msg[2]=data;                                       
                    GPS_step++;
                    break;
                case 3:
                    msg[3]=data;                    
                    GPS_step++;
                    MTK_payload_counter=0;                    
                    break;
                case 4:
                   if (MTK_payload_counter<MTK_payload_length_hi) {                                               
                        MTK_payload_counter++;
                        msg[MTK_payload_counter+3]=data;
                    
                        if (MTK_payload_counter==MTK_payload_length_hi) {
                            GPS_step++;
                            }
                            }
                            
                        break;
                case 5:
                    msg[30]=data;                    
                    GPS_step++;
                    break;
                case 6:
                    msg[31]=data;                                                             
                    GPS_step=0;                    
                    break;
                }
           }
      
}
int main(){
    ini_gps();
    wait(0.1);
    pc.printf("comienzo programa\r\n");
    while(1){
    decode_gps();
    for(int i=0;i<32;i++){
    pc.printf("0x%X\n\r",msg[i]);
    }
    wait(0.4);
    }
 }
Here is the code that works, it would be usefull for someone with the Diydrones GPS

21 Sep 2010

Dear Mr.Jose

Great.

Thank you for your fixed codes and the messages. :)

Best regards

Shin.

22 Sep 2010

Hi !

I had lot of issues with too many printf on my program (datalogger who spend long time to decode serial data stream) and with the wait function into my decode serial routine or in my main loop !

Now i use a tinker to "stop" all process and give me debug informations with printf for example, with this approach i never have serial "getc()" stream decoding problem.

I will try the buffered serial class given by Shin asap too ;-), thank you Shin.

Regards,

Chris

30 Apr 2012

Hi Jose,

are you using the mediatek 3329 GPS receiver from diydrones?

Thanks, shahid

09 Dec 2016

12