The plcLib library implements a scan cycle which has some similarities – and also some important differences – to the traditional scan cycle of an industrial PLC. The scan cycle is defined as the repeating process of reading inputs, performing calculations and updating outputs.
The scan cycle of a PLC takes place in well defined phases, and may be driven by a regular repeating signal, as shown below.
Precise details will vary with PLC implementation, but in a simple example, a scan cycle might be triggered at regular intervals by a repeating pulse – for example every 20 milliseconds, or 50 times per second. The PLC would begin the scan cycle by reading all physical inputs and storing values in an input table. In theory, the PLC then has a consistent set of inputs to operate on, for the next phase in the scan cycle. This is performing calculations and related actions, based on values stored in the input table. Any output values are written to an output table, in readiness for the final step, which is updating of the physical outputs. This in turn guarantees that each output is updated once only, in each scan cycle. The remainder of the scan time is free for other background tasks, idle time, or might even be partitioned to allow operational of other programs, which operate in parallel to the single program scan cycle being considered here.
The PLC is obviously designed to be a very robust device, and is intended to operate in harsh physical and electrically noisy environments. PLC inputs and outputs tend to operate at relatively low speeds, so the scan time of 20 ms, from the earlier example, might be more than adequate. Even so, computers do sometimes crash, either due to software bugs, or extreme environmental conditions – and PLCs are no exception!
An extra layer of protection might be a watchdog timer, which automatically resets the PLC if it doesn’t receive its regular “all is well” signal from an associated background task running in the scan cycle. Technically, the watchdog timer might have a timeout of, let’s say 100 ms, and the scan time would contain a clear watchdog timer command. If the scan cycle stops running for any reason, then the watchdog timer ‘times out’, and a reset is initiated. Activation of the watchdog timer is clearly an operation of last resort, and something that would need to be further investigated.
Note: Many microcontrollers have a built-in watchdog timer capability, including the ATmega328P used inside the Arduino Uno. The current plcLib version does not implement this feature, but it may be considered in future.
The plcLib scan cycle is considerably simpler than that of the traditional PLC, as shown below.
The plcLib software uses direct input/output, so inputs are read immediately, related processing is carried out and then outputs are directly updated. This happens on a rung by rung basis, as shown in the above ladder diagram extract. There are pros and cons to both approaches, which will now be considered.
The first advantage of direct I/O is simplicity, as there is no need for input or output tables, which in turn reduces the memory footprint. However, the user is still free to adopt an equivalent coding style, in which inputs are read to variables, processing takes place on these variables and then values are written to the outputs at the end of the scan cycle.
An example where direct I/O could give an unexpected output, would be the use of linked setL (set Latch) and resetL (reset Latch) commands, operating directly on the same output. All works well until both inputs are pressed simultaneously. The first command turns the output on, while the second turns it off again, so an oscillation is observed on the output. A potential scenario would be a momentary action push button, used to enable an output, and a second switch used to disable it. If the start button became physically jammed in the on position, then the user might struggle to disable the system, short of physically turning it off. This can easily be overcome by using a buffer variable, as shown in the following example.
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 |
// Using setL and resetL commands with output via an Auxiliary // Outputting via an intermediary variable avoids oscillation when // S = R = 1, which is associated with direct output. The last command // (resetL in the example below) is the one which ‘dominates’. myLatch = new Auxiliary(); function setup() { } function loop() { din(X0); // Read switch connected to digital input X0 (Set input) setL(myLatch); // Set latched output to 1 if X0 = 1, // leave output unaltered otherwise din(X1); // Read switch connected to digital input X1 (Reset input) resetL(myLatch); // Reset latched output to 0 if X1 = 1, // leave output unaltered otherwise din(myLatch); // Read latched variable dout(Y0); // Output to Y0 } |
Listing 1. Using a buffer variable to avoid output oscillation when setL and resetL commands are simultaneously applied (Source: Latch > SetResetCommandsAuxiliary).
The sequence of setL followed by resetL results in the reset operation taking precedence, which might be desirable if these corresponded to start and stop signals, respectively. Alternatively, the setL and resetL commands could be replaced by a single latch command, which is inherently reset-dominant, and which would then eliminate the need for a buffer variable.
Traditional PLC programmers might be thinking ‘game over’ for direct I/O at this point, but it is actually not so clear cut! Race conditions in bistable electronic circuits are nothing new, and methods of overcoming those problems are well known. (Study the operation of the SR bistable, made from cross-connected NAND or NOR gates, for example.)
A second look at the above problem, reveals that it has at least one potential application, as shown in the following example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// Bare Minimum – Single bit digital input and output // with repeating scan loop pulse on Y1 // The repeating pulse on Y1 can be connected to an // oscilloscope to find the period T and hence // frequency F of the scan loop, where F = 1/T. AUX0 = new Auxiliary(1); // AUX0 = 1 function setup() { } function loop() { din(AUX0); // Send pulse to Y1 at start of scan loop setL(Y1); // Y1 = 1 resetL(Y1); // Y1 = 0 din(X0); // Read digital input X0 dout(Y0); // Send to digital output Y0 } |
Listing 2. Using setL and resetL commands to measure the speed of the scan cycle (Source: Extras > ScanLoopSpeedTestBareMinimum).
In this case, an auxiliary variable is pre-configured to have a value of 1, which then triggers the following setL and resetL commands, with the resulting brief pulse being written to an unused digital output. If this is displayed on a oscilloscope, then it becomes possible to measure the period of the plcLib scan cycle, as shown below.
The above example adds a timing pulse to an unused output of the BareMinimum example, which in normal operation reads a single digital output and sends the result to an associated digital output. Taking the reciprocal of the period gives a frequency of approximately 25,000 scan cycles per second, which is considerably faster than the earlier example of a traditional PLC, having a fixed scan time. Higher speed is a second advantage of direct I/O, although it does reduce (relatively linearly) as more commands are added to the scan cycle.
The next thing to consider is the input signals themselves. Firstly, what is the minimum duration of a momentary input, which guarantees that it is ‘seen’ by the input scanning process? To answer this, the external inputs are assumed to be entirely asynchronous to the scan cycle, so they must be applied for a minimum of one scan cycle. Hence plcLib can handle briefer input pulses, due to its higher operating speed, which is a potential third advantage, depending on the application. (However, connection of external switches would tend to nullify part of this speed advantage, due to the need to add switch debounce logic.)
A second input signal question relates to ‘glitches’, which are defined here as transitory and spurious input signals which might cause incorrect operation of related systems. Given that inputs are asynchronous, as discussed previously, then the best way to ensure a consistent set of input signals at the start of the scan cycle is to capture all of the digital inputs simultaneously. This may be achieved using a latch circuit with an edge-triggered Clock signal, as shown in the following illustration.
Hopefully, a PLC would implement a similar approach, which may be confirmed from the user documentation, or by studying the schematic, if available. Arduino-based microcontrollers on the other hand, use single bit digital input via the Arduino digitalRead command (also used internally by din and its variants), so each digital input would be read at a slightly different time. Hence if digital inputs are changing asynchronously, then an Arduino-based system would be more prone to input glitches. Many microcontrollers actually implement port-based I/O behind the scenes, however, the mapping of ports and I/O pins is unlikely to be consistent across different hardware platforms. Hence this is an aspect where a traditional PLC, running on dedicated hardware, is likely to fare better than an Arduino-based microcontroller running on multiple hardware platforms.
A similar situation exists for digital outputs.
The position with synchronisation of analogue inputs is even worse. In an ideal world, a microcontroller with multiple analogue inputs would have a dedicated Analogue to Digital Converter (ADC) for each channel, hence allowing fully parallel operation. In practice, a low cost microcontroller is likely to have a single ADC, which is connected to multiple analogue inputs via a multiplexer. This multiplexer acts like a rotary switch, connecting one of the inputs to the internal ADC at any time. The input to the ADC also uses a small capacitor, which holds a copy of the input voltage, which has been read via a sample and hold circuit. A small settling time may be needed after changing analogue channels, to recharge the capacitor, otherwise the analogue value obtained may not be fully accurate. The plcLib software does not impose any specific settling delay, after changing channels, as this is likely to be application specific. It is recommended that users consult the microcontroller data sheet for details of specific requirements, particularly where multiple analogue inputs are being used.
Issues and Challenges
Hopefully the above discussion has made it clear that “obtaining a consistent set of inputs to operate on, for the next phase in the scan cycle” is not quite as straightforward as it at first appears!
If inputs to the system cannot always be guaranteed to have been obtained simultaneously, or to be glitch free, then any subsequent processing of inputs cannot always be guaranteed to be accurate! In practice, inputs tend to change much more slowly than the processing speed of the application, so are static most of the time. Systems are also chosen (or designed) to be insensitive to momentary glitches, so incorrect operation is not generally a problem.
Results of calculations often rely on the order of operations. A latch command, for example may implement a set function first, followed by a reset, as seen earlier. It is the last operation which actually gets written to the digital output, hence making the latch reset dominant. A set dominant latch could easily be created, simply by swapping the order of operations.
While this approach is valid, and widely used, a potential issue in user programs is where the same output has been unintentionally written to more than once. The first occurrence will not be seen on an output, due to the second command. However this first case may represent a latent bug. Subsequent removal or modification of the second command, possibly by a different programmer, several years later, may cause the latent bug to become active. The direct output approach used by plcLib reduces the chances of latent bugs, given that writing to an output twice is more likely to create an actual visible effect on an output.
Research indicates that the cost of undiscovered bugs in software increases the later they are discovered in the development cycle – potentially by up to 100 times! Indeed the cost of software bugs is sometimes even greater than financial, with faulty software known to have contributed to loss of life in multiple airplane crashes, to give just one scenario.
Conclusions
The direct I/O approach used in the plcLib scan cycle is simpler and faster than the buffered I/O approach used in a typical PLC. Potential errors due to direct updating of outputs do exist, but can be mitigated with careful design. Obtaining a consistent and glitch free set of inputs is challenging, and this relates in part to hardware design, and also to the bit-oriented nature of input-output commands used by Arduino compatible microcontrollers. Applications should be chosen, or designed, to be insensitive to momentary glitches on inputs or outputs, and use with mission critical applications should be avoided.