Despite being a text-only system, a diagrammatic approach to system design can greatly aid the plcLib software development process. One of the surprising features of PLC-style programming is that block diagrams, logic diagrams and even certain types of electronic circuit diagrams, may easily be translated into equivalent program code – and it comes as an even greater surprise when it is discovered that they actually work!
A further advantage of diagrammatic system design is that it supports iterative development. Hence a simple system may be rapidly developed and tested, and then progressively enhanced. Consider the example of a simple alarm system, as illustrated by Figure 1.
The system has three alarm sensors, X0–X3, which are combined using an inclusive-OR gate. Hence the output of the OR gate is high if one or more of the sensor inputs is high. This in turn becomes the input of a Set-Reset latch, whose output, Y0, goes high, and stays high, when triggered by the output of the OR gate, and which is cancelled by the Reset input of X3. The equivalent JavaScript version of the sketch is shown in Listing 1.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// Simple Alarm OR0 = new FunctionBlock(); // OR Function block variable function setup() { } function loop() { orFB(OR0, X0, X1, X2); // Read sensor inputs din(OR0); // Read Set input from sensors latch(Y0, X3); // Q = Output Y0, Reset = X3 } |
Listing 1. A simple alarm circuit with three sensor inputs, a reset input and an alarm output (Source: Apps > Alarm).
Notice that the inclusive-OR gate has been implemented using an orFB function block command, with the output stored in the OR0 variable. This could also have been coded using an instruction-list coding style by using a din command followed by a couple of orBit commands, and finally a dout command to the chosen output variable. (See the Logic > RepeatedOrToVariable example on the ‘live’ system for more details.) Either way, the OR0 variable becomes the set input to the latch.
This simple circuit is not perfect however. A useful addition would be to add a visual deterrent, in the form of a flashing Armed LED. This will flash briefly and repeatedly when the system is enabled, but not yet triggered. A modified system diagram is given in Figure 2.
The equivalent JavaScript version of the sketch is shown in Listing 2.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// Alarm with Armed Status Indicator OR0 = new FunctionBlock(); // OR Function block variable WAVE0 = new Waveform(); // Pulse waveform for timerCycle function setup() { } function loop() { orFB(OR0, X0, X1, X2); // Read sensor inputs din(OR0); // Read Set input from sensors latch(Y0, X3); // Latch Q = Y0, Reset = X3 dinNot(X3); // Enable input (0 = enable) timerCycle(WAVE0, 1900, 100); // Repeating pulse 1.9 s low, 0.1 s high andNotBit(Y0); // Disable Armed if alarm is triggered dout(Y1); // Armed pulse on output Y0 } |
Listing 2. An alarm circuit which adds a flashing Armed status indicator to the simple alarm (Source: Apps > AlarmArmed).
The timerCycle command is configured to produce a 0.1 second pulse, which repeats every 2 seconds, when activated by its enable input. An inverter, implemented by a dinNot command, ensures the cycle timer is enabled under the correct conditions. Similarly, an AND gate with a single inverted input, achieved using an andNotBit command, causes the repeating pulse to be visible on the Armed output, provided the alarm has not been triggered. For simplicity, these simple ‘glue logic’ functions have been implemented using instruction list style statements, rather than logical function blocks and associated variables.
Aside: The term glue logic dates back to early 8-bit microprocessor-based system design, where unused logic gates on TTL ICs would be used to implement functions such as chip select logic and even address decoding. This frugal use of existing capacity saved the additional cost of adding dedicated ICs.
However the improved system is still not perfect. In the real world, alarms which run continuously are often ignored, in addition to being a considerable nuisance! A further improvement would therefore be the addition of an alarm timeout, as shown in Figure 3.
The above system adds an on-delay timer, whose input is driven by the alarm input, and which cancels the alarm once the configured timeout period, of 10 seconds in this case, has passed. The equivalent JavaScript version of the system is given in Listing 3.
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 |
// Alarm with Armed Status Indicator and Timeout OR0 = new FunctionBlock(); // OR Function block variable WAVE0 = new Waveform(); // Armed pulse waveform for timerCycle TIMER0 = new Timer(); // On delay timer for timeout (10 s) RESET = new Auxiliary(); // Reset status TIMEOUT = new Auxiliary(); // Timeout status function setup() { } function loop() { orFB(OR0, X0, X1, X2); // Read sensor inputs din(OR0); // Read Set input from sensors latch(Y0, RESET); // Latch Q = Y0, RESET = (X3 OR TIMEOUT) dinNot(X3); // Enable input (0 = enable) timerCycle(WAVE0, 1900, 100); // Repeating pulse 1.9 s low, 0.1 s high andNotBit(Y0); // Disable Armed if alarm is triggered dout(Y1); // Armed pulse on output Y0 din(Y0); // Read Alarm output Y0 timerOn(TIMER0, 10000); // 10 second alarm timeout delay dout(TIMEOUT); // Output to TIMEOUT din(TIMEOUT); // Read alarm timeout status orBit(X3); // OR with Reset switch X3 dout(RESET); // Reset alarm if X3 pressed OR alarm timeout } |
Listing 3. An alarm circuit which adds an alarm timeout to the alarm with flashing Armed status indicator (Source: Apps > AlarmArmedTimeout).
Notice that the latch is now reset if either the Reset input (X3) is triggered, or the on-delay timer has finished. This is implemented using the orBit command near the end of the above listing.
While the addition of a timeout is certainly an improvement, many false alarms are triggered by faulty sensors. A final improvement is to make the three input sensors edge triggered. This will effectively disable any sensor which is still in the ON condition when the alarm is reset after an alarm timeout. The resulting final system diagram is given in Figure 4.
The associated JavaScript version of the sketch is given in Listing 4.
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 |
// Alarm with Armed Status Indicator, Timeout and Isolation of faulty inputs OR0 = new FunctionBlock(); // OR Function block variable WAVE0 = new Waveform(); // Armed pulse waveform for timerCycle TIMER0 = new Timer(); // On delay timer for timeout (10 s) RESET = new Auxiliary(); // Reset status TIMEOUT = new Auxiliary(); // Timeout status P0 = new Pulse(); // Create a pulse object ‘P0’ for input X0 P1 = new Pulse(); // Create a pulse object ‘P1’ for input X1 P2 = new Pulse(); // Create a pulse object ‘P2’ for input X2 function setup() { } function loop() { din(X0); // Read sensor connected to input X0 and P0.inClock(); // connect it to the clock input of P0 din(X1); // Read sensor connected to input X1 and P1.inClock(); // connect it to the clock input of P1 din(X2); // Read sensor connected to input X2 and P2.inClock(); // connect it to the clock input of P2 orFB(OR0, P0, P1, P2); // Read sensor pulse inputs din(OR0); // Read Set input from sensors latch(Y0, RESET); // Set latch from sensor rising edges dinNot(X3); // Enable input (0 = enable) timerCycle(WAVE0, 1900, 100); // Repeating pulse 1.9 s low, 0.1 s high andNotBit(Y0); // Disable Armed if alarm is triggered dout(Y1); // Armed pulse on output Y0 din(Y0); // Read Alarm output Y0 timerOn(TIMER0, 10000); // 10 second alarm timeout delay dout(TIMEOUT); // Output to TIMEOUT din(TIMEOUT); // Read alarm timeout status orBit(X3); // OR with Reset switch X3 dout(RESET); // Reset alarm if X3 pressed OR alarm timeout } |
Listing 4. An alarm circuit which adds faulty sensor isolation to the existing alarm timeout and flashing Armed status indicator features (Source: Apps > AlarmArmedTimeoutIsolate).
The three pulse objects, P0–P3, are configured to detect the rising edges of their respective inputs X0–X3. Objects P0–P3 are then used as inputs to the three-input orFB function block, which in turn drives the Set input of the latch. An alarm sensor input signal will now be active for a single scan cycle, but this is enough to trigger the alarm. However the alarm will not be automatically retriggered, should this same sensor still be active following an alarm timeout, unless the sensor input first goes low and then high again.
There are many further enhancements that could be made to the alarm, but those are left to the reader’s imagination!
Pros and Cons
It is useful at this point to review the advantages and disadvantages of this diagrammatic design approach, taking into account the outcomes achieved. Can this method be applied to other design problems, for example, and if so what types?
Main characteristics and conclusions are summarised below.
- A diagrammatic approach to system design with plcLib is capable of being used for rapid application development, where applicable, with the added potential for iterative enhancement of system features. This is despite the fact that plcLib is not itself a graphical software development environment.
- Examination of the four design iterations demonstrates a high degree of design/code reuse between versions.
- The final version of the alarm application uses six rectangular function blocks (of four different types), plus a further four logic gates, one of which is itself implemented as a function block. Hence this is a relatively high level design approach, when viewed from the perspective of the number of separate design elements needed, compared to the operational complexity of the system produced.
- Each function block produces an identifiable ‘behaviour’ in the system generated. Hence the graphical design approach is likely to be applicable where system operation may be described in terms of common electronic system elements, such as those supported by the plcLib library. These include analogue and digital inputs, outputs, latches, time delays, counters, shift registers, pre-defined functions, finite state machines, and simplified parallel programming.
- The availability of low cost microcontroller hardware, means that this approach may be applicable in many scenarios where a traditional PLC would be too large or too expensive.
FBD Comparisons
One common design approach used with traditional PLCs is the Function Block Diagram (FBD). There are obvious similarities to the approach presented here, but also some differences, which are peculiar to the more ‘hybrid’ approach of plcLib.
Standards-based FBD designs are more strictly presented as a series of interconnected rectangular blocks. Each rectangular block has a meaningful title at the top, with named inputs at the left and named outputs at the right. Signals generally flow from left to right via ‘wires’. Each connecting wire has an associated data type, but there may be small differences of implementation between PLC manufacturers. For example, different types of interconnecting signal may be shown with different type of line. Thus, interconnection of Boolean values could be shown using dotted lines, while integer values might use solid lines. The FBD implementation would then restrict the types of input and output which are allowed to be interconnected.
The plcLib system diagrams presented here use Boolean interconnections only, so there is no need to use different line types. However, this is certainly an option for the future.
Named wire labels are used where a particular node is reused by other system elements. In simple terms, a preceding command stores its result in a named variable, or object property, and subsequent commands use this value as a named input.
Rectangular blocks are used by the majority of plcLib function blocks, although logic gates are shown using the ‘distinctive’ logic symbols, rather than rectangular types. This is for three key reasons. Firstly, it helps to keep the diagrams compact, for display on a web page. Secondly it makes them easier to read and understand by readers with a general electronics background – and the distinctive symbols are of course more widely known. Thirdly, the plcLib library can implement Boolean operations using either function blocks, or by using equivalent instruction list style coding. The diagrams do not not make any assumptions regarding the underlying implementation approach. In general, the simplest approach is the one which is used.
Finally, the level of error checking is minimal in plcLib, compared to that provided by a FBD-based graphical user interface. Inappropriate connections may (or may not) generate compile time errors. In practice, knowledge of correct and incorrect design is gained by experience. Once operational, block diagram-based systems lend themselves to structured fault-finding and testing approaches, which can greatly simplify the task of demonstrating correct system operation.
Final Thoughts
Hopefully, this alarm-based case study has illustrated the value of block diagram-based system development, even for a text-based library such as plcLib. The approach is also well suited to incremental development, with additional features being progressively added, until the final system is realised.
The system diagrams presented here are ‘bespoke’, but are capable of being adapted to more closely resemble the Function Block Diagrams used with traditional PLCs, should that be desired.
Finally, it should be noted that alternatives to block diagram-based design do exist! One popular approach is the Finite State Machine (FSM), which will be the subject of one or more future posts. In the meantime, you may be interested to study the four equivalent FSM-based alarm examples, which are available in the FSM menu area of the ‘live’ system.