String Parsing/Converting
Dear all
I am using the GPS_IO_MINI to extract data from the NMEA information from my GPS. I need to use the velocity and GPS fix quality as numbers. A first attempt failed after which it occured to me that they were probably extracted as strings. First question - is that right?
If they are strings, I need to convert them into decimals. One is an integer (quality), the other is not (velocity). In practice I only need the integer part of the velocity though. Looking around I have found lots of objects that can turn strings into decimals but (newbie alert) they all "return a pointer" and I don't know how to use them. So the second question is where can I find a gentle walkthrough description of using methods that "return a pointer"? If you assume that I have no more programming knowledge than the average Cocker Spaniel you will have the level just right!
Oh and I also need some advice on just getting the integer part of the velocity out of the string!
Time for breakfast.
Regards from rainy England
Richard
I am using the GPS_IO_MINI to extract data from the NMEA information from my GPS. I need to use the velocity and GPS fix quality as numbers. A first attempt failed after which it occured to me that they were probably extracted as strings. First question - is that right?
If they are strings, I need to convert them into decimals. One is an integer (quality), the other is not (velocity). In practice I only need the integer part of the velocity though. Looking around I have found lots of objects that can turn strings into decimals but (newbie alert) they all "return a pointer" and I don't know how to use them. So the second question is where can I find a gentle walkthrough description of using methods that "return a pointer"? If you assume that I have no more programming knowledge than the average Cocker Spaniel you will have the level just right!
Oh and I also need some advice on just getting the integer part of the velocity out of the string!
Time for breakfast.
Regards from rainy England
Richard

Comments
value := numbers.FromStr(gps.speed, numbers#DEC)
This returns nothing at all so I am still puzzled.
Regards
Richard
As I mentioned, I'm new to this...
Regards
Richard
Next would be to check serial.hex(gps.speed, 8), if that value is NULL then it's not available, otherwise (not equal NULL) what does serial.str(gps.speed) report?
repeat waitcnt(clkfreq + cnt) if temp := gps.speed serial.str(temp) else serial.str(string("not available", 13))!5315.80N/00208.80W-0.00 Knots A
I used the numbers object and then added 120 to the "speed" and "333" to the valid, this gave:
<0x06>5<0xfa><0x80>F Knots 0N/
where <0x06>5<0xfa><0x80>F is the speed and;
0N/ is the valid.
I am debugging over an APRS network and clearly it can't interpret these values as decimal numbers so something's wrong!
Regards
Richard
CON _clkmode = XTAL1|PLL16X _xinfreq = 5_000_000 OBJ fds[2] : "FullDuplexSerial" GPS : "GPS_IO_mini" n : "Numbers" VAR long stack[32] Pub GPS_Time | value, valid, s_addr cognew(helper, @stack{0}) ' fake GPS emitter GPS.start(1, 9600) fds{0}.start(31, 30, %0000, 115200) repeat if valid := GPS.valid ' get valid state fds{0}.str(valid) ' valid fds{0}.tx(32) else fds{0}.str(string("- ")) ' not valid if s_addr := GPS.speed fds{0}.str(s_addr) ' print as string fds{0}.tx(32) value := n.FromStr(s_addr, n#DEC) ' convert to decimal fds{0}.dec(value) ' print as decimal fds{0}.tx(13) else fds{0}.str(string("not available", 13)) waitcnt(clkfreq + cnt) PRI helper fds[1].start(2, 1, %0000, 9600) repeat waitcnt(clkfreq*3 + cnt) fds[1].str(string("$GPRMC,081836,A,3751.6565,S,14507.3654,E,[COLOR="red"]010.0[/COLOR],360.0,130998,011.3,E*62", 13)) DATWith the code above I send a fake GPS string every 3 seconds and get this output: Note that GPS.speed returns an address to a string. This string must not be manipulated in any way. After convertion you'll get a single long value which is all yours.Regards
Richard
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 out = 1 'useful definitions in = 0 on = 1 off = 0 'AX25 Modem Definitions XMTPIN = 27 PTTPIN = 25 TX_LVL = 10 'LED PORT LED = 22 'GPS Config GPS_RX = 23 'NMEA data sent to this port from GPS GPS_Baud = 9_600 'Default for most GPS modules OBJ mdm : "ax25" 'generates AX25 packet gps : "GPS_IO_mini" 'Extracts data from GPS NMEA string Num : "Numbers" 'Used to convert strings into decimals Debug : "Debug_LCD" VAR byte packet[255] byte packetcount LONG TX_DELAY 'used for timing Long valid_dec, speed_dec, speed_addr, valid_addr 'used in string to dec routine PUB main Debug.init(0, 9_600, 4) 'Pin 0, 9_600 baud, 4 lines Debug.backlight (true) Debug. dira~~ 'sets all pins to outputs - this help avoid problems with RF dira[GPS_RX] := in 'GPS Port set to input mdm.start_simple(mdm#NONE, XMTPIN, PTTPIN, TX_LVL) 'Start AX25 gps.start(GPS_Rx, GPS_Baud) 'Start GPS Repeat 5 'Boot indicator led_(on) waitcnt((clkfreq/10)+cnt) led_(off) waitcnt((clkfreq/10)+cnt) repeat 'this is the main loop valid_addr := gps.valid 'get address of gps.valid valid_dec := num.FromStr(valid_addr, num#DEC) 'convert to decimal if valid_dec > 0 'Don't send invalid packets led_(off) clearPacket fillGPSPacket mdm.createPacket(@packet, 1) '1 means no path included , 0 means full path mdm.sendPacket led_(on) 'Packet dispatched waitcnt((clkfreq/3)+cnt) led_(off) TX_DELAY := 120 'initialise TX hold off (seconds) Repeat until TX_DELAY < 1 'simple adaptive delay 'Conversion from string to decimal speed_addr := gps.speed 'get address of gps.speed speed_dec := Num.FromStr(speed_addr, Num#DEC) 'turn string into decimal speed_dec := speed_dec * 100 'multiply by 100 to make integer IF speed_dec > 2500 'in Knots = 29MPH TX_DELAY := TX_DELAY - 5 'keep reducing the delay if travelling fast waitcnt( clkfreq + cnt ) 'Wait 1 second TX_DELAY := TX_DELAY - 1 'Decrement delay PRI fillTestPacket addToPacket(string("!5315.60N/00207.70W-"), 20) addToPacket(string("***TEST***"), 10) 'This allow remote debugging via APRS! addToPacket(gps.latitude, 7) addToPacket(gps.N_S, 1) addToPacket(string("/"), 1) addToPacket(gps.longitude, 8) addToPacket(gps.E_W, 1) addToPacket(string("-"), 1) addToPacket(string("Propellor Test 12345"), 20) addToPacket(0,1) 'end of packet PRI fillGPSPacket addToPacket(string("!"), 1) addToPacket(gps.latitude, 7) addToPacket(gps.N_S, 1) addToPacket(string("/"), 1) addToPacket(gps.longitude, 8) addToPacket(gps.E_W, 1) addToPacket(string("-"), 1) valid_addr := gps.valid valid_dec := num.FromStr(valid_addr, num#DEC) valid_dec := valid_dec + 333 speed_addr := gps.speed speed_dec := num.FromStr(speed_addr, num#DEC) speed_dec := speed_dec * 100 speed_dec := speed_dec + 120 'Your data payload goes here addToPacket(string("APRS implemented by G3CWI. "), 27) addToPacket(string(" Test data follows: "), 20) if speed_dec > 119 addToPacket(string("Speed was 120"),13) addToPacket(string(" Knots "), 7) if valid_dec > 332 addToPacket(string("Valid was 333+"),14) addToPacket(0,1) 'end of packet PUB led_(onoff) outa[led] := onoff PUB addToPacket(straddr, length) | pointer 'no zeros may be added, except at the end! pointer := straddr repeat length if (packetcount<256) packet[packetcount++] := byte[pointer++] PUB clearPacket | i repeat 255 packet[i] := 0 i++ packetcount := 0This fails to work as hoped. I am really finding this whole address and content thing most confusing.
Any ideas?
Regards
Richard
I want to change a floating point number into a string.
FloatString has the perfect subroutine:
FloatToFormat(single, width, dp) : stringptr
However, I have been unable to figure out how to use it - the problem being that I don't understand
a) how to get back the string pointer and then
b) how to use it to get the string back.
Assuming my number is stored so that:
test := 123.456
I then tried combinations of:
test := fs.Floattoformat (test, 6, 2)
Debug.str (test)
I tried sprinkling @ signs around but still no joy. I am clearly mis-understanding the whole "address", Pointer, string thing.
Help appreciated.
Regards
Richard
Strings are encoded (we're dealing with ASCII encoding) byte arrays where each byte represents a character. Strings end with a zero. Called zero or null terminated.
This is incorrect syntax
This is correct syntax
bytemove(@buff, string("123.456"), strsize(string("123.456")))Hopefully this example helps a bit. This is the first time I used Float32. Someone will correct me if I did not use the object correctly.
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 DAT buff byte $0[10] OBJ pst : "Parallax Serial Terminal" f32 : "Float32" PUB Main | integer, mantissa, ans pst.Start(115_200) f32.Start waitcnt((clkfreq / 1_000 * 1_000) + cnt) ' 2 * 3.1416 = 6.2832 integer := 3 * 2 mantissa := f32.FFloat(1416) mantissa := f32.FMul(mantissa, 2) 'Write 6.2832 pst.dec(integer) pst.char($2E) ' . pst.dec(mantissa) pst.char($0D) ' CR 'Write a string bytemove(@buff, string("123.456"), strsize(string("123.456"))) pst.str(@buff) pst.char($0D) ' CRThanks for your interest. The number I have is of the form 123.456 and is a floating point decimal. Basically I need to round it to 0 decimal places (i.e. 123) and then use it as a string. That was the reason for looking at theFloattoFormat method from the FloatString Object. However as I don't really understand the terminology I don't know how to recover the pointer and how to use it to recover the string itself.
Regards
Richard
I'm not much further along the trail than you are but I think I just walked your path last week. I've attached my sloppy code that is a work in progress. If I understand your issue correctly, essentially what you need to do is apply the Numbers object. I give an example in the code below. If I'm not mistaken, if you bring in a decimal number into the Prop, say 123.45, you will by default get 123 . I hope I'm not being captain obvious and this helps you out.
Point of order to the experts out there: I noticed that the object GPS_IO_mini does NOT have a STOP method. Should it by convention have a Stop method and that Stop method be part of the Start method?
Regards,
Steve Woodrough
{************************************************** * GETTING GPS DATA 4 MARCH 2012 * * * *************************************************** THIS PROGRAM DEMONSTRATES GETTING GPS DATA, PARSING AND CONVERTING STRINGS TO NUMBERS AS WELL AS SENDING THE DATA TO EITHER THE PST OR LCD. } CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 RxPin = 1 CR = 13 ' ASCII <CR> LF = 10 ' ASCII <LF> { LCD ASCII Commands 8 Cursor left 9 Cursor right 10 Cursor down (bottom line will wrap to top line) 12 Clears the display 13 goes to next line 21 Turns display off 22 Turns Display ON 128 - 143 along line 0 148 -163 along line 1 } OBJ ss : "Simple_Serial" fds : "FullDuplexSerial" GPS : "GPS_IO_mini" n : "Numbers" VAR long Time, ShortTime Pub Main GPS_LCD 'This sould display the GPS data to the LCD. Pub GPS_LCD GPS.start(15,9600) 'Starts the GPS data parser to Rx data at 9600 fds.start(-1,4,1,19_200) ' Data to LCD via FDS (No Rx Pin, Tx on Pin 4, Mode 0 or 1, 19_200 Baud) FDS.tx(22) 'Turn LCD ON waitcnt(clkfreq/20+cnt) FDS.tx(12) 'Clears screen 'fds.start(31,30,0,57600) 'Sending data to PST via FDS repeat fds.tx(12) 'Clears screen fds.tx(128) 'move cursor Display_Longitude fds.tx(140) 'move cursor Display_Speed fds.tx(148) 'move cursor Display_Latitude fds.tx(160) Display_Heading waitcnt(clkfreq/2+cnt) Pub Display_Longitude fds.str(GPS.longitude) 'Transmits string pointer Pub Display_Latitude fds.str(GPS.latitude) 'Transmits string pointer Pub Display_Heading fds.str(GPS.Heading) 'Transmits string pointer Pub Display_Speed fds.str(GPS.Speed) 'Transmits string pointer Pub Display_Time fds.str(String("GPS String = ")) fds.str(GPS.time) 'Transmits string pointer to PST displaying the current time fds.tx(CR) fds.tx(LF) fds.str(String("GPS Time as Variable 'TIME' = ")) 'Converts the string value of time to a 10 digit decimal Time := n.FromStr(GPS.time,10) 'Using BASE 10 format fds.dec(Time) ShortTime:=Time-5 'Just playing around and proving to myself that I actually have a real number fds.str(String(" ShortTime = ")) 'Of course when "Time" ends with 00 the value of ShortTime ends in 95 but that fds.dec(ShortTime) 'was not the point of the exercise fds.tx(CR) fds.tx(LF) waitcnt(clkfreq+cnt) 'wait a second just to keep too much data from going to the PST Pub GPS_String_to_PST|x 'This routine works just fine and sends the NMEA strings to the PST ss.init(15,-1,9600) 'Message in on pin 15, no TX (-1) and 9600 baud fds.start(31,30,0,57600) 'Sending data to PST must be turned off to use VP terminal repeat x:=ss.rx 'Receive a byte on pin 3 from the GPS fds.tx(x) 'Transmits data to PST works great w/o VP active'Till the next problem
regards
Richard