Serin and #

pmolsen

Senior Member
I am using Serin and # successfully in several programs (written 6 years ago). Just trying to use them again and cannot seem to get it to work.

I am sending a file from a PC with Tera Term (via USB TTL link) then reading with SERIN on the Picaxe. The file starts like this and is in ASCII:

A08,00,09,30crlf
P14,30,16,00crlf
Y12,00,00,00crlf

If I read like this:
serin [8000,sertimeout],radio,t9600_32,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13
It works perfectly, with b0="A",...B10="3", B11="0", B12=$0D, B13=$0A

If I read like this:
serin [8000,sertimeout],radio,t9600_32,b0,#b1,b19,#b2,b19,#b3,b19,#b4,b19,b19
I get b0="A", B1=8, B2=0, B3=9 but for some reason B4=0 instead of 30

I tried putting another comma after the 30 and before the crlf but still got the same.
I tried changing the 30 to 125 and B4 was then 25.

What am I not understanding? (The manual is extremely light on explanation on the use of #).

I put a 2ms delay between each character on the send side.
 

hippy

Technical Support
Staff member
The #var consumes the last character that is not a digit so the "," and CR are already lost before it moves onto the next character, the 'b19' are therefore not eating the "," but the first digit of the subsequent number - when that's zero you won't notice it!

This works for SERRXD ...

#Picaxe 18M2
#Terminal 4800
Do
SerRxd b0, #b1, #b2, #b3, #b4
SerTxd( b0, " ", #b1, " ", #b2, " ", #b3, " ", #b4, CR, LF )
Loop

For "A08,00,09,30crlf" prints "A 8 0 9 30".
 

pmolsen

Senior Member
Oh, I think I see. I should have coded it without any B19's, or rather, just the final one to eat the LF.

Does a variable have to be coded? (the b19)? or can it be left out with ,,?
 

hippy

Technical Support
Staff member
Oh, I think I see. I should have coded it without any B19's, or rather, just the final one to eat the LF.
That's correct ...

Code:
.----------------------------------> "A"
| .--------------------------------> 8
| |     .--------------------------> 0
| |     |     .--------------------> 9
| |     |     |     .--------------> 30
| |____ |____ |____ |_____
A 0 8 , 0 0 , 0 9 , 3 0 cr lf
Does a variable have to be coded? (the b19)? or can it be left out with ,,?
Not exactly sure I understand. Assuming the first "," is consumed by a preceding #var, you can either manually consume the second "," with a 'b19' or use a #var and let it ignore the "," and anything else until a first digit character is seen.

If you having variable length data and/or missing fields in the data it can be tricky, sometimes impossible, to use a SERIN to grab it all in one go.
 

pmolsen

Senior Member
What I meant was having null variables to skip junk like #b1,b2,,,,b5 but it gives a syntax error.

Is the full explanation of how the # works documented anywhere? For example consuming lots of junk with one # var?

Just to clarify, if the data was 111,,,,,,222 then serin... #b0,#b1,#b1 would give b0=111 and b1=222?
 

hippy

Technical Support
Staff member
What I meant was having null variables to skip junk like #b1,b2,,,,b5 but it gives a syntax error.
No, consecutive ,, in SERIN and SERRXD are not valid.

Is the full explanation of how the # works documented anywhere? For example consuming lots of junk with one # var?
Possibly not, other than having been described on the forum. I will make a note of that.

Just to clarify, if the data was 111,,,,,,222 then serin... #b0,#b1,#b1 would give b0=111 and b1=222?
No.

Every #var waits for a digit character to arrives then starts accumulating the number until a non-digit character arrives. So #b0 will have read "111," and deliver the result 111.

#b1 will then start looking for a number, skip five commas, see the 222 but will then wait until a further digit or non-digit arrives. The accumulation will only terminate when a non-digit arrives.

The second #b1 won't even start until after the first #b1 has been completed.

Receiving "111,,,,,,,222,,,,,333crlf" would have b0 set to 111 and b1 set to 77 ( 77=333 And $FF).
 

pmolsen

Senior Member
Afraid you've lost me on the last line. Why is the "first" b1 not set to 333 since cr is a non-digit? Where does And $FF come in?
 

Technical

Technical Support
Staff member
Because 333 is bigger than 255, the maximum the byte b1 can hold. That is why hippy anded with 255 ($FF), 77 is the overflow value you will end up with.
 

pmolsen

Senior Member
Now I am having another issue.

In total I am sending 35 lines, each having 12 characters + crlf. That totals 490 bytes or 3920 bits. In Tera Term I have specified a 1ms delay between each character. I am transmitting at 9600. So the transmission of the 3920 bits should take under half a second and the 1ms delays should total under half a second. The total transmission time should therefore be under one second.

I turn on an LED at the start of the receiving and off at the end, yet it is on for 8.5 seconds.

Here is the data. It is in a file and I am using File/Send File in Tera Term:

#2
A08,00,09,30
P14,30,16,00
Y12,00,00,00
D01,04,07,10
H01,01,26,01
H06,04,20,04
H11,06,11,06
H02,07,13,07
H24,09,05,10
H24,12,31,12
Y13,00,00,00
D07,04,06,10
H01,01,28,01
H15,04,26,04
H10,06,10,06
H01,07,12,07
H23,09,07,10
H23,12,31,12
Y14,00,00,00
D06,04,05,10
H01,01,27,01
H14,04,25,04
H09,06,09,06
H30,06,11,07
H22,09,06,10
H22,12,31,12
Y15,00,00,00
D05,04,04,10
H01,01,26,01
H03,04,17,04
H25,04,25,04
H08,06,08,06
H29,06,10,07
H21,09,05,10
H21,12,31,12
%%%%%%%%%%%%


Here it my test code: (Note that the short first data line above is processed separately, then I turn on the LED. It is not counted in the data count above.)

symbol radio = C.0
symbol ledpin = B.0 ; For indicator LED
symbol startbyte = "#"

a1:
setfreq m32
w7 = 0
do until b0 = startbyte or w7 > 10
serin [8000],radio,t9600_32,b0
w7 = w7 + 1
loop
if b0 <> startbyte then sertimeout

serin [500,sertimeout],radio,t9600_32,b0,b1,b2 'opt,cr,lf

high ledpin
bptr = 50
for b0 = 1 to 35
serin [500,sertimeout],radio,t9600_32,@bptrinc,#@bptrinc,#@bptrinc,#@bptrinc,#@bptrinc,@bptr
next

low ledpin

setfreq m4
for w7 = 50 to 300 step 5
peek w7,b1,b2,b3,b4,b5
sertxd (b1," ",#b2," ",#b3," ",#b4," ",#b5," ",cr,lf)
next

sertimeout:
goto a1
 
Last edited:

pmolsen

Senior Member
I forgot the start and stop bits. They bump it up to 4900 bits or just over half a second transmission time.
 

Technical

Technical Support
Staff member
We would guess you are getting out of sync and timing out. Put some test code at sertimeout: to indicate this.
 

pmolsen

Senior Member
No, it is not timing out. It is working perfectly and reading all of the data correctly as the sertxd just above the sertimeout proves.
 

Technical

Technical Support
Staff member
Then what is the actual issue you have? If the code is working correctly the only extra delays can be in what the sending software is actually doing, have you checked it really adds a 1ms precise delay?
 

pmolsen

Senior Member
I have rewritten the test program based on what I came up with in the real one. It is as below. Also a screen shot showing testing of the 3 valid options. The first two are just dummied up, the third one reads actual data and stores it.

As you can see it does not give any errors but runs perfectly. The data is written to EEPROM from temp storage then read from there and displayed.

I have also modified the data file to be less rigid. The data is as below.

On TeraTerm the data on the screen flies through in about 1 second. I cannot imagine that it would be buffering it somewhere. I assume that as it writes bytes from the file to the screen it also sends them to the interface.

Code:
   symbol radio        = C.0
   symbol ledpin       = B.0             ; For indicator LED
   symbol startbyte = "#"
   symbol stopbyte = "%"
   symbol dumpstart = 7
   symbol serincnt = b9
   symbol opt = b10
   symbol optasc = b11
   symbol val = b12
                  
a1:
' Read start byte
    setfreq m32             ; run faster here
    high radio            ; supply power to radio
    serincnt = 0
    val = 0
    do until val = startbyte or serincnt > 253
      serincnt = serincnt + 1  
      serin [4000],radio,t9600_32,val ; wait 0.5 seconds for data
      loop
    if val <> startbyte then a1      ; no serial input 


' Read option - do not use # or it eats stop byte
    serin [500,badradio1],radio,t9600_32,optasc ; get option
    opt = optasc - 48                     ; ascii to decimal
    on opt goto badradio2,opt1,opt2,opt3  ; branch based on opt
    goto badradio2                    ; invalid opt


' Read and store new data in RAM
opt1:
   high ledpin
   bptr = 50              ; RAM storage start location
   do until bptr > 250  
      serin [500,badradio3],radio,t9600_32,#@bptrinc
      loop
   low ledpin

' read final cr and stop byte
   serin [500,badradio4],radio,t9600_32,b0,b1
   if b1 <> stopbyte then badradio5


' Transfer validated data to EEPROM
   setfreq m4
   bptr = 50              ; RAM storage start location
   for b0 = dumpstart to 255
      write b0,@bptrinc   ; save in eeprom
      next

   for b0 = 0 to 250
     read b0,b1
     sertxd (#b1," ")
     next 

   goto a1

opt2:
opt3:
   setfreq m4
   sertxd ("valid option ",optasc,cr,lf)
   goto a1

badradio1:
   setfreq m4
   sertxd ("timed out reading option",cr,lf)
   goto a1

badradio2:
   setfreq m4
   sertxd ("invalid option ",optasc,cr,lf)
   goto a1

badradio3:
   setfreq m4
   sertxd ("timed out reading data",cr,lf)
   goto a1 

badradio4:
   setfreq m4
   sertxd ("timed out reading stop byte",cr,lf)
   goto a1

badradio5:
   setfreq m4
   sertxd ("invalid stopbyte",cr,lf)
   goto a1
Data file:
Code:
#1
8,0,9,30
14,30,16,0

12

1,4,7,10

1,1,26,1
6,4,20,4
11,6,11,6
2,7,13,7
24,9,5,10
24,12,31,12
0,0,0,0
0,0,0,0
0,0,0,0
0,0,0,0
0,0,0,0


7,4,6,10

1,1,28,1
15,4,26,4
10,6,10,6
1,7,12,7
23,9,7,10
23,12,31,12
0,0,0,0
0,0,0,0
0,0,0,0
0,0,0,0
0,0,0,0


6,4,5,10

1,1,27,1
14,4,25,4
9,6,9,6
30,6,11,7
22,9,6,10
22,12,31,12
0,0,0,0
0,0,0,0
0,0,0,0
0,0,0,0
0,0,0,0


5,4,4,10

1,1,26,1
3,4,17,4
25,4,25,4
8,6,8,6
29,6,10,7
21,9,5,10
21,12,31,12
0,0,0,0
0,0,0,0
0,0,0,0
0,0,0,0
%
 
Last edited:

pmolsen

Senior Member
PS. How do I get the sample program above to be scrollable in a separate window like I see in other posts please?

Here is the screenshot mentioned above.
pic156.jpg
 

Technical

Technical Support
Staff member
Have you considered that the bluetooth module itself may be buffering and/or adding a delay between each byte?
You really need to get a 'scope or logic analyser on the data stream into the PICAXE to see.
 

pmolsen

Senior Member
I am actually not using the bluetooth module at present. Every time I download a new program it loses the pairing with the PC and won't reconnect (as per separate topic I raised.) I have to Remove Device and Add Device every time, which takes forever.

At present I am just using a hard-wired USB-TTL converter: http://cgi.ebay.com.au/ws/eBayISAPI.dll?ViewItem&item=270962306229&ssPageName=ADME:X:eRTM:AU:1123#ht_4389wt_1140

I guess it could be buffering, although there is nothing in the specs to suggest it does and no reason why it should.

I will try a scope on the line and see what it looks like.
 

hippy

Technical Support
Staff member
On TeraTerm the data on the screen flies through in about 1 second. I cannot imagine that it would be buffering it somewhere. I assume that as it writes bytes from the file to the screen it also sends them to the interface.
If it sends a byte to the UART, then suspends for 1ms, it could be that Windows is actually suspending the app for longer than 1ms. 18ms used to be the standard suspend time interval and 500 bytes x 18ms = 9 seconds, pretty close to what you are seeing.

Try increasing the inter-byte gap delay and seeing if that still has the 8.5 second receive timing. Above some time you'll probably see the time jump to double, 17 seconds, if it is rounding up suspend times.

That doesn't explain why the app displays the data sent in a shorter time but it may be two threads running; one for the display and one for serial which are independently suspending.

You can also add a LED+R to the signal line to see how long the actual transmission lasts for. A scope or logic analyser should instantly show what's going on.

Added : Cross-posted with above couple of posts. I'd also say it could be the Bluetooth module / driver adding some buffering, waiting for acknowledgements.
 

pmolsen

Senior Member
I just put a scope on the line. The line is normally high (5v) but drops low for the data. It is transmitting constantly for the full 8 seconds but the gaps between the groups of 0v's are very long but also quite variable.
 

Technical

Technical Support
Staff member
Try taking out the 1ms delay but using 2 stop bits instead to give the PICAXE a bit of breathing space between bytes.
If it is an FTDI type USB-TTL device you can change the latency under driver advanced properties down to about 2.
 

pmolsen

Senior Member
That is a lot quicker thanks. It is reading about half the data then getting a timeout. I will do some more playing.

I could do the read of the full 250 bytes with a huge serin statement but unfortunately my program is too big.

What I have is about as tight as I can get the loop:

bptr = 50 ; RAM storage start location
do until bptr > 250
serin [500,badradio3],radio,t9600_32,#@bptrinc
loop

I think a hard-coded test instead of the do-until may be a bit faster. I will try that also.
 

Technical

Technical Support
Staff member
This is quicker - simply keeps getting data until it stops coming and hence timesout

bptr = 50 ; RAM storage start location
lp:
serin [500,badradio3],radio,t9600_32,#@bptrinc
goto lp
 

pmolsen

Senior Member
My concern was what happened if it got more data than expected. The manual is a bit light on with a description of the RAM and what happens if you try to write past the end (511). I assume it does no harm.
 

pmolsen

Senior Member
Hmmm. That could be a problem as it would then overwrite the b0-b27 variables if I read the manual correctly.
 

pmolsen

Senior Member
I have done some more testing. With this tight loop and 2 stop bits I can capture all the data.

serin [50000,badradio],radio,t9600_32,b0,b1,b2
opt1a:
serin [500,xx],radio,t9600_32,#@bptrinc
goto opt1a

If I change to 1 stop bit it fails. If I change the goto to read: if bptr < 252 then opt1a it fails.

So it would seem that even at 32MHz it is right on the limit reading 9600bps.

I cannot afford to risk corruption.

I have just changed it to 4800 and it sings. I can also add several additional statements into the loop and it still works. If I use 2 stop bits I can even insert a PAUSE 1 and it still gets all the data - and 8 times as fast as at 9600 with the 1ms delay between each byte!

The cause of the 8s transmission time when I use a 1ms pause between each byte remains a mystery. Maybe someone else can look at it some time.

I tried two other free terminal emulator programs but they did not have the ability to insert delays into the stream so I couldn't test with them.
 
Top