Automating the Physical World with Linux, Part 1: Control Automation
This is the first of three articles introducing the field of control automation and its use with Linux. Control automation uses software applications to monitor and control the physical world. Software for control automation is similar to most software Linux users are already familiar with, but with a twist; an application's input and output variables are retrieved from and sent to external devices in the physical world. Combining software with variables from the physical world, we can automate lighting, temperature control, safety systems, power management, autonomous robots, elevator management and flight-guidance systems, to name a few.
Linux brings many of its known advantages to control automation. Source code availability allows a software package to be built on any supported architecture and to be improved by others. Multiple architecture and platform support allows machines from supercomputers to pocket-toted PDAs to run a common application, while the ability to pick and choose from a wide range of hardware platforms allows cost-efficient and precise system selection for each task. In short, Linux brings software availability, system availability and cost-effective platforms.
Control automation is a vast topic; we'll discuss key items to help you identify the strength of automated systems. In my experience, many simple functions can be easily automated, and these simple functions can be combined to build a much more complex system. Chances are that you can implement most automation tasks on a Linux system.
In this first article, I introduce basic concepts for adding automation to Linux's repertoire of features. This article introduces the two fundamental building blocks of control automation: the data acquisition hardware and the software control loop. These building blocks form the basis of all automation systems, whether simple or complex. We'll learn more about these building blocks in this article by designing two simple systems: a control system for water sprinklers and a system for controlling the temperature in a server room.
My approach is to introduce a simple, defined control automation task. As we progress, I'll introduce more complexity into these examples. Complex automation systems are built around a set of simple control automation tasks. So, let's get wet!
My home has a fairly large yard (at least by urban California standards) and maintaining the plants requires a sizable automatic sprinkler system. The yard is covered by 32 sprinkler zones (a zone is a section of sprinklers controlled by a single water valve). The automation task for the sprinkler system, which is implemented in a control strategy, is fairly straightforward: I want to turn each zone on at a specified time and day of the week for a given duration.
To implement this strategy requires two steps: add hardware to interface with the sprinkler system and develop an algorithm to express the control strategy in code. For the time being, we'll use generic examples for the hardware and language used.
Step 1: Add a hardware interface to give Linux a way to ``drive'' our system. Here, ``drive'' simply means the ability to push a command to the physical world (in our example, an electrically actuated water valve). For this interface, we'll use a data acquisition device that translates physical world signals to computer-tolerant ones, and vice versa. The water valve is a control point for the data acquisition device.
Step 2: Develop an algorithm that describes how the sprinkler valve needs to be controlled. For our sprinkler system, this algorithm mirrors how I personally control a sprinkler zone: I water the orange trees, for example, on Monday evenings at 5:00PM for 20 minutes. The other zones are similar, except that day, time and duration of watering are different.
The algorithm, shown in Listing 1 in C pseudo-code, is straightforward: our control application waits for a specific day of the week and time to turn on the control point for the water valve. The software loop turns the control point on for the defined watering duration and then disables it. This solution may be expanded to the other zones of the yard by replicating this simple control loop.
Step 3: (I guess there is a step 3.) Once the control system is implemented, forget about turning sprinklers on and off manually and enjoy the fruits of our work (literally, in the case of the orange trees).
There are a few things to know about our simplified control example. First, this type of system is called an open-loop system. The control application uses time as the system state. Time is not related to the actual moisture in the ground, so this means that strange things may occur, such as the sprinklers coming on while it's raining.
Another is the ``sleep for a while'' comment. This part of the program controls how fast the control loop is performed. If this line weren't here, our loop would check thousands of times per second, needlessly consuming a great deal of processor time. In effect, a delay slows the update rate. The update rate reflects the speed at which we inspect our conditions and update the results. An update rate of approximately one second is fairly reasonable in this example. Other derivatives of Linux kernels offer a different way of controlling this rate, but this method is simpler and will work on any Linux distribution.
Earlier we mentioned the data acquisition hardware that translates physical world signals into computer-readable signals. In the control automation business, this hardware is broadly referred to as I/O, for input/output. This usage can lead to some confusion until you get used to it; people outside control automation who would describe hard drive access as I/O, for example, might wonder when a control engineer says, ``We just got some new I/O.'' Fortunately, you'll also hear the less cryptic terms I/O unit and I/O system used the same way.
I/O units can interface with a huge number of devices to detect conditions such as temperature, humidity, voltage, wattage and current. This is the input side of I/O. For example, you could determine electrical breaker status, lighting, the presence of smoke, inclination, open doors, low voltage, bad batteries and so on. In short, almost any condition we experience in the physical world can be quantitatively measured through a data acquisition system.
I/O units can also send, or output, a signal to a device. Discrete or digital outputs are analogous to a switch: they turn something on or turn it off. Anything that you would recognize as a switch function is controlled by a discrete output. Continuous or analog outputs are a bit different. Analog outputs deliver an electrical signal that varies in level and can be compared with older style volume control knobs, i.e., the throttle on your car or a temperature setting on a stove. These functions operate where typically a proportion of command is required instead of all or nothing.
I/O hardware is classified as either local or remote. Local hardware is usually an adaptor card installed in a server's interface slot. (Note that I say ``server'' because computers used for device control are typically servers or otherwise dedicated systems.) Remote hardware is connected via a communications channel, historically ARCNET or serial (RS-232, RS-485 or RS-422). More recently, Ethernet has gained in popularity; we'll look at this in more detail shortly.
Local I/O hardware is typically an extension of the main processor's memory bus. Due to the local interface, these devices are capable of very fast access times. The processor simply needs to access a memory location to send or receive data to a board. Local I/O hardware has several disadvantages. First, the Linux kernel must have a device driver and a user application module that interfaces to the device. Both are either provided by the manufacturer or created by the developer, causing anxiety in many novice or inexperienced software developers. Another disadvantage to a local interface is that local devices are exclusively owned by the local server; that is, another system requesting data cannot easily access the device.
Recent trends in computer form factors make local I/O hardware difficult to install. Rack servers may not accept adaptor cards; although they may have expansion slots, it may be physically impossible to install cards due to the thin packaging. Internet appliances and embedded architectures do not offer any adaptor card expansion. The addition of a larger package and slot connectors dramatically increases the cost of manufacture and may make the device too large for the application.
In addition, maintenance of local I/O hardware is difficult. Any inspection of the card requires screws to be removed and possibly the card as well. While there are PCI architectures that are ``hot-swappable'' (hardware can be replaced without turning the system off), these machines are significantly more costly. If you don't have a hot-swappable server, then I/O hardware maintenance will require the server--and thus your control application--to be shut down. This doesn't work well if you also use your server for web serving, file serving or another dedicated function.
For our sprinkler example, I'll use a remote I/O unit that interfaces with the server over Ethernet (Figure 1). I'm avoiding a local adaptor card (Figure 2) because of the disadvantages discussed above. Both the I/O unit and the adaptor card happen to be made by my employer.
Figure 1. Remote I/O Unit with Ethernet Interface
Figure 2. Local Adaptor Card
Using Ethernet-based I/O hardware provides an additional layer of electrical isolation, which can be important when accessing lights, switches and other electrical devices in the physical world. If I accidentally short one of my server cards (that is, cause an electrical fault), I'm certain to destroy the rest of the server. With isolation, my server remains protected. In addition, I can maintain the hardware by disconnecting the patch cord, not turning off the server.
Another benefit of using Ethernet is that thin servers and dedicated internet appliances offer Ethernet connectivity, thus taking advantage of an already installed interface. Linux people use TCP/IP daily, usually without a second thought. There are also other advantages we'll discuss later in the series that make this a very popular and preferred interface.
Whether communicating with a local or remote I/O unit, a data protocol is used to define how an application sends data to and retrieves data from an I/O unit. Data protocols have historically been cryptic, as computationally limited devices need compact packets and easy parsing ability. However, while our selected I/O hardware has a data protocol, it has the advantage of using standard TCP or UDP sockets to transfer the data between client and server.
Writing your own library to handle the data protocol can be quite involved. Most manufacturers have documentation and software support for their data interfaces. For this I/O device, however, a small protocol library for the device shields the developer from having to deal with the cryptic data interface or even with TCP/IP sockets.
Unlike our earlier example of an open-loop system that was time-based, a system that actively reads the state of the system and attempts to correct it is called a closed-loop system. As an example, let's use my network server room, where I would like to stabilize the temperature. The input is the state of my system, temperature in this case. The output is the result that tells me to turn on a fan or a heater. The strategy is the method of computing the input to determine the output. The system's update rate can be fairly slow because most heating and cooling systems aren't capable of extremely rapid temperature changes.
Like the design approach for the sprinkler system, we'll start with a method similar to the way we would do it in our world. We would look at a temperature gauge and compare the temperature to our high and low limits. If it has reached one, we'll turn on the appropriate fan or heater to correct the room's temperature. Listing 2 has the algorithm to do this in C pseudo-code.
The function of this loop is to check whether the temperature I enter is above 70ºF. If so, it will tell me to turn on a fan. If I report a temperature that is below 65ºF, it will tell me to turn on a heater. Ideally, my logic is designed to keep the system temperature between my two limits. The speed at which this loop is computed is as fast as I can enter the current temperature.
Listing 3 shows the same control loop, this time including the hardware interface. It looks very similar.
In this first article I have discussed some basic automation concepts and introduced the two main building blocks of control automation: the data acquisition hardware and the software control loop. The software algorithms model the way we would control a sprinkler system or a server-room thermostat manually.
With additional data acquisition hardware, Linux is capable of monitoring and commanding our physical space. In turn, the addition of automation improves the safety, efficiency and capability in our lives by performing tasks for us.
In the next article, we'll introduce other areas where control exists, expanding our sprinkler system in the process.
Bryce Nakatani is an engineer at Opto 22, a manufacturer of automation components in Temecula, California. He specializes in real-time controls, software design, analog and digital design, network architecture and instrumentation. He can often be found digging trenches for his sprinklers. He welcomes your comments or questions and can be reached at firstname.lastname@example.org.