SERIN parsing help needed.
oday
Posts: 7
Hi,
I'm receiving a serial string (38.4k strict) using a 2p24 and able to take it into one variable. However, the string contains three comma-delimited data sets and are not fixed length, so I need to break the data out into three separate variables. I put together a decent example of what I have.
Anyone able to advise? I about broke my back spending the past couple days trying to solve this! I'm okay with parsing VAR raw instead of doing it during the SERIN, but I need help with that -- I don't know how.
Daniel
--
raw VAR BYTE ' No specific array is defined, but it reads the string in great!
vvv_aaa VAR BYTE(6) ' Max input string length is 5 chars
vvv_bbb VAR BYTE(6) ' Max input string length is 5 chars
vvv_ccc VAR BYTE(5) ' Max input string length is 4 chars
DO
PAUSE 1000
SEROUT RX, T38K4, ["go",CR] ' I have to use 38.4k. Data is coming from a 3rd party product.
SERIN TX, T38K4, 3000, NO_DATA, [STR raw\17\CR] ' This works great
DEBUG "RAW: ",STR raw,CR ' and returns "aaaaa,bbbbb,cc.c" or shorter perfectly
' should I go ahead and parse this variable into three separate
' ones rather than gamble on parsing during SERIN?
vvv_aaa(5) = 0 ' Defining byte 6 as "0" per Syntax Manual 2.2 Page 405
vvv_bbb(5) = 0 ' "
vvv_ccc(4) = 0 ' Defining byte 5 as "0" per Syntax Manual 2.2 Page 405
PAUSE 1000
SEROUT RX, T38K4, ["go",CR]
SERIN TX, T38K4, 3000, NO_DATA, [STR vvv_aaa\5\",",STR vvv_bbb\5\",",STR vvv_ccc\2\CR]
' vvv_ccc\2 is filled with garbage
' and sometimes vvv_bbb is garbage too, when real data is "--"
' vvv_ccc\4 (desired) hangs the program
' tried with and without \CR
DEBUG "RAW X 3: ", STR vvv_aaa, " ", STR vvv_bbb, " ", STR vvv_ccc, CR
LOOP
NO_DATA: ' Merely loops back in, prevents hanging, etc. Not important for troubleshooting the SERIN parsing.
///
DEBUG SAMPLE #1:
RAW: 2948,1592,0
RAW X 3: 2948 1592
I'm receiving a serial string (38.4k strict) using a 2p24 and able to take it into one variable. However, the string contains three comma-delimited data sets and are not fixed length, so I need to break the data out into three separate variables. I put together a decent example of what I have.
Anyone able to advise? I about broke my back spending the past couple days trying to solve this! I'm okay with parsing VAR raw instead of doing it during the SERIN, but I need help with that -- I don't know how.
Daniel
--
raw VAR BYTE ' No specific array is defined, but it reads the string in great!
vvv_aaa VAR BYTE(6) ' Max input string length is 5 chars
vvv_bbb VAR BYTE(6) ' Max input string length is 5 chars
vvv_ccc VAR BYTE(5) ' Max input string length is 4 chars
DO
PAUSE 1000
SEROUT RX, T38K4, ["go",CR] ' I have to use 38.4k. Data is coming from a 3rd party product.
SERIN TX, T38K4, 3000, NO_DATA, [STR raw\17\CR] ' This works great
DEBUG "RAW: ",STR raw,CR ' and returns "aaaaa,bbbbb,cc.c" or shorter perfectly
' should I go ahead and parse this variable into three separate
' ones rather than gamble on parsing during SERIN?
vvv_aaa(5) = 0 ' Defining byte 6 as "0" per Syntax Manual 2.2 Page 405
vvv_bbb(5) = 0 ' "
vvv_ccc(4) = 0 ' Defining byte 5 as "0" per Syntax Manual 2.2 Page 405
PAUSE 1000
SEROUT RX, T38K4, ["go",CR]
SERIN TX, T38K4, 3000, NO_DATA, [STR vvv_aaa\5\",",STR vvv_bbb\5\",",STR vvv_ccc\2\CR]
' vvv_ccc\2 is filled with garbage
' and sometimes vvv_bbb is garbage too, when real data is "--"
' vvv_ccc\4 (desired) hangs the program
' tried with and without \CR
DEBUG "RAW X 3: ", STR vvv_aaa, " ", STR vvv_bbb, " ", STR vvv_ccc, CR
LOOP
NO_DATA: ' Merely loops back in, prevents hanging, etc. Not important for troubleshooting the SERIN parsing.
///
DEBUG SAMPLE #1:
RAW: 2948,1592,0
RAW X 3: 2948 1592
Comments
By all means, if you must stay at 38.4K, do the parsing after receiving. The Stamps don't have comm buffers so if you slow down to parse on the fly, you'll miss characters.
If you want to experiment, set up three SERIN statements with a WAIT modifier (see the Helpfile) so that you grab the first variable on the first data transmission, the second variable on the second data transmission and so on.
It will take longer but may preserve some variable space. But, with the Scratchpad area available, its probably not a big deal.
Cheers,
I played around with the wait, like you sggest, but couldn't get it to work. I suspect an error on my part using wait.
SERIN TX, T38K4, 3000, NO_DATA, [STR vvv_aaa\5\","] ' works
PAUSE ... SEROUT
SERIN TX, T38K4, 3000, NO_DATA, [WAIT(","), STR vvv_bbb\5\","] ' does not work
PAUSE ... SEROUT
SERIN TX, T38K4, 3000, NO_DATA, [WAIT(","), WAIT(","), STR vvv_ccc\4\CR] ' doesn't work either
Can you offer and specific advice on how to parse var raw into separate variables, or help me properly use the WAIT modifier?
Thanks,
Daniel
You will definitely have to parse the string after receiving the raw data. The other parsing modifiers are simply too slow unless the other device can add extra stop bits pacing. If the amount of RAM buffer required is a problem, an alternative, also capable of relatively high speed reception on a BS2p, is the SPSTR modifier to receive the bytes directly into SPRAM.
There is some info on the timing of serial commands here.
It may just be that at the high speed, it can't see 5 characters before the "," comes along. Try it without expecting the trailing "," You may find the fifth character in the string is the comma. Similarly with the CR for the third string. If the data is variable length and the specified number of bytes don't arrive, it will hang.
You can also use the SKIP modifier which might act faster; but if you don't know how many characters to expect, it may not be too useful.
With variable length, the only things you know for sure is two commas and a CR, so crunching everything after the capture may be the most effective.
Then, a bit of a FOR-NEXT loop looking for the commas and CR will define how many characters in each number.
Can you capture and post the data string from the data source with Hyperterminal so we can see what to expect?
-looks like the extended ascii output in the debug won't paste properly to the forum. Attaching a text file.
Daniel
ECK01 RAW: 1220,659,0
TEST:
A couple brief (fairly important) questions about it, if I may;
1. The template for the third serin field is xx.x (or) x.x. Does the code you advised drop the decimal point, or what kind of behavior might happen?
2. Where you used .., timeout, [..., I had previously been trying to use a subroutine that resets the sending device and goes back to the parent routine to try again. I understand the purpose of the timeout as used here, but wonder how I might go elsewhere if no data is received?
Thanks again,
Daniel
1) I believe based on the logic of the code that it just loops over the decimal point and returns a number in units of tenths. So xx.x will be xxx, and x.x will be xx. You should be able to print the result with the radix point using,
2) If no data at all is received, the very first character and the ones after it in the SPRAM buffer will remain as zeros. So, a simple solution would be to look and bail out if that first char is zero: A more sophisticated test would bail out if there are too few chars, or if unallowed chars are found, or if the data values are out of expected range. The need for that will depend on looking at the raw data string to see what sort of errors (if any!) crop up.
Amazing -- thank you! I had to alter it a bit, since I do consider "0" to be valid data. I did try your
DEBUG DEC wz/10, ".", DEC1 wz
but it seemed to result inaccurately. Specifically, whenever wz is "6", I got "0.6". I'll fiddle more with it.
- Daniel
In my main:
FOR idx=0 TO 17 : PUT idx, "a" : NEXT
SEROUT RX, T38K4, ["go",CR]
SERIN TX, T38K4, 3000, GOT_DATA, [SPSTR 17]
GOT_DATA:
GET 0, char
IF char = "a" THEN GOTO NO_DATA
GOSUB PARSE
RETURN
And commented out part of the parsing routine that seemed to be interfering with the zeros:
PARSE:
wx=0 : wy=0 : wz=0
pntr=0 ' this will point in succession to wx, wy, wz
FOR idx=0 TO 17
GET idx,char
SELECT char
' CASE "0", CR
' EXIT
CASE "0" TO "9"
wx(pntr) = wx(pntr)*10+char-48 ' accumulate digits into variable
CASE ","
pntr=pntr + 1 ' point to next word wy, wz.
ENDSELECT
NEXT
RETURN ' wx, wy wz contain values
It has to be
CASE 0, CR
not
CASE "0", CR.
The former looks for a null, that is, the actual ascii code zero, whereas "0" looks for the ascii representation of zero, which is the ascii code $30 hex or 48 decimal.
From what you have said, the data will all be printable ascii characters, and the null would not normally occur.
That CASE is important because it gives the criterion for exiting the loop early, in case there is no data at all, or in case it has processed the entire received string.
I'm not sure about the 6. So, this device can send back xx.x, x.x, or simply x? That will take a little more code.