# Parsing Data Strings

Status
Not open for further replies.

#### Bill2003

##### New Member
I am trying to parse 2 lots of data from a string of serial data called EasyComm coming from my computer. It arrives in a format such as this AZ123.0 EL145.5. The AZ & EL are always in the string but the numbers unfortunately don't don't always have the 3 digits that come before the decimal point. It can be anything from 0.0 to 360.0 for the AZ data and 0.0 to 180.0 for the EL data. What I want to do is to identify each of the 2 parts of data using the AZ & EL strings and then get the 1 to 3 digits that follow them. I don't need the value after the decimal point, I only need an integer value. I was looking at using the AZ & EL characters to identify each string and then use the decimal point as a delimiter. I hope I've made that clear. There is always a space character between the 2 data strings that I receive, i.e. AZ145.6 EL34.7 I am new to the Oshonsoft software coming from Arduino's and I am still finding my way around the system but I have a reasonable knowledge of the BASIC language. Any help would be appreciated.
Bill2003

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Oshonsoft isn't very good with strings....

The best way forward is to write two functions... one to split the two parameters and the second to obtain the two integers...

Are they NULL terminated strings? as you use this delimiter to identify the end of string..
Once you call the function to split the two parameters just traverse the string until the space..
Then you will have two strings... Then traverse the split string until the decimal point, working backwards work out the integer one by one until a character ( A,B,C etc..) is encountered.

#### Bill2003

##### New Member
Thanks for the help Nigel. Yes, the strings are always terminated with a decimal point and the a number from 0 to 9 as the decimal part of the data. I don't need this number and was going to use the decimal point as the delimiter. I want to identify each string by the AZ or the EL start and then just read the 1 to 3 numbers that will appear before the decimal point from each chunk of data. I hope that makes it clearer. Using PBasic (probably a swear word on this forum), it can be done via the serin command, such as serin portin,84, [wait("AZ"), dec newazpos, wait(".") for Azimuth and serin portin,84, 2000,GetData[wait("EL"), sdec newelpos, wait(".") for the Elevation data. Like the Jack Daniels logo by the way but I normally drink Bush Mills Irish Whiskey this end. Thanks Bill

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Nigel!! I'm called Ian... Easy mistake to make....

How many strings are going to be involved? Is it just the AZ and the EL?

If this is the string in it's entirety " AZ123.0 EL145.5. ".. Then I would read the whole string into a buffer...

Then I would split the buffer at the space.. Then I would parse the two strings to leave the numbers...

I have a system that reads from a magnetic compass.. the string is as follows

$HCHDG,,,,15.3,E*30... The first parameter is the one I want it is the magnetic heading..$HCHDG, xxx.x , , , 15.3 , E*30. So I read the string until I get to the first ',' Then process the number..

Jack Daniels is a bit special to me as my daughter always buy's me one on Christmas, Fathers day and My birthday!!

I normally drink Dalwhinnie or a glenlivet ( well any single malt )...

#### Bill2003

##### New Member
Sorry about getting the name wrong Ian, I had looked at Nigel's tutorials in one of your links at the bottom of the page and thought that was your name.
Thanks for the example text. My biggest problem with extracting the information is the number that follows either the AZ or EL characters can be from 1 to 3 characters long followed by a decimal point and then a modulo of one number. I can use the decimal point as the point where I stop reading the number, but the biggest problem I am getting is the variation in the 1 to 3 numbers that follow the AZ & EL characters. I hope I made that sound right.

Glenlivet is a good drink, my favorite Scottish Whiskey is Talisker but it tends to be pretty expensive.

Bill

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
What operating system do you use??? I have now finished messing about with my laptop!!! all my software is now re-installed so I can now at last simulate stuff at home..... If you can give me a stream ( several outputs from easycomm) I will then write a little C# program to output a similar stream.... I then feed it via USB back to another program running the sim..... I can then show you what I mean....

#### Pommie

##### Well-Known Member
I didn't realise that Oshonsoft doesn't have any string functions and so I had a little play.

This is in VB but does everything as bytes.
You call addChar when you receive a character and it places the values in the two variables.
Code:
Dim buff(10) As Byte
Dim Length As Byte
Dim find(2) As Byte
Dim bool As Byte
Dim Var, AZ, EL As Integer

Length = 0
End Sub

buff(Length) = Dat
Length = Length + 1
If Length < 6 Then Exit Sub
find(0) = Asc("A")      'setup find string
find(1) = Asc("Z")
comp
If bool Then            'have we found AZ
GetNum              'yes, so get value
AZ = Var            'and save it
End If
find(0) = Asc("E")      'repeat for EL
find(1) = Asc("L")
comp
If bool Then
GetNum
EL = Var
End If
For i = 0 To Length - 1 'scroll buffer and loose first char
buff(i) = buff(i + 1)
Next
Length = Length - 1
End Sub

Sub GetNum()    'get the number at buff(2)
Dim i As Byte
i = 2
Var = 0
While buff(i) <> Asc(".")
Var = Var * 10
Var = Var + buff(i) - 48
i = i + 1
Wend
End Sub

Sub comp()      'compare find and buff
bool = 0
If buff(0) = find(0) Then
If buff(1) = buff(1) Then
bool = 1
End If
End If
End Sub
Edit: You could do the comparison in the main code and get rid of the comp subroutine and bool and find variables,
Code:
Dim buff(10) As Byte
Dim Length As Byte
Dim Var, AZ, EL As Integer

Length = 0
End Sub

buff(Length) = Dat
Length = Length + 1
If Length < 6 Then Exit Sub
If buff(0) = Asc("A") Then
If buff(1) = Asc("Z") Then
GetNum
AZ = Var
End If
End If
If buff(0) = Asc("E") Then
If buff(1) = Asc("L") Then
GetNum
EL = Var
End If
End If
For i = 0 To Length - 1 'scroll buffer and loose first char
buff(i) = buff(i + 1)
Next
Length = Length - 1
End Sub

Sub GetNum()    'get the number at buff(2)
Dim i As Byte
i = 2
Var = 0
While buff(i) <> Asc(".")
Var = Var * 10
Var = Var + buff(i) - 48
i = i + 1
Wend
End Sub
It shouldn't be too hard to convert.

Have fun,

Mike.

Last edited:

#### Bill2003

##### New Member
Thanks for the help Mike, I'll print off your code and have a look at the code and see if I can convert it over. I do have another option of using an Arduino as my Rotator board and could work in 'C' if I had to but I would rather use Oshonsoft with a PIC chip if I can.

#### Bill2003

##### New Member
Hello Ian,
Mike has come up with something that I will have a good look at later today. I use either Windoze or Linux as an operating system. for playing about with code, I use PICAXE, Oshonsoft's PIC Basic (which I like), and Arduino and that's running in 'C'

When the code comes to me from my Satellite Tracking Program, (I use WxTrack mainly, from http://www.satsignal.eu/software/wxtrack.htm and free in it's basic form), and the data comes to me in what is called EasyComm format. (explanation: ftp://www.amsat.org/amsat/software/win32/wisp/easycomm.txt) I only use the Azimuth and Elevation data and it will arrive on a Comm Port in the following format: AZ123.4 EL34.5 and if the satellite is being tracked, the data would either increment or decrement depending the direction it is travelling in so I would get something like: AZ123.4 EL34.5 AZ125.6 EL35.6 AZ127.5 EL40.3 and so on. All I need is the Integer part of the data that is between AZ and the Period . and EL and the Period . I then use this in a simple servo system that has two motors in it with a Potentiometer feedback that comes back to me as an analog voltage depending where the Antenna motor is pointing too. I then convert this voltage to an angular measurement, compare it with the data that has come from the satellite tracking program and if needed, move the motors so the antenna is pointing in the correct direction. It's basically a dual servo system. I hope I've made it clear but do let me know if I haven't.
Thanks again, Bill

#### Pommie

##### Well-Known Member
Hi Bill,

I would try the second version of the code first as that is simpler. The way to use it is to receive one character at a time and call addChar with that character. As soon as 6 characters have been received and the start of the buffer is either AZ or EL then it will update the variables. If anything isn't clear then just ask.

Mike.

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
First of all... You need to grab the entire string... This will be "carriage return terminated"

Setup the RXIE and wait until the string arrives... Then use Mike's code to make a parser ( BTW Mike! the part string can be smaller than 6 "EL1.0 " 5 will be the smallest )

The second of Mike's routines expect you have split the buffers into two... The "space" character is the splitting point.. the rest should be quite easy..

I'll try and write something in Oshonsoft basic today or tonight!

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
I have just done a little tester

This outputs the two integer values after being read as one string..

Code:
Dim inbuff(40) As Byte
Dim inptr As Byte
Dim outptr As Byte
Dim first(10) As Byte
Dim second(10) As Byte
Dim az As Word
Dim el As Word

Hseropen 19200
WaitMs 100
PIE1.RCIE = 1
INTCON.PEIE = 1
INTCON.GIE = 1
outptr = 0
inptr = 0

main:

If outptr > 0 Then
Call split()
Call getnumb()
outptr = 0
inptr = 0
Hserout "Azmouth = ", #az, 10, 13
Hserout "Elevation = ", #el, 10, 13
Endif

Goto main
End
On Interrupt
Save System
If RCSTA.OERR = True Then
RCSTA.CREN = 0
RCSTA.CREN = 1
Goto fin
Endif

inptr = inptr + 1
If inptr = 39 Then inptr = 0
inbuff(inptr) = RCREG
If inbuff(inptr) = 0xd Then outptr = inptr
fin:
Resume

Proc getnumb()
Dim x As Byte

x = 2
az = 0
While first(x) <> 0x2e
az = az * 10
az = az + first(x) - 0x30
x = x + 1
Wend
x = 2
el = 0
While second(x) <> 0x2e
el = el * 10
el = el + second(x) - 0x30
x = x + 1
Wend

End Proc

Proc split()
Dim x As Byte
Dim y As Byte
x = 1
y = 0
While inbuff(x) <> 32
first(y) = inbuff(x)
x = x + 1
y = y + 1
Wend
first(x) = 0
x = x + 1
y = 0
While inbuff(x) <> 13
second(y) = inbuff(x)
x = x + 1
y = y + 1
Wend
End Proc

#### Bill2003

##### New Member
I should have said that the EasyComm data string coming from the Satellite Tracking Software is at the moment, being updated every 5 seconds. I can set this between 1 and 60 seconds. Around 5 seconds is all I need so there is plenty of time for the software to sort out the maths between updates.. Bill

I should have said, Thanks for all of your help up to now and I am now working on what you have both sent me.

Last edited:

#### Pommie

##### Well-Known Member
The second of Mike's routines expect you have split the buffers into two... The "space" character is the splitting point.. the rest should be quite easy..
The above code doesn't split (or expect you to) the buffer at all. It simply looks for a valid start to the buffer (start = AZ or EL) and gets the number. It then scrolls the buffer so the start becomes invalid the next time it's called. BTW, how does your code know where the start of the string is in the buffer?

Mike.

#### Bill2003

##### New Member
I identify the start of the string by the "A" of the AZ etc string that is coming from the Satellite Tracking program. It always come in the form of AZ123.4 EL45.6.

Bill

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
The above code doesn't split (or expect you to) the buffer at all. It simply looks for a valid start to the buffer (start = AZ or EL) and gets the number. It then scrolls the buffer so the start becomes invalid the next time it's called. BTW, how does your code know where the start of the string is in the buffer?

Mike.
I'm going off Bill's explanation the complete string "AZxxx.x ELxxx.x" The space splits the two parts... and each substring only has two alpha characters...

#### Bill2003

##### New Member
Hello Languer, I have tried a number of times to register for the pic sim ide website but everytime I try to register, it just takes me to a yahoo page that says it's not available. Is there any other way I can register for this site?
Bill

#### jjw

##### Member
I have been a member in pic sim ide group, but can't sign in anymore.
I tried to get a new membership with a reply:

"Hello,

Your request to join the pic_sim_ide group was not approved.
Your membership was automatically rejected because the moderator didn't
approve it within 14 days. We do this to provide a high quality
of service for our users."

Status
Not open for further replies.