Query on NMEA

Hi, I need to write a c code for calculating the distance detween two points on earth using GPS data. NMEA sentence from GPS receiver is GPRMC . The sentence is $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A It is given thro keyboard.(working on Turbo C Compiler).Code checks for $ and then put the characters in an array of size 100. After the last character,'\0'is assigned to terminate the character array. How to identify the end of sentence?(i/p comes from keyboard. scanf is used in code) Pls advice me what to do?

thank you,

sindhu

Reply to
sindhu
Loading thread data ...

Funny enough, my C experience is limited to embedded systems, where I never have to deal with keyboard input using scanf. But the documentation of TurboC should very well explain what to expect when you press enter. Further, if you are only interested in the position of the RMC sentence, why not rewrite the input routine and ask the user for the position only instead of parsing the entire RMC sentence.

Meindert

Reply to
Meindert Sprang

Not funny. How will u give the input in turbo-c? I need to write a code which has to take NMEA sentence as input and output lat,long. I need to check for the end of sentence.Pressing enter key has to return lat, long outputs. can anyone help me?

thanks

Reply to
sindhu

Do a continuous loop using getchar(). Process the incoming characters with a state machine. Sentence is complete when CR and LF is received. In your case, using keyboard, CR will terminate the sentence.

Then, parse the sentence.

Meindert

Reply to
Meindert Sprang

Sindhu, this is a situation where you should try to help yourself a bit more and then come back to the group with questions that show you've thought about the problem - it will make you stronger in the long run.

The advice about how scanf works is good and the documentation should point you to the answer. Look at the format of the string that the scanf generates and the characters it produces when you hit enter. A good debugger should let you examine the contents of the array.

Reply to
Tom Lucas

He's using a nmea multiplexer that types onto a keyboard?

Reply to
Bas-i

Its obviously a class assignment of some sort. Probably a requirement to use Scanf as I suspect the purpose is to demonstrate one's understanding of Scanf & Printf format specifiers.

Meindert's advice to use getchar and a state machine is the way to go for a real embedded system (unless its an embedded PC :-) ) as the library that contains Scanf, Printf etc. is usually really vast and will eat up your limited ROM space, however to pass the assignment you've got to keep the Prof happy.

If you are having problems with Scanf try using Sscanf (quoting from TurboC++ 1.0 for DOS help file):-

You'll need to read the characters into a character array as a string buffer, not forgetting to null terminate when enter is pressed then pass it to Sscanf for parseing. The trouble with Scanf is if your input doesn't match the format, Scanf goes back to get more input. Sscanf is 'polite' and stops at the end of the string.

If you are haveing problems with detecting your system's enter key, I suggest writing and running a short program to wait for a key then echo it in decimal, hex and as a character. For added conveniance write it to exit if the same (non null) key is pressed three times. You'll soon be able to see what character constant you need to define to match an Enter.

Using Sscanf instead of Scanf *shouldn't* loose you too many marks if you explain the problems you were having with Scanf. If you are lucky, you'll spot the bug in your format string and be able to revert to using Scanf for full marks.

Good Luck, I still remember how finding out how badly broken the compiler in the

1st year C lab was with a short deadline looming. (IIRC we had a really early version of Zortech C for DOS, and the problem was a very non K&R version of Scanf) Needless to say, later on I was very carefull *not* to get assigned a project that was based on one of the 80x86 development boxes.
--
Ian Malcolm.   London, ENGLAND.  (NEWSGROUP REPLY PREFERRED)
ianm[at]the[dash]malcolms[dot]freeserve[dot]co[dot]uk [at]=@, [dash]=- &
[dot]=.
*Warning* SPAM TRAP set in header, Use email address in sig. if you must.
Reply to
Ian Malcolm

LOL Not one of mine, I hope.....

Meindert

Reply to
Meindert Sprang

When you do parse, make sure that you catch and reject the dummy sentences that the GPS will return before acquiring enough satellites for a solution---things like

$GPMRS,,,,,,,0E/n

Also watch out for checking for CR/LF. Various OSs do strange things to that combination in the serial drivers. As noted, it is probably best to receive data character-by-by character and look for the line feed as the terminator.

My own GPS code looks for LF, then checks to see if '$' is the first character in the array. If it is, substitute a 0x00 for the LF (to make the array into a C string), and parse. Then reset the array index and start over.

Mark Borgerson

Reply to
Mark Borgerson

Don't use geek-speek. The 'u' and similar abbreviations are not acceptable here.

Two days ago I posted something under "query on c". Copy follows:

Subject: Re: query > "Tom Lucas" wrote:

... snip ...

You don't need any of that for a positive action, if you can drive an input state machine from an interrupt. The ISR should look roughly like:

/* totally untested */ void process(void) {

int ch; static enum state {startup, newch, awaitlf}; static char buf[MAXMSG]; static int ix; static time_t t, now; /* assumed in millisecs */

ch = getc(inputdevice); if ('$' == ch) state = startup; switch (state) { case startup: ix = 0; t = systemtime; if ('$' == ch) state = newch; break; case newch: if ('\n' == ch) state = awaitlf; else if (ix < MAXMSG-1) buf[ix++] = ch; else state = startup; /* overlong input, discard */ break; case awaitlf: if ('\r' == ch) { now = systemtime; if ((now - t) < TIMEOUT) { /* not too long */ buf[ix] = '\0'; /* terminate string */ ship(buf); /* to processing code, make copy */ } state = startup; break; default: state = startup; break; } /* switch */ return; /* from interrupt */ } /* process, untested */

Watch out for timer wrap-around.

You need to resolve the meaning of systemtime, inputdevice and ship(buf).

--
 "A man who is right every time is not likely to do very much."
                           -- Francis Crick, co-discover of DNA
 "There is nothing more amazing than stupidity in action."
                                             -- Thomas Matthews
Reply to
CBFalconer

And you will want proper interlocks on ship(buf) so that the buffer doesn't get overwritten in the middle of the main loop processing.

I avoid such issues by having a hardware fifo or DMA (as in the case of the ATMEL SAM controllers) and ISR to queue up the input. Then my main loop checks for available input and does the processing and parsing as data arrives.

That means that I don't have to rewrite and test the ISR for each new application that uses serial input. What's the word for that--- Oh, Yeah: Driver! ;-)

The preprocess-in-the-ISR approach does have some utility when there must be very low latency, but I doubt that's much of an issue with 1Hz NMEA messages sent at 4800Baud. The latency issue can become important if you are integrating the GPS data with other sensors that report asynchronously---as when using a GPS and inertial sensors for navigation calculations.

Mark Borgerson

Reply to
Mark Borgerson

If using a FIFO, you can help things along by having two push-pointers (pushA & pushB) for the FIFO, and just one pull-pointer. The output side of the FIFO (using the pull pointer) works normally, testing for empty with the pushB pointer. The input side works thus:

void Initialise() { PushA = pushB = 0; }

void Received_char(char input) { to_FIFO(input, &pushA); // Load using pushA if(end_of_message()) // Detected '\n', or whatever { if(message_looks_good()) // Whatever tests you like { PushB = PushA; // "Lock" the message into FIFO signal_to_processing_thread(); // If appropriate } else { PushA = PushB; // Delete bad message } } }

This way, the processing thread only ever wakes up when there is known to be a complete message in the FIFO.

Reply to
David R Brooks

Same with my interrupt code.

--
 "A man who is right every time is not likely to do very much."
                           -- Francis Crick, co-discover of DNA
 "There is nothing more amazing than stupidity in action."
                                             -- Thomas Matthews
Reply to
CBFalconer

I guess that would work if done properly and the user had an OS that handled message queues efficiently (hopefully not using malloc() and free() ). However, using a generic interrupt- driven serial driver solves the timeout problem also----no input and the driver tells you no data is available. The processing state machine exits as soon as it finds no new input is available.

Mark Borgerson

Reply to
Mark Borgerson

I was really referring to a hardware FIFO on the serial port UART. You are also assuming a bit more OS than I usually get to work with. I guess that's a result of gradually working my way up from an M6802 with a 2K EPROM! ;-) I've got uCOS and FreeRTOS and hardware that will run them (AT91SAM7S256), but nobody has yet offered to pay me to learn them and incorporate them into they systems I'm working on now---so they remain free-time-available projects. One customer jumped straight to LINUX for a hard real-time system, and I'm still working on straightening that out! ;-(

Mark Borgerson

Reply to
Mark Borgerson

It's interesting/amusing to see a thread that started as an obvious query from a very lazy student who has absolutely no interest in engineering (aside from passing his/her course) evolve into a discussion between professional engineers that the OP has no chance of (probably ever) understanding... ;)

Regards,

--
Mark McDougall, Engineer
Virtual Logic Pty Ltd, 
21-25 King St, Rockdale, 2216
Ph: +612-9599-3255 Fax: +612-9599-3266
Reply to
Mark McDougall

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.