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 CCS Technical Support

problem with pic18f4550 in mathematics {solved}
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
eng.alamin



Joined: 08 Sep 2008
Posts: 17

View user's profile Send private message

problem with pic18f4550 in mathematics {solved}
PostPosted: Mon Sep 08, 2008 11:59 am     Reply with quote

hello
I am trying to develop gps data logger.
So i have to receive data serially from gps module and store longitude and latitude each in Double variables to allow me to make mathematical operators.

GPS module transmit this package
($GPGLL,2447.2073,N,12100.5022.E)

What i want to do is load
Double lon = 2447.2073 ;
and
Double lat = 12100.5022 ;

But i felt to catch these two variables direct from rs232 receiving pin.

So i did some magic and load all data in array.

int buffer[31] ;

By this code all incoming serial data will store in buffers array.


Code:

for (x = 0 ; x ==31 ; x++)
{
buffer[x] = getc() ;

}


Then i found that buffer array is content the ASCII code of incoming data :(

So i did some trick to convert ASCII code to correct integers
by using switch.
Code:

for(x = 0 ; x ==31 ; x++)
{
switch(buffer[x])

case 48 : buffer[x] == 0 ;

break;
...
...
...

case 57 : buffer[x] == 9 ;

break;

}



and finally to load data in lon and lat variable in correct way i did this
Code:
lon = buffer[7]* 1000  + buffer[8]*100  + buffer[9]*10 + buffer[10]


The outcome
Code:

printf("%f", lon)



It suppose to be = 2447

But its came weird strange number :(

But when i check buffers they are all right all contents of corrects integer.

Please tell me what is problem.

regards


Last edited by eng.alamin on Wed Sep 10, 2008 5:39 am; edited 1 time in total
meereck



Joined: 09 Nov 2006
Posts: 173

View user's profile Send private message

PostPosted: Mon Sep 08, 2008 12:51 pm     Reply with quote

what about using function atoi()

however your for loop is wrong:
for (x = 0 ; x ==31 ; x++)
it should be:
for (x = 0 ; x <31 ; x++)

you also dont need switch()
just subtract the value of 48 (which is 0x30 in hex) from the character
e.g. buffer[i]-=0x30
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Mon Sep 08, 2008 12:54 pm     Reply with quote

Our brains only comprehend numbers through notation. For example lat = 12100.5022 is 121 degrees in base 180 notation 00 minutes in base 60 notation and .5022 fractions of a minute in base 10 decimal notation. The digits are further encoded in ascii. Now to put a mixed base into PIC internal binary floating point notation requires an idea of the precision that may be lost in changing notations. PIC Floating point binary is exact in terms of base two mathematics. However, it is only able to contain certain values of decimal notated numbers exactly ( this is not an error just a fact of mathematics). Further due to finite 4 byte storage truncation will also occur. This truncation will occur at about 6 to 7 decimal digits but even 0.1 will never be able to be represented in binary notation exactly. 12100.5022 has nine digits neglecting the mixed bases in its representation of navigational position so serious truncation must occur often.
Suggestion:
Bring the number into binary integer notation. An byte integer for degrees and a byte integer for minutes and a two byte integer for fractions of a minute. These internal binary integers will be exact. Converting from ascii encoding to binary values can take advantage of the fact that digits 0 to 9 are ascii values 48 to 57
so binval=asciival-48 can be an alternative to a messy case statement.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Sep 08, 2008 1:11 pm     Reply with quote

There are many previous posts on this topic, with lots of sample code.
Do a search for:
Quote:
GPS atof

Set it to: "Search for all words"

or do a search for:
Quote:
NMEA


Link to the forum's search page:
http://www.ccsinfo.com/forum/search.php
Guest








PostPosted: Mon Sep 08, 2008 3:26 pm     Reply with quote

meereck wrote:
what about using function atoi()

however your for loop is wrong:
for (x = 0 ; x ==31 ; x++)
it should be:
for (x = 0 ; x <31 ; x++)

you also dont need switch()
just subtract the value of 48 (which is 0x30 in hex) from the character
e.g. buffer[i]-=0x30


atoi is not working .

ya it's wrong i guess i used (=<) .

thanks for this method (buffer[i]-=0x30) i'll use it .

by the way my problem is not load incoming data into buffers

i load it successfully and i chick it , each number is in correct buffer

to load digits from buffers to (lat) which is double variable
i used this method

example: 2447 = ( 2 * 100) +( 4 * 100) + (4 * 10) + 7

this type of operation never done successful by pic c and pic18f4550

but when i used pic16f877a it worked perfect.

most of exampls expane how to read gps data and display it wither on lcd or to pc but i have to load longitude and latitude into double variable to do some mathematical calculation (distance - pearing .... etc )
Guest








PostPosted: Mon Sep 08, 2008 3:42 pm     Reply with quote

Douglas Kennedy wrote:
Our brains only comprehend numbers through notation. For example lat = 12100.5022 is 121 degrees in base 180 notation 00 minutes in base 60 notation and .5022 fractions of a minute in base 10 decimal notation. The digits are further encoded in ascii. Now to put a mixed base into PIC internal binary floating point notation requires an idea of the precision that may be lost in changing notations. PIC Floating point binary is exact in terms of base two mathematics. However, it is only able to contain certain values of decimal notated numbers exactly ( this is not an error just a fact of mathematics). Further due to finite 4 byte storage truncation will also occur. This truncation will occur at about 6 to 7 decimal digits but even 0.1 will never be able to be represented in binary notation exactly. 12100.5022 has nine digits neglecting the mixed bases in its representation of navigational position so serious truncation must occur often.
Suggestion:
Bring the number into binary integer notation. An byte integer for degrees and a byte integer for minutes and a two byte integer for fractions of a minute. These internal binary integers will be exact. Converting from ascii encoding to binary values can take advantage of the fact that digits 0 to 9 are ascii values 48 to 57
so binval=asciival-48 can be an alternative to a messy case statement.


what is killing me this .. look at this operation:

if Y is defined as integer

int y ;

y = 2 * 1000 + 4 * 100 + 4 * 10 ;

printf("%U", y) ;

answer will be 2440 and it's a correct answer


but if Y is defined as Double

double y ;

the outcome is really weird -784




Question
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Sep 08, 2008 3:54 pm     Reply with quote

Quote:
if Y is defined as integer

int y ;

y = 2 * 1000 + 4 * 100 + 4 * 10 ;

printf("%U", y) ;

answer will be 2440 and it's a correct answer

Not true. Not in CCS. In CCS, an 'int' is an 8-bit unsigned integer.
Your program above will compile and execute, but it gives me a
result of 13. I don't think you are really running the code listed above.

To actually get 2440, you need to declare 'y' as 'int16'. Also, to display
an int16 value with printf, you need to use "%LU". Note the 'L'.
Guest








PostPosted: Mon Sep 08, 2008 4:03 pm     Reply with quote

PCM programmer wrote:
Quote:
if Y is defined as integer

int y ;

y = 2 * 1000 + 4 * 100 + 4 * 10 ;

printf("%U", y) ;

answer will be 2440 and it's a correct answer

Not true. Not in CCS. In CCS, an 'int' is an 8-bit unsigned integer.
Your program above will compile and execute, but it gives me a
result of 13. I don't think you are really running the code listed above.

To actually get 2440, you need to declare 'y' as 'int16'. Also, to display
an int16 value with printf, you need to use "%LU". Note the 'L'.


Very Happy ya ya your right

what i ment is y = 2 * 100 + 4 * 10 + 4 ;

result is 244


also iused %f when ichange (y ) from int to duoble

sorry for that

regards
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Sep 08, 2008 4:37 pm     Reply with quote

Is it working now, or do you still have a problem ?
Guest








PostPosted: Mon Sep 08, 2008 4:54 pm     Reply with quote

Shocked

it works in case of y is int only

but it never work when y is double

i still don't know why

if you have any idea to load longitude and latitude as double
please help me !
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Sep 08, 2008 4:58 pm     Reply with quote

When you have a problem, you need to post a small but complete test
program that demonstrates the problem. Example:

The program below uses your code, and uses %f as you said.
This was tested with vs. 4.069 in the MPLAB simulator.
It displays the following output:
Quote:
244.00


Code:
#include <18F4550.h>
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

//===============================
void main()
{
double y;

y = 2 * 100 + 4 * 10 + 4;

printf("%f \n\r", y);
   
while(1);
}
eng.alamin



Joined: 08 Sep 2008
Posts: 17

View user's profile Send private message

PostPosted: Mon Sep 08, 2008 5:37 pm     Reply with quote

this is my code iused Proteus simulator


Code:
#include <18f4550.h>
#include <stdlib.h>
#include <MATH.H>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=12000000)
#use rs232(baud=4800, xmit=PIN_b4,rcv=PIN_b0,stream=GPS)

void main()
{

   int string[31];
   int buff[8] ;
   byte sync;
   double lon  ;
   double lat  ;
   char value1;
   char value;
   int x ;
   float des ;
amin:
lon = 0 ;
lat = 0 ;




    while(TRUE) {


loop :

  sync =  getc()  ;
  if (sync == '$' )

  {
    for (x = 1 ; x <= 6 ; x++)
{
     string[x] =  getc()  ;
}}else{goto loop ;}

if ( string[3]  == 'G' && string[4]  == 76 && string[5]  == 76  )
{
    for (x = 7 ; x <= 30 ; x++)
{
     string[x] =  getc()  ;
}

}

else {goto loop ; }
 for(x = 7 ; x <= 30 ; x ++)
 {
 switch(string[x])
 {

   case 48 :  string[x] = 0;

      break;

   case 49 :   string[x] = 1 ;

      break;

   case 50 : string[x] = 2;

      break;
   case 51 : string[x] = 3;

      break;
      case 52 : string[x] = 4;

      break;
      case 53 : string[x] = 5;

      break;
   case 54 :  string[x] = 6;

      break;



   case 55 :   string[x] = 7 ;

      break;

   case 56 : string[x] = 8;

      break;
   case 57 : string[x] = 9;


      break;




       }

 }
//strcpy(string,"123456789");

//lat = atod(string);


lat = (string[7] * 1000 )+  (string[8] *100) + (string[9] * 10) + (string[10] )+(string[12] *0.1) +(string[13] * 0.01) +(string[14] * 0.001)+(string[15] * 0.0001) ;

lon= (string[19] *10000) +(string[20] *1000) + (string[21] * 100)  + (string[22] *10) +(string[23] )+(string[25] *0.1) +(string[26] * 0.01) +(string[27] * 0.001)+(string[28] * 0.0001) ;


       printf("%f  %C  %f  %C   ", lon ,string[30], lat , string[17]  );

   }






goto amin; }


am using pcw c compiler
idid some quick modification and ididn't compile it you may find some erorr

anyway please tell me what is wrong with it
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Sep 08, 2008 5:46 pm     Reply with quote

I confess that I don't want to look at it. Reasons:
1. It has goto's in it.
2. It has a switch-case statement to convert ascii to binary integers.
The code is over 20 lines. It could be replaced by 1 line.

Why not just tell us what your purpose is ?
Show the input ASCII, and show the desired output.

I suspect that you are simply trying to parse an incoming NMEA-0183
stream from a GPS. There is tons of sample code on the forum to do that.
eng.alamin



Joined: 08 Sep 2008
Posts: 17

View user's profile Send private message

PostPosted: Mon Sep 08, 2008 6:15 pm     Reply with quote

will thanks for your words i guess it's hard to learn something this days without get some humiliation .
i just moved from picbasic pro to pic c without any proper education
that why i have those stupid mistake.

any way i saw these (( tons of example )) they all about get data from GPS module and display it or send it

what i need is get data from gps and store longitude and latitude in (variables ) type (double)

i used printf just to be able to see what is store in (lon , lat ) variable

that's all
if you can make it in one line it will be cool
-----------------------
this is the input
$GPGLL,2447.2073,N,12100.5022,E,104548.04,A,A*65

no output need

just store
lon = 2447.2073,
lat = 12100.5022,

lon and lat are double

-------------------
ckielstra



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

View user's profile Send private message

PostPosted: Mon Sep 08, 2008 6:39 pm     Reply with quote

eng.alamin wrote:
if you can make it in one line it will be cool

eng.alamin wrote:
thanks for this method (buffer[i]-=0x30) i'll use it .
You didn't use it or the switch statement would have been replaced by one line... Cool
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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