CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Problem when getting data from GPS

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Kimi



Joined: 30 Jan 2005
Posts: 23
Location: Argentina

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger

Problem when getting data from GPS
PostPosted: Sun Jan 30, 2005 5:01 am     Reply with quote

Hello

I'm trying to get data from a SIRF GPS module, it outputs data at 4800bps. I have connected a Logic inverted between the GPS module and the PIC Hardware UART (STREAM = GPS), so I can use the Hardware port. Then, I configured another pin (STREAM = PC) so I can resend what the PIC Received.
The problem are basically two. With Code "A", the program gets halted or received a few bytes and halts. With Code "B", the program pass "succesfully" the part where receives GPS's Data, but make a mess with a printf instruction.

--- BOTH HAVE THE SAME DEFINITIONS
#include <16F877.h>
#device *=16
#use delay(clock=16000000)
#fuses NOWDT,HS, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=GPS,errors)
#use rs232(baud=9600,parity=N,xmit=PIN_D1,rcv=PIN_D2,bits=8,stream=PC,errors)


---- CODE A -------------
char c;

void main() {

setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
while(1) {
c = fgetc(GPS);
fprintf (PC,"%C",c);
}
while(1);
}

--------------- CODE B ----------------------------------------
char c;
char gps_packet[30];
unsigned int8 i;

void main() {
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
i = 0;
for (i = 0; i = 10; i++){
c = fgetc(GPS);
gps_packet[i] = c;
}
for (i = 0; i = 10; i++){
fprintf(PC,"%C",gps_packet[i]); // the problem is here
}
while(1);
}
in Code B the program starts printing 0x00 and 0x20 in the terminal window, and doesn't stop! it prints that characters for EVER!!!

I believe tha GPS sends too much data and also too fast. I tried implementing kbhit(GPS) but I don't remember if the program got halted, or if it was another error... I just want to receive "$GPRMC" from the GPS... only that... Also tried with ProtonPlus and PicBasic Pro without success...

Compiler Version 3.206

Please... help me...
Thanks
Kimi
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Jan 30, 2005 5:54 am     Reply with quote

Your Code A looks fine to me, I don't see why it should stop after receiving a few bytes. Are you sure your terminal program on the pc is working fine? Especially Hyperterm is terrible in my experience...

In your Code B, change the two lines:
Code:
 for (i = 0; i = 10; i++){
to
Code:
 for (i = 0; i <= 10; i++){
Kimi



Joined: 30 Jan 2005
Posts: 23
Location: Argentina

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger

PostPosted: Sun Jan 30, 2005 6:12 am     Reply with quote

Really it's not hyperterm but the built in Serial Port monitor that the CCS compiler has.
May the difference is the For statement be a problem? I don't think so...
The GPS sends information each one second (sends packet, wait 1 sec, sends packet...and so on) ... How would you implement a rutine that only receives bytes if before that a pin was in the same state for 500mS?

The procedure will be like this.

1)wait for the RX pin of the UART to be in idle state for 500ms
2)implement kbhit properly, so I don't miss the first start bit
3)receive at list a few bytes

If I can catch the first start bit of the first byte correctly, I think I will solve all my problems...

-- I think Code A stops because when the PIC send data to the PC, misses some start bits, or something like that. ---

Thanks
Kimi
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Jan 30, 2005 6:46 am     Reply with quote

Quote:
May the difference is the For statement be a problem? I don't think so...
Your version is not working and will never work. I'm sure that difference is a problem...
Kimi



Joined: 30 Jan 2005
Posts: 23
Location: Argentina

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger

PostPosted: Sun Jan 30, 2005 6:51 am     Reply with quote

Thanks... Now I understand the problem...

What about the other question I made? Is it possible to make that little rutine? Do you have in mind a good method to do that ckeck of the pin state?

Thanks very much

Kimi
libor



Joined: 14 Dec 2004
Posts: 288
Location: Hungary

View user's profile Send private message

PostPosted: Sun Jan 30, 2005 7:36 am     Reply with quote

I don't know what is the application you want in the end. But even if you succed in tuning your sample code not to miss bytes, etc, you will certainly run into troubles when you want other things to do in your program (like some kind of a user interface, remote reporting, journaling)
You can't wait for a serial port in your main() and not do other things in the meantime.
Later, after these testings, I suggest you to use interrupts (I mean learn using them) that place the arriving characters into a buffer (a whole NMEA sentence should fit into the buffer) or it would be even more useful to extract the needed infomation (coordinates) from the sentence on-the-fly in the interrupt service routine and place only these values in to the corresponding variables.
Using interrups to serve the serial ports you will have the freedom of doing other things in your program without timing worries.
Kimi



Joined: 30 Jan 2005
Posts: 23
Location: Argentina

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger

PostPosted: Sun Jan 30, 2005 7:42 am     Reply with quote

hello libor

I only need to get the Info from the GPS once each 5sec or more... so I have plenty of time to do other things... I only need to receive the $GPRMC data in the whole NMEA protocol... that's why in a part of the program, it will be usefull to wait for the packet to arrive, process the information, and continue doing other things, without the need of an interrupt. But as this is the begining, I only want to receive the packet, and show it on the PC each 5 seconds, of course, without using interrups...

Do you have any idea? what about the suggestion I made to wait for 500ms of idle state on the RX pin? How will you implement something like this?

Thanks very much
Kimi
libor



Joined: 14 Dec 2004
Posts: 288
Location: Hungary

View user's profile Send private message

PostPosted: Sun Jan 30, 2005 8:01 am     Reply with quote

You can check the RX pin's state (data coming from the GPS) continuously for 500ms (= 5000 x 100us), resetting your timing counter if any data bit arrived during this time.
If is enough if you look at the pin every 100us, to certainly not miss a bit of 208us length (at 4800bps)
(this code waits until 500ms of continuous silence is on your RX line, if you have inverted signal, you should omit the ! in the if()

Code:
long cnt;
for (cnt=0; cnt<5000; cnt++) {
    delay_us(100);
    if (!PIN_C7) cnt = 0;
}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Jan 30, 2005 8:18 am     Reply with quote

Kimi,
Both your example programs are good starting points. The fact that they don't work (after the small fix to example B) indicates to me that there is some kind of hardware problem. My suggestion is to continue with example A and get this working before continuing and making your program 'smarter' by only waiting for the coordinate data.

Lot's of people have used the CCS routines for RS-232 communications on a PIC16F877, it seems strange to me that these routines would fail in your application. Again, have an extra look at your hardware. You inserted an hardware inverter... Are you sure this one is required? Is it just a logic lever inverter or is it a true rs-232 converter like the MAX232?

The only info I can find about SIRF is that they are producing GPS chips, not complete modules except for an evalutaion kit. Without more details about the module you are using it's hard to help you with the hardware aspects.
Kimi



Joined: 30 Jan 2005
Posts: 23
Location: Argentina

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger

PostPosted: Sun Jan 30, 2005 8:49 am     Reply with quote

Hello

Thanks to both of you.
I will continue testing the program tomorrow, now I have to rest a bit. The SIRF module, is only a board with a GPS chip, it doesn't have screen or a GUI Interfase. It output data at 4800bps and needs a MAX232 to connect to the PC. As the data that comes out is TTL, and I use the Hardware Port of the PIC, I put a TTL logic inverter between the GPS and the PIC, because the HUART doesn't support inverted mode.
I believe that code A has the problem that, when it's sending data to PC, it miss data from the GPS, and perhaps it miss start bits of the incoming bytes, which result in a halt in the program.
Program B should be more stable to this matter, I will try tomorrow the modification of the FOR statement, really... don't know how I skip that.
Where can I get a DETAIL explanation of what KBHIT and GETC do, and how they work?
Is the ERRORS statement in the USE RS232 for the HUART requeried? What will improve with it?
Thanks
Kimi
GDetienne



Joined: 20 Sep 2003
Posts: 47
Location: Brussel - Belgium

View user's profile Send private message

PostPosted: Sun Jan 30, 2005 12:31 pm     Reply with quote

hello,

here some ideas to solve your problems.
- SIRF and NMEA are differents protocoles, be carrefull,
- the output is TTL and inverter is not necessary,
- most GPS send six sentences each second. The best solution is to stop the sending of the five unnecessaries sentences.
- when you receive only the good sentence, wait till you receive the character $ (it's the beginning), you put all received characters in a buffer, the last character is (I thing) one CR (13).

This work great with 16F876.

Detienne Guy.
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Sun Jan 30, 2005 8:08 pm     Reply with quote

I suspect the GPS will speak every second or so regardless of the state of the PIC (assuming the pic doesn't command the GPS to talk on demand)
If this is true ( asynchronous ) then the whole program must be centered around the ability to accept a gps sentence immediately as it is spoken char by char.
You need a circular buffer for the GPS transmission. When a char is received from the GPS it should trigger an interrupt routine that will stuff it into the circular buffer. The main code can then read the buffer do printf or whatever else it takes knowing that it can never prevent a char from being received. As long as the main code reads out the sentence within a sec the circular buffer should never overwrite any unread data.

When your code was busy doing printf data was coming from the GPS
and overflowed the 3 char deep hardware buffer of the PIC.

here is a snippet buff[] can be as small as two sentences in length

Code:
//globals
char buff[256]; ///// assumes in8 roll over at 255
int8 next_ptr; //// next available byte in the circular buffer
int8 read_ptr;
int8 free_space;
int8  sentence_count;
#int_rda
void gps_isr()
{
char c;

/// note this routine needs to as short as possible since it is called
/// for each char received from GPS
/// the routine places NMEA sentences into the buffer and inc sentence count
/// a sentence begins with $GP and ends /n/r

c=getc() ; // get data from RCREG hardware clears RCIF



buff[next_ptr++]=c;// rolls over at 255 circular  buffer
free_space--;
if(free_space==0)
   {
    puts("full buffer");
   }




}


int8 buff_getc()
// used instead of getc to read chars from the circular buffer
{
int8 c;
while( free_space==255); /// wait for data in buffer
 c=buff[read_ptr++];// circular  buffer rolls over at 255
 free_space++;
 if ( free_space==0)
    {
     puts("exceeded buffsize");
    }


return(c);
}
int8 get_nmea (char *cmd,int8 *res_buff)
{
int8 i,match,c;
//// a response  Ex  is $GPSGLL,  and ends with *CC CR LF
////

match=0;
while ( match<8)

       {
// ex match $GPSGLL 7 chars
//               cmd="GLL"
         c=buff_getc();
         if (c==',' && match==7) match=8;
         if (c==cmd[2] && match==6) match=7;
         if (c==cmd[1] && match==5) match=6;
         if (c==cmd[0] && match==4) match=5;

         if (c=='s' && match==3) match=4;
         if (c=='P' && match==2) match=3;
         if (c=='G' && match==1) match=2;
         if (c=='$' && match==0) match=1;

       }
match=0;
i=0;

     do {

         // we have data
         c=buff_getc();
         if (c>=32 && c<127) res_buff[i++]=c;



       }while (c!='*');
       res_buff[i]=0;

match=0;
  while ( match<2)

       {
//  look for CR LF terminator
         c=buff_getc();


         if (c=='\n' && match==1) match=2;
         if (c=='\r' && match==0) match=1;

       }


return (i);
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group