1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
component estop_latch "Software ESTOP latch";
description """
This component can be used as a part of a simple software ESTOP chain.
It has two states: "OK" and "Faulted".
The initial state is "Faulted". When faulted, the
.B out-ok
output is false,
the
.B fault-out
output is true, and the
.B watchdog
output is unchanging.
The state changes from "Faulted" to "OK" when
.B all
these conditions are true:
.RS
.IP \\(bu
.B fault-in
is false
.IP \\(bu
.B ok-in
is true
.IP \\(bu
.B reset
changes from false to true
.RE
When "OK", the
.B out-ok
output is true, the
.B fault-out
output is false, and the
.B watchdog
output is toggling.
The state changes from "OK" to "Faulted" when
.B any
of the following are true:
.RS
.IP \\(bu
.B fault-in
is true
.IP \\(bu
.B ok-in
is false
.RE
To facilitate using only a single fault source,
.B ok-in
and
.B fault-en
are both set to the non-fault-causing value when no signal is connected.
For estop-latch to ever be able to signal a fault, at least one of these
inputs must be connected.
Typically, an external fault or estop input is connected to \\fBfault-in\\fR,
\\fBiocontrol.0.user-request-enable\\fR is connected to \\fBreset\\fR,
and \\fBok-out\\fR is connected to \\fBiocontrol.0.emc-enable-in\\fB.
In more complex systems, it may be more appropriate to use classicladder to
manage the software portion of the estop chain.
""";
pin in bit ok_in = true;
pin in bit fault_in = false;
pin in bit reset;
pin out bit ok_out = false;
pin out bit fault_out = true;
pin out bit watchdog;
function _ nofp;
option data estop_data;
license "GPL";
author "John Kasunich";
;;
typedef struct { int old_reset; } estop_data;
FUNCTION(_) {
/* check inputs */
if ( ok_in && !fault_in) {
/* no fault conditions, check for reset edge */
if ( reset && !data.old_reset ) {
/* got a rising edge, indicate "OK" on outputs */
ok_out = 1;
fault_out = 0;
}
if( ok_out ) {
/* toggle watchdog */
watchdog = !watchdog;
}
} else {
/* fault condition exists, trip */
ok_out = 0;
fault_out = 1;
}
/* store state of reset input for next pass (for edge detect) */
data.old_reset = reset;
}
|