PDA

View Full Version : Converting Knots to MPH with ascii numbers



Rob Martin
- 20th March 2004, 10:34
I'm working on a project where I'm reading data from a gps.
Here's my problem, the GPS Knots string changes in length

When stationary it reads e.g. ,0.0,
When the slightest movement e.g. ,2.28,
With more movent ,38.71,
More ,78.97,
Breaking the speed limit ,100.73,

I tried using DEC to grab the numbers but this didn't work reliably
So I used STR and looked for the , before and , after the string which works well. But when trying to convert the string from Knots to MPH (x 1.15) here I hit my problem.
As the string varies in length the Knots 100x 10x 1x etc move around in the Knots[6]
eg.
0.0????
0.11???
11.11?
111.11


And lastly once converted i need to be able to read the MPH out one chr at a time to write to screen. And i'm only looking the whole MPH nothing after to .


Any pointers are welcome.

Rob





A few example strings below


$GPRMC,201639.219,A,5124.2293,N,00029.3233,E,0.0,0 00.0,020304,,*01
$GPRMC,201651.219,A,5124.2280,N,00029.3227,E,2.28, 291.1,020304,,*3B
$GPRMC,201854.211,A,5124.5346,N,00029.7814,E,38.71 ,079.8,020304,,*02
$GPRMC,201948.207,A,5124.6416,N,00029.1546,E,78.97 ,279.9,020304,,*0B
$GPRMC,202200.199,A,5124.6983,N,00030.1561,E,100.7 3,080.1,020304,,*3F

KNOTS[6]

SERIN2 PORTb.1,188,1000,NoData,[WAIT("$GPRMC,"),dec2 HH,DEC2 MM, dec2 ss,_
skip 5,Lock,_ 'Looks for V or A
wait(","),dec2 latA,Dec2 LatB,_ 'Looks for Lat 2 digits
wait("."),DEC2 LatmsA,DEC2 LatmsB,_
wait(","),NS,_
wait(","),LonA,Dec2 LonB,dec2 Lonc,_
wait("."),DEC2 LonMSA,DEC2 LonMSB,_
wait(","),EW,_
wait(","), str Knots\6\",",str head\5\",",dec2 d,dec2 m,dec2 y]

Melanie
- 20th March 2004, 19:44
When reading the numbers in, zero a Byte variable when the decimal point is encountered. Let's call this byte variable our Multiplyer. Then when each subsequent number is encountered (until the next comma), increment the multiplyer.

Now, knowing how many decimal points you're playing with. You can then construct a word integer variable to do your math with knowing exactly where you stand. So using your last example, you can have an integer loaded with 10073, with the Multiplyer standing at 2, you know there are two decimal places.

You can then multiply 10073 by 115 and use DIV32 to divide by 100 and extract your answer. The Multiplyer byte will still indicate where to drop-in your decimal place when displaying, outputting or otherwise processing your final answer.

Naturally you can't spill out of your word variable, but with two decimal places you can go to 569.86 knots (which equates to 655.33 mph by your calculation and PBP's integer math limitations) and should be enough for the majority of applications).

Melanie

Rob Martin
- 21st March 2004, 08:16
Melanie
I can understand what you are saying but not sure is will help.

My knots[6] for 100.73 would by $31,$30,$30,$2E,$37,$33

So how do I get this lot into one WORD then do my maths then back to Ascii again? I know I can -$30 to get it close but how do i get it all in to one WORD.

once I've done that is there a way to convert 10075 = $2759 back to 10075 as individual bytes?

Hope that makes sense.


Rob

Melanie
- 21st March 2004, 11:35
Just think about what you need to accomplish in each step as I have outlined in my previous reply. There are probably more elegant ways of doing this but I've thrown this together in the short time available to me today (I have kept comments to a minimum so you can work-out what I’m doing in each section)...

Lets break the job down into steps...

We start with Knots array holding an ASCII numeric string with a Decimal place somewhere within it.

CounterA var Byte
DataA var Word
DataB var Word
Knots var Byte [6]
KnotsW var Word
Multiplyer var Byte
MPH var byte [6]
MPHW var Word

'
' Step 1
' This section loads the Word variable KnotsW
' from the ASCII String variable Knots
' and ensures there are ALWAYS 2 decimal places
' regardless where the decimal place is in the string.
' Any more than 2 decimal places are truncated.
' Any less than 2 decimal places are multiplied up.
'
KnotsW=0
Multiplyer=$FF
For CounterA=0 to 5
If Knots(CounterA)=$2E then
Multiplyer=0
Else
If Multiplyer<2 then
KnotsW=(KnotsW*10)+Knots(CounterA)-48
If Multiplyer<5 then Multiplyer=Multiplyer+1
Endif
Endif
Next CounterA
If Multiplyer=$FF then Multiplyer=0
DecimalAdjust:
If Multiplyer<2 then
KnotsW=KnotsW*10
Multiplyer=Mutiplyer+1
Goto DecimalAdjust
endif
'
' Step 2
' This next section converts to MPH
' The resultant is an Integer called MPHW
'
DataA=115
DataB=KnotsW*DataA
MPHW=DIV32 100
'
' Step 3
' Finally you want individual ASCII Bytes
' So we'll load our result MPHW into the array MPH
' and Right-justify with Leading Zero Suppression
'
MPH[0]=MPHW DIG 4
MPH[1]=MPHW DIG 3
MPH[2]=MPHW DIG 2
MPH[4]=MPHW DIG 1
MPH[5]=MPHW DIG 0
DataA=0
For CounterA=0 to 5
If CounterA=3 then
MPH[3]=$2E
Else
If CounterA=2 then DataA=1
If MPH[CounterA]=0 then
If DataA=0 then
MPH[CounterA]=$20
Else
MPH[CounterA]=MPH[CounterA]+48
DataA=1
Endif
Endif
Endif
Next CounterA

At the end we have Miles Per Hour ALWAYS with 2 decimal places. If you want variable decimal places, then remove the DecimalAdjust section, and use the Multiplyer variable accordingly when loading your MPH array.

Now it wasn’t that difficult to break-down into steps was it?

I've not tested this code, but I'm sure you will once you've worked out the logic.

Melanie

mikep
- 21st March 2004, 12:29
I use this little routine

' Get the value of a numeric field
' The size of the field cannot pass a word
GetNumField:
tempbyte=1 ' Used for field position of GPS Data
factor = 1 ' Used to retun the factor that we multiplied the value
FOR i = 0 to MAXDATA
IF gpsdata[i] = "," THEN
tempbyte = tempbyte + 1
ENDIF

IF tempbyte = field THEN
' isolate the value here
tempword=0
tempbyte=1
WHILE i < MAXDATA
i = i + 1
IF gpsdata[i] = "," OR gpsdata[i] = "*" THEN
RETURN
ENDIF
IF gpsdata[i] = "." THEN
factor = factor * 10
ELSE
tempword = tempword * 10
tempword = tempword + (gpsdata[i] - 48)
ENDIF
WEND
RETURN
ENDIF
NEXT i
gpsvalid = 0
RETURN


You can see all of it at:

http://cvs.sourceforge.net/viewcvs.py/rcpilot/rcap/src/main.bas?rev=1.2&view=markup

It also does the checksums etc.

This was a way to actually not need to know the exact format of the data since it changes on different models of GPS.

I've seen many GPS reading routines in PBP and almost all of them would break if you ever used a different GPS. Also none of them ever checked the checksum.


Mike

Rob Martin
- 22nd March 2004, 09:54
Thanks Melanie & Mike
I give both ways a try when I get home later today.


Rob