Linux-Based PLC for Industrial Control

What Linux is doing for the highly proprietary embedded systems market is what the PuffinPLC will do for industrial automation.
Embedding the PuffinPLC

The PuffinPLC makes liberal use of memory, inconsistent with a program that will be run in embedded applications. Two main areas need to be augmented to fulfill this requirement: the configuration file parsing library and the gmm.

Currently, in a running PuffinPLC with five modules, all five modules will parse the configuration file and load it into memory. Once there, the relevant data for the module will be copied into its internal data structures. This, and the existence of the configuration file, leads to very poor use of memory.

This situation will be rectified by requiring the modules to store their internal state in the configuration memory. This will allow the modules to be broken into two independent processes. The first will parse the configuration file, allocate enough memory from the cmm for its internal state variables and initialize this memory. The second process asks the cmm for the location of its initialized state variables and then executes the module logic. The first process may be run on the developing platform and is not required to run in the target platform. We have to make a copy of the already-initialized configuration memory for the target platform. This removes the requirement for the configuration file and the multiple copies of its parsed form in the target platform's memory.

The second area that needs to be augmented is the gmm. The current architecture makes sense if we want to take full advantage of the capabilities of the underlying OS. Unfortunately, this requires multiple copies of the memory map (i.e., a global memory and a private memory map for each module). In many situations, end users will not require these capabilities and will have the modules synchronized to run in lockstep, one after another. In this case, a single process may suffice. We are planning on expanding the methods of accessing the global memory map, such as dispensing with private memory maps and accessing the global memory map directly. Eliminating the need to synchronize the memory maps will save memory and increase speed. On the other hand, it will mean the modules must be run in lockstep, one after another, to preserve the PLC semantics.

PuffinPLC Modules

We are well on our way toward completing several basic modules that will provide the standard capabilities of PLCs. While some will be running user-defined logic, others will be communicating with the real world. Logic-based modules will provide support for specific PLC programming languages (e.g., IEC compiler) and commonly executed functions (e.g., dsp). I/O modules all take PuffinPLC points and either transmit them over a network using a specific protocol (e.g., modbus) or turn them into real, electrical signals that move cylinders and motors (e.g., DIO48). They may also take electrical signals from devices such as buttons and proximity switches and turn them into PuffinPLC points.

The IEC Compiler

The IEC 61131-3 language compiler is not yet fully functional. This compiler will compile IEC ST (structured text) and IL (instruction logic) programs into C++ modules. Each compiled program will be an independent PuffinPLC module. Debugging support will probably be provided by an IEC language interpreter.

The IL compiler is a Perl-written compiler of a nonstandard, simple instruction logic language. This language provides only basic logic operations (e.g., LOAD, AND, OR, OUT) and is intended as a stop-gap until the IEC compiler is working, allowing for easier testing of other PuffinPLC components.

The dsp Module

The digital signal processing (dsp) module provides signal-handling capabilities. The dsp module itself is composed of submodules or blocks that implement basic signal-processing algorithms. The user can string these submodules together to implement the desired functionality.

Currently we have adder, PID, filter, alarm, ramp, nonlinear and type conversion blocks. In the future, we expect to have multiplier, hysteresis, FFT, delay and signal source blocks. The dsp module executes the blocks in the same order in which they are configured.

All blocks except the type converter expect inputs to be in 32-bit, floating-point format and provide output in the same format. The type converter can convert data to/from (unsigned) integers of several sizes, from/to 32-bit, floating-point format. The adder adds a variable number of inputs, each scaled by a configurable constant, to provide a single output. The PID block provides an open-loop PID (proportional, integral, derivative) controller. Closed-loop controllers can be implemented by closing the loop with an adder block. The PID block does not assume fixed period scans of the dsp module, as it takes into account the elapsed time between every two successive scans.

The filter block implements infinite impulse response (IIR) and finite impulse response (FIR) filters using canonical, second order sections. These filters can be configured directly or by giving the desired frequency and attenuation response, along with the desired analog transfer function type (butterworth, chebyshev, elliptic, bessel). This block, unlike the PID, assumes fixed period scans of the dsp module.

The alarm block allows Boolean alarms to be set depending on the input value. This block supports alarm activation when the input value is larger than, less than, equal to or different from a specified constant.

The ramp block provides an output that follows the input but whose maximum first and second derivatives may be limited. Maximum positive and negative derivatives may be set independently.

The nonlinear block implements dead-band and limiting functions.