Serin timings

sid

Senior Member
I've written a program that starts off by waiting for a serin input, when this is received the program happily goes off and does the other things required of it. However at various points within that program I want to "gosub" back to the serin section of code to see if a new piece of data has been sent and if not then as you were via a "return".
When I code for this, the program just stops at the serin command. Having read manual two (see below) am I right in understanding, that when a serin command is used the program will stop at this point until new data is received and a solution to this is to set a timeout value for the serin command. The manual goes on the say read the section on serial download for further info. I've looked through all three manuals but can't seem to find any further info.
How do I go about setting a timeout for the serin command?


Code:
All processing stops until the new serial data byte is received. This command
cannot be interrupted by the setint command. The following example simply
waits until the sequence “go” is received.
serin 1,N2400,(“go”)
:confused:
The M2, X1 and X2 parts can take an optional timeout value and address at the
start of the command. The timeout value, set in milliseconds, is the length of
time the serin command will wait for a serial command to be detected. After the
timeout period , if no signal is detected, program flow will jump to the time out
address.
 

Chavaquiah

Senior Member
Additional optional timeout syntax options for M2, X1 and X2 parts:
SERIN [timeout], pin,baudmode,(qualifier...)
SERIN [timeout], pin,baudmode,(qualifier...),{#}variable,{#}variable
SERIN [timeout], pin,baudmode,{#}variable,{#}variable
SERIN [timeout,address], pin,baudmode,(qualifier...)
SERIN [timeout,address], pin,baudmode,(qualifier...),{#}variable,{#}variable
SERIN [timeout,address], pin,baudmode,{#}variable,{#}variable
An example:

Code:
main:
   serin [5000, NoData], C.0, N2400, b0 'Wait at most 5s for serial data
   sertxd ("Received: ", #b0, cr, lf)
   goto main

NoData:
   sertxd ("No data received within 5 seconds", cr, lf)
   goto main
 

westaust55

Moderator
You do not state which PICAXE chip you are using 18M2, X1 or X2 parts.

Background receipt of data using hserin is possible.

For the 18M2 from PICAXE manual 2 page 90
On M2 parts the hserin command is used to transfer background received bytes into a variable. Up to two bytes can be ‘background received’ at any time during the PICAXE program (not just when the hserin command is processing) and are temporarily stored in a 2 deep FIFO buffer. Any more than two bytes are lost.
hserin will also work with the X2 parts for background serial input - read up from page 89 onwards.
Note that on X2 parts you may prefer to background receive the serial data into
the scratchpad (hence not requiring use of this command at all) - see the
hsersetup command for more details (hserin only accepts data when the
command is being processed - background receive accepts data all the time).
 

sid

Senior Member
You do not state which PICAXE chip you are using 18M2, X1 or X2 parts.

Background receipt of data using hserin is possible.

For the 18M2 from PICAXE manual 2 page 90


hserin will also work with the X2 parts for background serial input - read up from page 89 onwards.
Thanks, Westaust55,
I'm using a 20x2 so I'll have a read of the maunual tonight and then give it a go.
I like the idea a being able to monior/recieve data in the background as this should make the coding simpler rather than having lots of gosubs all over the place.
Cheers Sid
 

sid

Senior Member
You do not state which PICAXE chip you are using 18M2, X1 or X2 parts.

Background receipt of data using hserin is possible.

For the 18M2 from PICAXE manual 2 page 90


hserin will also work with the X2 parts for background serial input - read up from page 89 onwards.
I had a read of the manual and I find the explanation quite difficult to grasp and also before I ride that particular learning curve there is still something about the serin [2000,nodata], pin, baud rate, data command that I'm not quite getting. but first I better explain what I'm trying to do.
I've built a circuit around a 20x2 that is going to control upto 8 signals for a model railway/road.
When a toggle switch on the control pannel is used this will via a resistor netowrk send a voltage to an adc input of a 08m, which will then give that reading a value and send it to several other circuits (of which my 20x2 is one) via a serout command. The 20x2 curcuit then uses this data to know which signal it is controlling, eg:
Code:
serin c.2, n1200_8,("ABC"),b0
if b0=1 then goto signal1
if b0=2 then goto signal2
etc
What I want the software to do is set the signal to green and then monitor an adc input for the choosen signal and also keep monitoring the serin command to see if any new data has arrived. This part of the code works by adding a gosub to a serin [timeout,return address] command.
When the adc has detected a change it then swaps the signal leds from green to red, wait abit, then red to yellow, wait some more and then finally back to green. But I want the code to keep going back to the serin command to see if any new data has arrived and the code should be controlling a different signal.
I can only get the serin [timeout,address] command to work for one part of the program?.
If I add another serin [timeout,address] command for a differnt stage of the program, the code just locks up and I can't see why that should happen.
I've proved that the hardware works fine, as long as I only use one serin [timeout,address] command, what am I doing wrong?

I've attached a block diagram and the code (so far) is below

Code:
symbol counter=w4
prestart:
b1 = %00000000 :gosub doit
b1 = %00000000 :gosub doit
b1 = %00000000 :gosub doit
pulsout c.4 ,10
pause 500

start:
serin c.2, n1200_8,("ABC"),b0
if b0=1 then goto signal1
if b0=2 then goto signal2
if b0=3 then goto signal3
if b0=4 then goto signal4
if b0=5 then goto signal5
if b0=6 then goto signal6
if b0=7 then goto signal7
if b0=8 then goto signal8
goto start

SIGNAL1:				   ;SET SIGNAL TO GREEN
counter=0                    	   ;SET COUNTER TO ZERO
b1 = %00100100 :gosub doit    ;DATA TO SHIFT REGISTER
b1 = %10010010 :gosub doit    ;DATA TO SHIFT REGISTER
b1 = %01001100 :gosub doit    ;DATA TO SHIFT REGISTER
pulsout c.4,10                       ;LATCH REGISTERS


MS1:                        	          ;MONITOR SIGNAL1'S SENSOR
readadc 1,b3                	  ;READ ADC1
if b3 <160 then goto S1r         ;IF INPUT IS DARK THEN CHANGE THE SIGNAL TO RED
goto CHECKSWITCHS              ;CHECK SERIN FOR NEW DATA
goto MS1                    	  ;KEEP LOOPING UNTIL INPUT CHANGES

S1r:                        	          ;CHANGE SIGNAL1 TO RED
b1 = %00100100 :gosub doit	  ;DATA TO SHIFT REGISTER
b1 = %10010010 :gosub doit	  ;DATA TO SHIFT REGISTER
b1 = %01001001 :gosub doit	  ;DATA TO SHIFT REGISTER
pulsout c.4,10                       ;LATCH REGISTERS
counter=0				  ;SET COUNTER TO ZERO

MS1r:					  ;MONITOR ADC1 FOR CHANGE WHILE SIGNAL IS AT RED
counter=counter+1		  ;COUNTER
if counter=100 then goto S1y	  ;AFTER SO LONG GOTO YELLOW ASPECT
readadc 1,b3                	  ;READ ADC1 AGAIN
if b3>160 then goto MS1r        ;IF INPUT IS LIGHT THEN GOTO YELLOW
goto S1r                	          ;LOOP UNTIL INPUT IS LIGHT OR COUNTER REACHS LIMIT


S1y:					  ;CHANGE SIGNAL TO YELLOW ASPECT
b1 = %00100100 :gosub doit	  ;DATA TO SHIFT REGISTER
b1 = %10010010 :gosub doit	  ;DATA TO SHIFT REGISTER
b1 = %01001010 :gosub doit	  ;DATA TO SHIFT REGISTER
pulsout c.4,10                       ;LATCH REGISTERS
counter=0				  ;SET COUNTER TO ZERO

MS1y:				  ;MONITOR SIGNAL1'S SENSOR 
counter=counter+1                ;COUNTER
if counter = 100 then goto signal1	;IF COUNTER REACHS LIMIT GO BACK TO GREEN
readadc 1,b3                	  ;READ ADC1 AGAIN
if b3<160 then goto S1r          ;IF INPUT IS DARK AGAIN THEN GO BACK TO RED

goto MS1y                    	  ;LOOP UNTIL COUNTER REACHS 100

CHECKSWITCHS:			  ;CHECK SERIN FOR NEW DATA,AFTER 2SEC RETURN TO MS1
serin [2000,ms1], c.2, n1200_8,("ABC"),b0
if b0=1 then goto signal1
if b0=2 then goto signal2
if b0=3 then goto signal3
if b0=4 then goto signal4
if b0=5 then goto signal5
if b0=6 then goto signal6
if b0=7 then goto signal7
if b0=8 then goto signal8
goto ms1


CHECKSWITCHS2:
serin [2000,MONITOR2], c.2, n1200_8,("ABC"),b0
if b0=1 then goto signal1
if b0=2 then goto signal2
if b0=3 then goto signal3
if b0=4 then goto signal4
if b0=5 then goto signal5
if b0=6 then goto signal6
if b0=7 then goto signal7
if b0=8 then goto signal8
goto ms1r


;SIGNAL TWO
SIGNAL2:
counter=0                    
b1 = %00100100 :gosub doit
b1 = %10010010 :gosub doit
b1 = %01100001 :gosub doit
pulsout c.4,10              


MONITOR2:
readadc 2,b3                         ;READ INPUT
if b3 <160 then goto red2        ;IF INPUT IS DARK THEN CHANGE THE SIGNAL
GOTO CHECKSWITCHS2
goto monitor2                        ;KEEP LOOPING UNTIL INPUT CHANGES

;RED & RED MONITOR
red2:                                   ;CHANGE THE SIGNAL TO RED
b1 = %00100100 :gosub doit
b1 = %10010010 :gosub doit
b1 = %01001001 :gosub doit
pulsout c.4,10                       ;LATCH REGISTERS

counter=0
MONRED2:
counter=counter+1
if counter=100 then goto yellow2
readadc 2,b3                       ;READ INPUT AGAIN
if b3>161 then goto yellow2   ;IF INPUT IS LIGHT THEN GOTO YELLOW

goto monred2                       ;LOOP UNTIL INPUT IS LIGHT

;YELLOW & YELLOW MONITOR
yellow2:
counter=0
b1 = %00100100 :gosub doit
b1 = %10010010 :gosub doit
b1 = %01010001 :gosub doit
pulsout c.4,10                     ;LATCH REGISTERS

MONYEL2:
counter=counter+1               ;START COUNTER
if counter = 100 then goto signal2
readadc 2,b3                ;READ INPUT AGAIN
if b3<160 then goto red2        ;IF INPUT IS DARK AGAIN THEN GO BACK TO RED

goto monyel2                        ;LOOP UNTIL COUNTER REACHS 100



SIGNAL3:
GOTO START

SIGNAL4:
GOTO START

SIGNAL5:
GOTO START

SIGNAL6:
GOTO START

SIGNAL7:
GOTO START

SIGNAL8:
GOTO START



doit:
for b0= 1 to 8
if b1 > 127 then high c.7 else low c.7
endif
pulsout c.5,10
b1 = b1 *2
next b0
return
 

Attachments

hippy

Ex-Staff (retired)
Have you tried running the code through the simulator to see where it is 'locking up' ?
 

westaust55

Moderator
The code is approaching spagetti code status and has some things that need to be looked into.

For example:
Code:
MS1:                        	          ;MONITOR SIGNAL1'S SENSOR
  readadc 1,b3                	  ;READ ADC1
  if b3 <160 then goto S1r         ;IF INPUT IS DARK THEN CHANGE THE SIGNAL TO RED
  goto CHECKSWITCHS              ;CHECK SERIN FOR NEW DATA
  goto MS1                    	  ;KEEP LOOPING UNTIL INPUT CHANGES
The last line will NEVER be actioned.



In this part of the code:
Code:
S1r:                        	          ;CHANGE SIGNAL1 TO RED
  b1 = %00100100 :gosub doit	  ;DATA TO SHIFT REGISTER
  b1 = %10010010 :gosub doit	  ;DATA TO SHIFT REGISTER
  b1 = %01001001 :gosub doit	  ;DATA TO SHIFT REGISTER
  pulsout c.4,10                       ;LATCH REGISTERS
 [COLOR="Red"] counter=0	[/COLOR]			  ;SET COUNTER TO ZERO

MS1r:					  ;MONITOR ADC1 FOR CHANGE WHILE SIGNAL IS AT RED
  counter=counter+1		  ;COUNTER
  if counter=100 then goto S1y	  ;AFTER SO LONG GOTO YELLOW ASPECT
  readadc 1,b3                	  ;READ ADC1 AGAIN
  if b3>160 then goto MS1r        ;IF INPUT IS LIGHT THEN GOTO YELLOW
  goto S1r                	          ;LOOP UNTIL INPUT IS LIGHT [COLOR="Red"]OR COUNTER REACHS LIMIT[/COLOR]
if b3 is <= 160 then you go to S1r which resets the counter to 0 (line in red) so likely you might never break out unless b3 is high which is not what the comment suggests.

As hippy says, try running your program in the PE simulator and see if it is doing what you want
The comments mught be more readavle in lower case - my eyes are saying "ouch!" :eek:

Some indentation of the structures within IF...THEN and loops would make the program easier to follow
 
Last edited:

Dippy

Moderator
You make a good point Westy, but are you on the 'pop' ?

"The comments mught be more readavle in lower case - my eyes are saying "ouch!" :eek:"

- so are mine.:)
 

Pauldesign

Senior Member
My 10 cents or pennies:

Is not just a serin problem but stack program.

Using multiple serin commands in cascade provided they're are used according to the syntax shouldn't be a problem.

The second serin and subsequent serins will not execute if the data to be received doesn't replicates what it should receive.

Using multiple gotos in one program is bad programming. I reckon you replace all the gotos with gosubs if since u're using 20x2 which doesn't supports parallel tasking. There should be only one goto and mostly at the top of the main program and the rest subroutines should be call using but gosubs. What you're experiencing is mostly stack errors.

After executing the first goto, it might work fine and the rest gotos will result to stack errors which will be reveal if simulated as suggested by the old legends. (old men say wise words, is it). Even if you just need to program a picaxe with toggle 0 command, please always simulate it first. Spending time in simulation now, saves hell of a time and frustration during debugging.

Also, if timeout occurs, execution will proceed to the address in the serin command and if the address is in an endless routine or the same routine that the program got stuck before, then you'll have an endless stack error loops.
If i were u, the address in the timeout must have a reset command, so that the program is always initialized back to the beginning not in an embedded stack.

Also, after if command is used, there must be endif and best else

Why use signals 1-8, which refers and point to the same part in the program.

Just one signal should be fine if they're all pointing to the same address.

You're confusing the the program flow with your method of coding and since your app requires lots of branching, it would be easier to start from scratch, re-define your problem and code it properly.

I've successively used 5 serin commands in cascades and 79 gosubs and it works like magic. ;)
 

BeanieBots

Moderator
@Pauldesign,
I think you may have got a little confused yourself:eek:
It is impossible to have a stack error even if your program is nothing but GOTO's.

You can only get a stack error with GOSUBs and only then if they are nested too deep or the GOSUBs and RETURNs are not correctly paired.

What do you mean by
Using multiple serin commands in cascade
?
You can have as many SERINs as you like in sequence. Program flow will simply move on once the required number of bytes have received.
 

Pauldesign

Senior Member
You're right and excuse my terminologies BB. You know English is so vast that some of the words have different meanings depending on what part of the world you're:D and what i meant to explain, is what you just explained ;).

By the way it's spring in Cape Town and during this winter to spring seasons transition, Capetonians always get confused and what do you expect when a confused guy is figuring out some sense in a confused code; Bang confusion.:p
 

sid

Senior Member
Thanks everyone for your ideas, I've taken the best and the result is good.
Firstly, I used the simulator and it is a very useful tool for showing you where the code is getting stuck, so I will use the simulator everytime I write a program from now on.
Secondly, your right the code was very messy, so I started again and kept it as simple as I could and kept running it in the simulator first before downloading into the axe.
Thirdly, I appologise for the capitals, but I like them.
I now have a working program :D and have posed the code below so others can learn from my mistakes.

To answer PaulDesigns question,"why write a seperate piece of code for each signal".
Imagine a station with for example 5 platforms, each platform has a track and all tracks converge into one track that leaves the station. Each track has a signal and each signal has a sensor (this was omitted from the block diagram for simplicity) When a route is set I want the signal for that particular track to be set to green and all the other signals set to red. I then want the program (as far as its possible to do) to constantly monitor the signals sensor and the input that changes which signal is to be controlled, regardless of which aspect (red.yellow,green) is lit.
I've also added a read/write comand so on powerup the program remembers which signal it was controlling.
The hardware is sitting beside me working away quite happily, so when I've finished I'll give it a proper write up and post the code, circuit and pcb design here http://www.stuartmoore-modelrailways.co.uk/Signal control.html so others can use it should they wish
Thanks once again to everyone who has helped me, the forum is an invaluble picaxe tool.

Code:
symbol counter=w4

powerup:
read 0,b2					;READ MEMORY ON POWER UP
if b2=1 then goto signal1
if b2=2 then goto signal2

start:
serin c.2, n1200_8,("ABC"),b0
if b0=1 then goto signal1
if b0=2 then goto signal2
goto start

SIGNAL1:					;SET SIGNAL TO GREEN
b2=1
write 0, b2					;WRITE SIGNAL TO MEMORY
counter=0                    		;SET COUNTER TO ZERO
b1 = %00100100 :gosub registers    	;DATA TO SHIFT REGISTER
b1 = %10010010 :gosub registers    	;DATA TO SHIFT REGISTER
b1 = %01001100 :gosub registers	;DATA TO SHIFT REGISTER
pulsout c.4,10    			;LATCH REGISTERS
           		
Monitor1:                        	;MONITOR SIGNAL1'S SENSOR
readadc 1,b3                		;READ ADC1
if b3 <160 then goto red1     	;IF INPUT IS DARK THEN CHANGE THE SIGNAL TO RED
gosub checkswitchs			;CHECK SERIN FOR NEW DATA
goto Monitor1                    	;KEEP LOOPING UNTIL INPUT CHANGES

red1:
b1 = %00100100 :gosub registers	;DATA TO SHIFT REGISTER
b1 = %10010010 :gosub registers	;DATA TO SHIFT REGISTER
b1 = %01001001 :gosub registers	;DATA TO SHIFT REGISTER
pulsout c.4,10                	;LATCH REGISTERS
counter=0
red11:
counter=counter+1
if counter=5 then goto yellow1
readadc 1,b3				;MONITOR SENSOR FOR INPUT
gosub checkswitchs			;MONITOR SWITCHS FOR CHANGE
if b3 <160 then goto red1
goto red11

yellow1:
b1 = %00100100 :gosub registers	;DATA TO SHIFT REGISTER
b1 = %10010010 :gosub registers	;DATA TO SHIFT REGISTER
b1 = %01001010 :gosub registers	;DATA TO SHIFT REGISTER
pulsout c.4,10                	;LATCH REGISTERS
counter=0
yellow11:
readadc 1,b3                		;READ ADC1
if b3 <160 then goto red1
counter=counter+1
if counter=5 then goto signal1
gosub checkswitchs
goto yellow11				



SIGNAL2:					;SET SIGNAL TO GREEN
b2=2
write 0, b2					;WRITE SIGNAL TO MEMORY
counter=0                    		;SET COUNTER TO ZERO
b1 = %00100100 :gosub registers    	;DATA TO SHIFT REGISTER
b1 = %10010010 :gosub registers    	;DATA TO SHIFT REGISTER
b1 = %01100001 :gosub registers	;DATA TO SHIFT REGISTER
pulsout c.4,10               		;LATCH REGISTERS

Monitor2:                        	;MONITOR SIGNAL2'S SENSOR
readadc 2,b3                		;READ ADC2
if b3 <160 then goto red2     	;IF INPUT IS DARK THEN CHANGE THE SIGNAL TO RED
gosub checkswitchs			;CHECK SERIN FOR NEW DATA
goto Monitor2                    	;KEEP LOOPING UNTIL INPUT CHANGES

red2:
b1 = %00100100 :gosub registers	;DATA TO SHIFT REGISTER
b1 = %10010010 :gosub registers	;DATA TO SHIFT REGISTER
b1 = %01001001 :gosub registers	;DATA TO SHIFT REGISTER
pulsout c.4,10                	;LATCH REGISTERS
counter=0
red21:
counter=counter+1
if counter=5 then goto yellow2
readadc 2,b3				;MONITOR SENSOR FOR INPUT
gosub checkswitchs			;MONITOR SWITCHS FOR CHANGE
if b3 <160 then goto red2
goto red21

yellow2:
b1 = %00100100 :gosub registers	;DATA TO SHIFT REGISTER
b1 = %10010010 :gosub registers	;DATA TO SHIFT REGISTER
b1 = %01010001 :gosub registers	;DATA TO SHIFT REGISTER
pulsout c.4,10                	;LATCH REGISTERS
counter=0
yellow21:
readadc 2,b3                		;READ ADC2
if b3 <160 then goto red2
counter=counter+1
if counter=5 then goto signal2
gosub checkswitchs
goto yellow21				



registers:
for b0= 1 to 8
if b1 > 127 then high c.7 else low c.7
endif
pulsout c.5,10
b1 = b1 *2
next b0
return 

checkswitchs:			;CHECK SERIN FOR NEW DATA,AFTER 2SEC RETURN TO MS1
serin [1000,rtn], c.2, n1200_8,("ABC"),b0
if b0=1 then goto signal1
if b0=2 then goto signal2
rtn:
return
 

Pauldesign

Senior Member
Glad to hear, you start from scratch and got it to work first using the simulator. :)

To answer PaulDesigns question,"why write a separate piece of code for each signal".
I was referring to the below section of your code in your first post (#1).

Code:
SIGNAL3:
GOTO START

SIGNAL4:
GOTO START

SIGNAL5:
GOTO START

SIGNAL6:
GOTO START

SIGNAL7:
GOTO START

SIGNAL8:
GOTO START
As you can see, SIGNAL3 to SIGNAL8 subroutines all point the program flow back to START. It will be better to just use one SIGNAL address: e.g
Code:
SIGNAL:
GOTO START
instead of 6, since they're pointing to the same address (START) and in your code just use but goto SIGNAL or except the GOTO START in all of them was a mistake and was meant to be something else. If that is the case then it makes sense for the SIGNAL addresses to be different as can be seen in your new code. Note, my explanation was based on your first post.

Using just SIGNAL helps optimize code, program memory and reduces bugs.

Nevertheless, if you reckon all is working as you wanted then Great and you're welcome for further questions. ;)
 
Top