Question on Parsing using received data from Serial Terminal Object
kvanepps
Posts: 10
Hello to all:
I have been working the the Propeller for a few days now and would like to try to create a parer for incoming serial data over the serial port. I posted something earlier today but I do not see it so I am posting my problem in a different way since I was originally posting on a parsing method I was trying to create. Since then, I have found two objects on the OBEX site that provides parsing of string methods. But I do have some questions since I am running on a short time frame to get something working.
My plan is to have a protocol of ASCII data that is delimited by a pipe characters (|) sent as a single string. There will be five fields of numbers sent from a GUI on a PC to the Propeller via the USB/serial connector on the propeller board. These five fields will be separated by a pipe so it will be received as a string of text as follows:
40|200|14|12|15|
I want to parse this string and separate the five fields into a a byte array of five.
i.e
VAR
byte field[5]
By using some of the String parser methods, I want to read each field and convert the ASCII text of each field into a single byte, storing it in the byte field array. These fields will always be numbers and none of them will have a value over 254..
I plan on using the Parallax Serial Terminal object to receive and send data between the PC GUI and the Parallax Quickstart board.
I was thinking on using the method StrIn(stringptr) in the Serial Terminal Object to get the incoming string and them parse by looking for the pipes. To use this method, do I create a variable in the VAR section as a long or do I create another array of bytes that will hold the string returned from this method?
Does the Serial Terminal Object support a buffer for incoming messages? I noticed that the Serial Terminal Object also has a method (private) called StrToBase(stringptr,base) that will convert a string to a number. I would like to use this. Would it be better to copy this into my main program or would it be acceptable to change this method to be public?
Thanks
Ken
I have been working the the Propeller for a few days now and would like to try to create a parer for incoming serial data over the serial port. I posted something earlier today but I do not see it so I am posting my problem in a different way since I was originally posting on a parsing method I was trying to create. Since then, I have found two objects on the OBEX site that provides parsing of string methods. But I do have some questions since I am running on a short time frame to get something working.
My plan is to have a protocol of ASCII data that is delimited by a pipe characters (|) sent as a single string. There will be five fields of numbers sent from a GUI on a PC to the Propeller via the USB/serial connector on the propeller board. These five fields will be separated by a pipe so it will be received as a string of text as follows:
40|200|14|12|15|
I want to parse this string and separate the five fields into a a byte array of five.
i.e
VAR
byte field[5]
By using some of the String parser methods, I want to read each field and convert the ASCII text of each field into a single byte, storing it in the byte field array. These fields will always be numbers and none of them will have a value over 254..
I plan on using the Parallax Serial Terminal object to receive and send data between the PC GUI and the Parallax Quickstart board.
I was thinking on using the method StrIn(stringptr) in the Serial Terminal Object to get the incoming string and them parse by looking for the pipes. To use this method, do I create a variable in the VAR section as a long or do I create another array of bytes that will hold the string returned from this method?
Does the Serial Terminal Object support a buffer for incoming messages? I noticed that the Serial Terminal Object also has a method (private) called StrToBase(stringptr,base) that will convert a string to a number. I would like to use this. Would it be better to copy this into my main program or would it be acceptable to change this method to be public?
Thanks
Ken
Comments
Serial Terminal Object has a message buffer for sending and another one for receiving. (both set to 64 bytes in size)
The Serial Terminal Object is a good starting point for your project even if you have to modify it here and there to make it a perfect fit. So, create a copy with a different filename and start tweaking!
So, here is the idea of a program that is doing what you need:
The tweaked DecIn would simply receive bytes until it sees the number-separator-character ( | in your case ) instead of waiting for NL.
Please note the syntax could be off. I am writing this off memory
If you send a number as a string you have to parse it on propeller side to make it a number you can calculate with again. No way to parse it on PC-side.
If you want to send bytes ... well ... possible but then you have a protocoll that only computers can read. But this is only a good advice if you need the extra performance.
But in the end your avice is even wrong, because DecIn receives a number string and not a byte and is doing the parsing for you.
So, either you have the combination
send bytes - read with CharIn
send string - read with DecIn
Nevertheless in the byte transfer you really need to think about how to find the start/end of a package (5 bytes). So, you need a special kind of protocol which allows to recover if you have an transmission problem.
With decimal string you can use each character other than numbers to give signals to the receiver like END_OF_NUM ( | in our example ) and END_OF_PACKAGE ( CR maybe ... )
http://obex.parallax.com/objects/644/
There is also a good thread listing all the spin serial objects here:
http://forums.parallax.com/showthread.php?128184-Serial-Objects-for-SPIN-Programming
Been working on this and below is the code we came up with. There still is some debug statments in it for testing purposes. It will now take the following as a command with fields:
+10|200|20|20|10|<NF>
The line feed will indicate to the program that it is the end of the command and the ParseCommand method will work to parse out the five fields. Two errors will be fed back on the serial port if the "+" is not sent to indicate the start of the command fields as well as an error if too many fields are sent.
I don't know if this is the most efficient but it works. Any suggested improvements would be appreciated. It took a while to figure out how to work with pointers and variables.
The definition of StrInMax says:
PUB StrInMax(stringptr, maxcount)
ptr means that you should really call this function with a pointer to a buffer as the first parameter. But have a look at your code, you don't use a pointer but a variable containing zero because it's initialized like that by the propeller tool. But in all other calls which also expect a pointer you also simply use "input". Maybe you are coming from C programming? There the name of an array is a pointer, but that is not true for SPIN.
So, if you replace the input with @input in the TestMessage function you do it the right way.
For ParseCommand I do not really understand why you do not use input directly? Nevertheless -without running your program- this seems to be coded in a way that it also needs a pointer as parameter. The call ParseCommand(@input) should do the job.
Thanks for the info. I have been programming in C++ and Java so I am still trying to understand the syntax and language for Spin. I just received a Quickstart board this weekend and have been playing with some of the tutorials in the PE Expermienter manual. I will try your suggestions.
Thanks
Ken