help with plc coding....

I don't really have the time to go through the program and test every permutation, but it looks reasonable. You will need to actually put it through its paces. I do see that a bunch of your subroutines have the colon before the name instead of after. That will need fixing.
 
Could someone check my plc coding? also any ideas to make it better would be appreciated.

Thanks.

Code:
---------------------------
leak1	   = digital input 1 = ip1 (Leak Sensor floor)
leak2	   = digital input 2 = ip2 (Leak Sensor dwv coupler #1)
leak3	   = digital input 3 = ip3 (Leak Sensor dwv coupler #2)
leak4	   = digital input 4 = ip4 (Leak Sensor dwv/cast iron coupler)
valve limit = digital input 5 = ip5 (Limit Switch red+white)
valve limit = digital input 6 = ip6 (Limit Switch black+white)
mail	    = digital input 7 = ip7 (Tilt Switch, when box door is closed is high)
valve close = output	    1 = op1 (SSR red+white)
valve open  = output	    2 = op2 (SSR black+white)
--------------------
ABOVE WON'T BE IN CODE JUST FOR EASIER REFERENCE.
-----------------------------------------------------
start
tsteq ip7 1
set ram7 1
tsteq ip7 0
callsub mail
tsteq ip1[2000] 1
callsub leak1
tsteq ip1[2000] 0
callsub rst1
tsteq ip2[2000] 1
callsub leak2
tsteq ip2[2000] 0
callsub rst2
tsteq ip3[2000] 1
callsub leak3
tsteq ip3[2000] 0
callsub rst3
tsteq ip4[2000] 1
callsub leak4
tsteq ip4[2000] 0
callsub rst4
end
mail:
tsteq ram7 1
email em7
set ram7 0
ret
leak1:
tsteq ram1 1
ret
set op1 1
email em1
tsteq ip5 1
delay[12000]
tstne ip5 1
delay[5000]
set op1 0
set ram1 1
ret
leak2:
tsteq ram2 1
ret
set op1 1
email em2
tsteq ip5 1
delay[12000]
tstne ip5 1
delay[5000]
set op1 0
set ram2 1
ret
leak3:
tsteq ram3 1
ret
set op1 1
email em3
tsteq ip5 1
delay[12000]
tstne ip5 1
delay[5000]
set op1 0
set ram3 1
ret
leak4:
tsteq ram4 1
ret
set op1 1
email em4
tsteq ip5 1
delay[12000]
tstne ip5 1
delay[5000]
set op1 0
set ram4 1
ret
rst1:
set op2 1
tsteq ip6 1
delay[12000]
tstne ip6 1
delay[5000]
set op2 0
set ram1 0
ret
rst2:
set op2 1
tsteq ip6 1
delay[12000]
tstne ip6 1
delay[5000]
set op2 0
set ram2 0
ret
rst3:
set op2 1
tsteq ip6 1
delay[12000]
tstne ip6 1
delay[5000]
set op2 0
set ram3 0
ret
rst4:
set op2 1
tsteq ip6 1
delay[12000]
tstne ip6 1
delay[5000]
set op2 0
set ram4 0
ret
 
Maybe RossW can optimize this using ANDB, ORB and XORB? With 3.02.15 firmware, you can use bitwise flag, so that one RAM can store up to 31 states.
 
Well, if the problem is adequately explained with:
* If any water sensor activates, close the valve until the limit switch operates and send an email
* if no water sensor has been active for at least (x) time, open the valve until the limit switch operates
* if the letterbox tilt switch operates, send an email

then I'd probably do something like this:
Code:
loop:
 or ip1 ip2 ram1 # either floor or coupler 1 active?
 or ip3 ram1 ram1 # add coupler 2
 or ip4 ram1 ram1 # and cast iron
 bz ram1 dry # are all inputs inactive?

			 # if we get here, something is wet.
 xor ip5 1 op1 # close valve until limit switch operates
 bnz ram2 ems # have we sent email yet?
 set ram2 1 # if not, set flag
 email em1	# and send message
ems:
 set ram3 cts # remember most recent time we were wet
 goto testmail

dry:
 add ram3 300 ram1 # Have we been dry more than 5 minutes?
 tstgt ram1 cts
 xor ip6 1 op2 # if more than 5 mins, close valve until limit switch operates

testmail:
 xor ip7 ram4 ram1 # has mail switch changed state?
 bz ram1 loop	# no change, nothing to do.
 tsteq ram4 0 ram4 # if ram4=0 this was a rising edge. Set ram4 and send email, otherwise ram4 was 1, falling edge, clear ram4.
 email em2
 goto loop
 
Hmm, just noticed - I don't reset the ram2 flag after everything is dry, so it won't notify you of a second "wet" event.
Could be fixed by changing code to be:
Code:
dry:
 add ram3 300 ram1 # Have we been dry more than 5 minutes?
 tstlt ram1 cts
 goto testmail
 xor ip6 1 op2 # if more than 5 mins, close valve until limit switch operates
 set ram2 0   # reset mail sent flag

testmail:
 
Maybe RossW can optimize this using ANDB, ORB and XORB? With 3.02.15 firmware, you can use bitwise flag, so that one RAM can store up to 31 states.

Sometimes, its better to just look at the problem. I could have optimized the code that was there as - but I think my proposed answer is far simpler and has far less (no) duplicated code to achieve the result??
 
wow, thanks.

however in testmail should the "ram1" be "ram4"?

Code:
testmail:
xor ip7 ram4 ram1 # has mail switch changed state?
bz ram1 loop # no change, nothing to do.
tsteq ram4 0 ram4 # if ram4=0 this was a rising edge. Set ram4 and send email,	 otherwise ram4 was 1, falling edge, clear ram4.
email em2
goto loop
 
wow, thanks.

however in testmail should the "ram1" be "ram4"?

No. The XOR IP7 RAM4 RAM1 is detecting a "change of state".

If RAM4 was 0 and IP7 is NOW 1, then RAM1 is set to 1.
The branch instruction after that just checks if ram1 was zero or not. Ie, if there was a change of state.
If ram1 was zero, it means either:
( a ) IP1 = 1 AND RAM4 = 1
or ( b ) IP1 = 0 AND RAM4 = 0

So after the bz ram1 loop
we only get to execute more instructions if RAM4 and IP7 are different (ie, IP7 just changed state)

If IP7 just changed state, its either gone from low-to-high (leading edge), or high-to-low (trailing edge)
You only want an email notice when ip7 goes high... so if RAM4 = 0, then IP7 just went high.
In that case, we send the email. And since RAM4=0, the tsteq will also set RAM4 true.
If RAM4 *WAS* true, it won't be 0, and the test will set RAM4=false (0) and skip over the email instruction, thus achieving in one step setting or resetting the flag, and sending email only on setting the flag.
 
ok, i get it, but actually ip7 will always be high until the door is opened because of how i had to mount the sensor. should I just reverse it via the web interface?
 
ok, i get it, but actually ip7 will always be high until the door is opened because of how i had to mount the sensor. should I just reverse it via the web interface?

Inverting the input is actually more "logical" in this case, rather than trying to remember which inputs are active high, and which are active low.

But the code could be inverted easily enough either way:

Code:
testmail:
 xor ip7 ram4 ram1 # has mail switch changed state?
 bz ram1 loop   # no change, nothing to do.
 tsteq ram4 1 ram4 # if ram4=1 this was a negative-logic rising edge. Set ram4 and send email
 email em2
 goto loop
 
do I put the "end" after the "loop" section?

Yes, you will need a Start before the start, and an End at the end.
You may even choose to make it sit and wait until it synchronises to the network time....

You *MAY* also choose to initialize variables before the main loop too if you want to ensure it will behave in some particular regard. For example, initializing ram3 if you want it to notify you of a "wet" condition instantly or not...
Code:
START
sync:
	 tsteq CYEAR 2011
	 goto  sync		# wait until time is synchronised
	 sub cts 400 ram3

loop:
......

END
 
no I meant do the other subroutines go after an "end". Or are they all inside of the "start ---> end

I've never worked with this type of coding.

thanks for your help
 
no I meant do the other subroutines go after an "end". Or are they all inside of the "start ---> end

There are no subroutines in the code I offered.
I am STRONGLY against the misuse of subroutines. Putting them in "just because you can" does nothing to help anyone. Unless they are code that you can (and do) re-use, and unless there is a particular benefit (for example, readability), there just isn't any justification for them.
 
Back
Top