Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

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
 
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.
 
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
 
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 )...
 
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
 
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....
 
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

Private Sub Form_Load()
    Length = 0
End Sub

Sub addChar(Dat As Byte)    'add char to buffer
    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

Private Sub Form_Load()
    Length = 0
End Sub

Sub addChar(Dat As Byte)    'add char to buffer
    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:
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.
 
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 https://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
 
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.
 
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!
 
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
 
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:
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.
 
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
 
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...
 
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
 
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.

Latest threads

New Articles From Microcontroller Tips

Back
Top