Contact and Coil | Nearly In Control

TAG | plc

This information is for a Fanuc R30-iA, RJ3-iA or RJ3-iB controller but might work with other ones.

If you’re looking for a way to send the robot world TCP position (X, Y, Z, W, P, R) over to the PLC, it’s not actually that difficult. The robot can make the current joint and world position available in variables, and you can copy them to a group output in a background logic task. There is one caveat though: the values only update when you’re running a program. They don’t update while jogging. However, there is a work-around for this too.

First you should make sure that the feature to copy the position to variables is enabled. To get to the variables screen, use MENU, 0 (Next), 6 (System), F1 (Type), Variables.

Find this variable and set it to 1 (or True): $SCR_GRP[1].$m_pos_enb

The name of that variable is Current position from machine pulse

Now create a new robot program, and in it write the following:


GO[1:X POS]=($SCR_GRP[1].$MCH_POS_X*10)
GO[2:Y POS]=($SCR_GRP[1].$MCH_POS_Y*10)
GO[3:Z POS]=($SCR_GRP[1].$MCH_POS_Z*10)
GO[4:W ANG]=($SCR_GRP[1].$MCH_POS_W*100)
GO[5:P ANG]=($SCR_GRP[1].$MCH_POS_P*100)
GO[6:R ANG]=($SCR_GRP[1].$MCH_POS_R*100)

Note that I’ve multiplied the X, Y, and Z positions by 10, so you will have to divide by 10 in your PLC. Likewise I multiplied the W, P, and R angles by 100, so divide by 100 in the PLC.

To run this program in the background, use MENU, 6 (Setup), F1 (Type), 0 (Next), BG Logic. Configure it to run your new program as a background task.

Obviously you need to send these group outputs to the PLC. Ethernet/IP is great for this, but you can use hardwired interlocks too. You need to make sure that you have enough bits to handle the full range of motion. A 16-bit integer should work pretty well for all of these. Note that the robot will happily send negative numbers to a group output as two’s complement, so make sure you map the input to the PLC as a signed 16-bit integer (a.k.a. INT in most PLCs). For the X, Y, and Z positions, a 16-bit integer will give you from +3276.7 mm to -3276.8 mm of total range. For the W, P, and R angles you’ll get +327.67 deg to -327.68 deg. For most applications this is good (remember this is TCP, not joint angles). Please check that these are suitable though.

As I said, these numbers don’t update while you’re jogging, and won’t update until the robot starts a move in a program. One little trick is to do a move to the current position at the start of your program:


PR[100:SCRATCH]=LPOS
J PR[100:SCRATCH] 10% FINE

This starts sending the position without moving the robot. In my programs I typically enter a loop waiting for an input from the PLC, and inside this loop I turn a DO bit on and off. The PLC detects this as a “ready for command” heartbeat, and as long as the PLC sees this pulsing, then it knows the program is running and the position data is valid.

Another trick you can use is to detect when the robot has been jogged:


DO[n]=$MOR_GRP[1].$jogged

The name of this variable is Robot jogged. The description from the manual is: “When set to TRUE,the robot has been jogged since the last program motion. Execution of any user program will reset the flag.”

That’s how you get the world position of the TCP into the PLC. If you just want joint angles, you can use $SCR_GRP[1].$MCH_ANG[n] as the variable, where “n” is the joint number.

Important note: The I/O will probably change asynchronously to the program scan, so what you want to do is make a copy of the X, Y, Z, W, P, R values coming into the PLC and compare the current values to the values from the last scan. If they haven’t changed, then update your actual values, otherwise throw them away because they might not be valid. If you have a fast scanning PLC and I/O then you should still be able to keep up with the robot even during a fast move. If you have a slow scan time on your PLC, then you might only get valid stable values when the robot is stopped.

Now what if you want to know what the TCP position is relative to one of your user frames? The robot controller doesn’t seem to give you access to this, but the PLC can at least calculate the X, Y, and Z positions of the TCP in your user frame itself, given the world position and the user frame parameters.

First you need to find the accurate user frame parameters. Under the normal frames screen you can only get one decimal point of accuracy, but you need the full 3 decimal points to have your numbers in the PLC match the user frame position given in the robot. You can find these accurate positions in a variable: use MENU – 0,6 (SYSTEM) – F1 (TYPE) – Variables – $MNUFRAME[1,9] – F2 (DETAIL). The second index in square bracket is the frame number, so $MNUFRAME[1,1] is frame one and $MNUFRAME[1,2] is frame 2. Copy these numbers down exactly.

Here’s the math for calculating the TCP relative to your user frame. All variables are LREAL (which is a 64-bit floating point variable). I don’t know if you can use a regular 32-bit float or not. Result is your TCP in user frame. Point is your point in world frame (from the robot) and Frame is the accurate user frame data you copied from the $MNUFRAME[] variable.


Result.X_mm := Point.X_mm - Frame.X_mm;
Result.Y_mm := Point.Y_mm - Frame.Y_mm;
Result.Z_mm := Point.Z_mm - Frame.Z_mm;

RadiansW := DegreesToRadians(-Frame.W_deg);
CosOfAngleW := COS(RadiansW);
SinOfAngleW := SIN(RadiansW);

RadiansP := DegreesToRadians(-Frame.P_deg);
CosOfAngleP := COS(RadiansP);
SinOfAngleP := SIN(RadiansP);

RadiansR := DegreesToRadians(-Frame.R_deg);
CosOfAngleR := COS(RadiansR);
SinOfAngleR := SIN(RadiansR);

// Fanuc applies rotations WPR as W (around Z), P (around Y), R (around X)
// AROUND Z
temp := Result.X_mm;
Result.X_mm := Result.X_mm * CosOfAngleR - Result.Y_mm * SinOfAngleR;
Result.Y_mm := Result.Y_mm * CosOfAngleR + temp * SinOfAngleR;
// AROUND Y
temp := Result.Z_mm;
Result.Z_mm := Result.Z_mm * CosOfAngleP - Result.X_mm * SinOfAngleP;
Result.X_mm := Result.X_mm * CosOfAngleP + temp * SinOfAngleP;
// AROUND X
temp := Result.Y_mm;
Result.Y_mm := Result.Y_mm * CosOfAngleW - Result.Z_mm * SinOfAngleW;
Result.Z_mm := Result.Z_mm * CosOfAngleW + temp * SinOfAngleW;

Note that DegreesToRadians() is just PI*deg/180.

Run that on your PLC and check that the values in your Result variable match the user frame TCP position reported on the teach pendant.

I haven’t gotten around to calculating the W, P, and R angles of the TCP in user frame yet. Currently I just look at W, P, and R in world frame if I need to know if I’m “pointed at” something. If you get the math to work for W, P, and R, I’d really appreciate if you could share it.


· · ·

You may have noticed I recently added a new section to this site: Patterns of Ladder Logic Programming. My goal, as usual, is to try to help new ladder logic programmers come up to speed faster and without all the trial and error I had to go through.

The new Patterns section is an attempt to distill ladder logic programs into their component parts. I assume the reader already knows the basic elements of ladder logic programming, such as contacts, coils, timers, counters, and one-shots. The patterns describe ways of combining these elements into larger patterns that you’re likely to see when you look through real programs. In my experience, you can program 80% of the machines out there by combining these patterns in applicable ways.

The Patterns section isn’t complete yet, but I will be adding to it slowly over time. If you think of a pattern that’s blatantly missing, please send me a note so I can include it.

·

Nov/14

26

The TwinCAT 3 Review Revisited

I reviewed TwinCAT 3 in February of 2013 and it was a mixed bag. I lauded the amazing performance but warned about the reliability problems. I think it’s time to revisit the topic.

Things have improved greatly. When I wrote that review we had 2 production systems running TwinCAT 3 (the 32-bit version). We’re now up to 5 production systems with another on the way, all running version 3.1.4016.5 (which is a 64-bit version). The product has been more stable with each release. First we tried switching to a Beckhoff industrial PC, but we still experienced two blue screen crashes. We’ve then turned off anti-virus and disabled automatic windows updates. So far I haven’t seen another blue screen on that system, for about two months.

Manually installing windows updates isn’t a big deal, but it’s unfortunate to be running a PC-based control system with no anti-virus. Our industrial PCs are blocked from going online, and each one is behind a firewall that separates it from our corporate network, but it’s still a risk I don’t want to take. Industrial Control vendors continually tell us their products aren’t supported if you run anti-virus, and I don’t see how anyone can make statements like that in this day and age.

The performance of the runtime (ladder logic) and EtherCAT I/O is still absolutely amazing.

While the IDE is much better than the TwinCAT 2 system, the editor is still quite slow (even on a Core-i7 with a solid state drive).

The Scope is now integrated right into the IDE, and I can’t give that tool enough accolades. I recently had to use Rockwell’s integrated scope for ControlLogix 5000 and it’s pitiful in comparison to the TwinCAT 3 scope.

The TwinSAFE safety PLC editor is light years beyond the TwinCAT 2 editor, but it’s still clunky. It particularly sucks when you install a new revision of TwinCAT 3 and it has to upgrade the safety project to whatever new file format it has. We recently did this, then had to add a new 4-input safety card to the design, and it wouldn’t build the safety project because of a collision on the connection ID. It took us a couple hours of fiddling and we eventually had to manually set the connection ID to a valid value to get it to work. On another occasion, after a version upgrade, I had to go in and add missing lines in the safety program save file because it didn’t seem to upgrade the file format properly (I did this by comparing the save file to another one created in the new version).

The process of upgrading to a new TwinCAT 3 version often involves subtle problems. The rather infamous 3.1.4013 version actually broke the persistent variable feature, so if you restarted your controller, all the persistent variables would be lost. They quickly released a fix, but not before we experienced a bit of pain when I tried it on one of our systems. I’m really stunned that a bug this big and this obvious could actually be released. It’s almost as if Beckhoff doesn’t have a dedicated software testing department performing regression tests before new versions are released, but certainly nobody would develop commercial software like this without a software testing department, would they? That’s a frightening thought.

I ended my previous review by saying I couldn’t recommend TwinCAT 3 at this time. I’m prepared to change my tune a bit. I think TwinCAT 3 is now solid enough for a production environment, but I caution that it’s still a little rough around the edges.

Edit: Note that I’ve since added a TwinCAT 3 Tutorial section to this site.

· ·

Let’s assume you already know everything there is to know about motion control… you can jog a servo axis, home it, make it move to a position using trapezoidal or s-curve motion. Now what?

Sooner or later you’re going to find yourself with 2 or more axes and you’re going to want to do something fancy with them. Maybe you have an X/Y table and you want it to move on a perfect 45 degree angle, or you need it to follow a curved, but precise, path in the X/Y plane. Now you need coordinated motion.

Coordinated motion controllers are actually quite common. Every 3, 4, or 5 axis mill uses coordinated motion, every robot controller, and even those little RepRap 3D printers. What you may not know is that most integrated motion solutions you might encounter in the PLC world also offer coordinated motion (a.k.a. interpolated motion) control. If you’re from the Allen-Bradley world, the ControlLogix/CompactLogix line of PLCs allows you to use the Motion Coordinated Linear Move (MCLM) and Motion Coordinated Circular Move (MCCM) instructions along with a few others. If you’re from the Beckhoff world, you can purchase a license for their NC I product which offers a full G-code interpreter, which is the language milling machines and 3D printers speak.

Under the hood, a coordinated motion control solution offers several features necessary for a workable multi-axis solution. The first is a path planner, the second is synchronization.

The job of the path planner is fairly complex. If you say that you need to move your X/Y table from point 5,2 to point 8,3 then it needs to take the maximum motion parameters of both axes into account to make sure that neither axis exceeds it’s torque, velocity or acceleration/deceleration limits, and typically it will limit the “velocity vector” as well, meaning the actual speed of the point you’re moving in the X/Y plane. Furthermore, it must create a motion profile for each axis that, when combined, cause the tooling to move in a straight line between those points. After all, you may be trying to move a cutting tool along a precise path and you need to cut a straight line. To make matters far more complicated, after the motion is already in progress, if the controller receives another command (for instance to move to point 10,5 after the initial move to 8/3) then it will “blend” the first move into the second, depending on rules you give it.

For instance, let’s say you start at 0,0, then issue a move to 10,0 but then immediately issue a second move to 10,10. You have to option of specifying how that motion will move through the 10,0 point. If you issue a “fine” move then the X axis has to decelerate to a stop completely before the Y axis starts its motion. However, you can also tell it that you only care that you get within 1 unit of the point, in which case the Y axis will start moving as soon as you get to point 9,0 and will do a curved move through point 10,1 on its way to 10,10 without ever moving though point 10,0. This is actually useful if you’re more concerned with speed than accuracy. Another option you have is to issue a linear move to 9,0 followed by a circular move to 10,1 (with center at 9,1) followed by a linear move to 10,10. That will cause the tooling to follow a similar path, but in this case you’re in precise control of the curved path that it takes. In neither case will either axis stop until it gets to the final point.

The other important feature of coordinated motion is synchronization of the axes. Typically the controller delegates lower level control of the axes to traditional axis controllers, and the coordinated motion controller just feeds the motion profiles to each axis. However, it’s imperative that each axis starts its motion at precisely the same time, or the path won’t be correct in the multi-dimensional space. That requires some kind of clock synchronization, and that’s the reason why you see options for things like Coordinated System Time Masters on ControlLogix and CompactLogix processors.

That was very brief, but I hope it was informative. If you do have to tackle coordinated motion on your next project, definitely allocate some time for reading your manufacturer’s literature on the subject because it’s a fairly steep learning curve, but clearly necessary if your project demands it.

·

Aug/13

6

Where to Draw the Line(s)?

One of the most confusing things that new programmers face is how to break down their program into smaller pieces. Sometimes we call this architecture, but I’m not sure that gives the right feel to the process. Maybe it’s more like collecting insects…

Imagine you’re looking at your ladder logic program under a microscope, and you pick out two rungs of logic at random. Now ask yourself, in the collection of rungs that is your program, do these two rungs belong close together, or further apart? How do you make that decision? Obviously we don’t just put rungs that look the same next to each other, like we would if we were entomologists, but there’s clearly some measure of what belongs together, and what doesn’t.

Somehow this is related to the concept of Cohesion from computer science. Cohesion is this nebulous measure of how well the things inside of a single software “module” fit together. That, of course, makes you wonder how they defined a software module…

There are many different ways of structuring your ladder logic. One obvious restriction is order of execution. Sometimes you must execute one rung before another rung for your program to operate correctly, and that puts a one-way restriction on the location of these two rungs, but they could still be located a long way away.

Another obvious method of grouping rungs is by the physical concept of the machine. For instance, all the rungs for starting and stopping a motor, detecting a fault with that motor (failure to start), and summarizing the condition of that motor are typically together in one module (or file/program/function block/whatever).

Still we sometimes break that rule. We might, for instance, have the motor-failed-to-start-fault in the motor program, but likely want to map this fault to an alarm on the HMI, and that alarm will be driven in some rung under the HMI alarms program, potentially a long way away from the motor program. Why did we draw the line there? Why not put the alarm definition right beside the fault definition that drives it? In most cases it’s because the alarms, by necessity, are addressed by a number (or a bit position in a bit array) and we have to make sure we don’t double-allocate an alarm number. That’s why we put all the alarms in one file in numerical order, so we can see which numbers we’ve already used, and also so that when alarm # 153 comes up on the HMI, we can quickly find that alarm bit in the PLC by scrolling down to rung 153 (if we planned it right) in that alarms program.

I just want to point out that this is only a restriction of the HMI (and communication) technology. We group alarms into bit arrays for faster communication, but with PC-based control systems we’re nearing the day when we can just configure alarms without a numbering scheme. If you could configure your HMI software to alarm when any given tag in the PLC turned on, you wouldn’t even need an alarms file, let alone the necessity of separating the alarms from the fault logic.

Within a program, how should we order our rungs? Assuming you satisfied the execution order requirement I talked about above, I usually fall back on three rules of thumb: (1) tell a story, (2) keep things that change together grouped together, and (3) separate the “why” from the “how”.

What I mean by “tell a story” is that the rungs should be organized into a coherent thought process. The reader should be able to understand what you were thinking. First we calculate the whozit #1, then the whozit #2, then the whozit #3, and then we average the 3. That’s better than mixing the summing/averaging with the calculating of individual whozits.

Point #2 (keep things that change together grouped together) is a pragmatic rule. In general it would be nice if your code was structured in a way that you only had to make changes in one place, but as we know, that’s not always the case. If you do have a situation where changing one piece of logic means you likely have to change another piece of logic, consider putting those two rungs together, as close as you can manage.

Finally, “separate the why from the how”. Sometimes the “how” is as simple as turning on an output, and in that case this rule doesn’t apply, but sometimes you run across complicated logic just to, say, send a message to another controller, or search for something in an array based on a loop (yikes). In that case, try to remove the complexity of the “how” away from the upper level flow of the “why”. Don’t interrupt the story with gory details, just put that into an appendix. Either stuff that “how” code in the bottom of the same program, or, better yet, move it into its own program or function block.

None of these are hard and fast rules, but they are generally accepted ways of managing the complexity of your program. You have to draw those lines somewhere, so give a little thought to it at first, and save your reader a boatload of confusion.

·

Feb/13

16

The TwinCAT 3 Review

Edit: Note that I have posted an updated TwinCAT 3 Review in 2014.

So back in 2010 I wrote about my first impression of TwinCAT 2 and later that same year I wondered if automation programmers would accept TwinCAT 3. I was lucky enough to be involved in the TwinCAT 3 beta, and now that the 32-bit version of TwinCAT 3 is available for general release we’ve deployed 2 production systems based on TwinCAT 3, and will likely deploy more in the future. What follows are my impressions of the current state of TwinCAT 3 based on our experiences with those 2 systems.

I think the best way I can describe TwinCAT 3 to the non-initiated is by comparing it with Allen-Bradley’s ControlLogix platform with their RSLogix 5000 programming environment. I say that because I’m familiar with that platform, and so are most of my North American readers (I assume). It speaks well of Allen-Bradley that they are the de-facto default control system platform around here.

We often fall back on car analogies, and I don’t want to break with tradition. If ControlLogix is the Ford Taurus of control systems (common, reliable, with lots of performance for most tasks, lots of room, and fairly maintenance free) then TwinCAT 3 is something like the Rally Fighter. That is, it’s road legal, fairly rare, requires lots of TLC and understanding and may not be as reliable, but will take you places you’ll never get to go in a Ford Taurus.

When it comes to speed, TwinCAT 3 with Beckhoff’s EtherCAT I/O is a beast. I can’t stress this enough. We’re running both production systems of TwinCAT 3 with both a 0.5 millisecond logic scan time and a 0.5 millisecond I/O bus scan time and we’re only using about 10% to 15% of the available horsepower of each system. You can see and react to things in the TwinCAT 3 system that you’ll just miss in a ControlLogix processor. For instance in one case we’re driving an output off of an absolute encoder and the repeatability of turning on that output is much better than anything we’ve seen with any other controller.

Furthermore, data accessibility is light years beyond any traditional PLC. In one test I moved a 400 kB block of data from the real-time (ladder logic program) to a .NET program running under windows on the same PC and all I can say is that it’s nearly instantaneous. That’s an advantage of having the HMI and real-time executing on the same physical hardware.

That’s not even getting into the new C++ integration (which I haven’t used).

Any TwinCAT 3 vs. ControlLogix system comparison will also certainly favor the Beckhoff solution when it comes to price. At least I can’t seen any case yet where that’s not true by a significant margin. I can’t say exact prices, obviously, but I’m confident that’s generally a true statement.

Does that mean I think the competition is a hands-down blow-out in favor of TwinCAT 3? No. In fact if you’re considering trying TwinCAT 3 I can’t even go so far as to give you my blessing right now. It has problems.

TwinCAT 3 crashes with a blue screen. Regularly. There, I said it. That’s the dirty secret. Everyone’s fears about PC-based control on the factory floor were around stability and in our experience TwinCAT 3 isn’t stable yet. This is odd to me because we have another system with TwinCAT 2 and it’s solid as a rock. Unfortunately our TwinCAT 3 system crashes with a blue screen regularly, and the crash report always shows that it’s some kind of memory violation in their Tc*.sys files, which are the system files responsible for running their real-time system under ring 0 of the OS (as far as I understand). I’ve never even seen blue screens with Windows 7 until trying out TwinCAT 3. There are actually two different times that it crashes: (1) randomly, and (2) when I try to do an online change.

Beckhoff’s response was that we were running it on 3rd party hardware. They loaned us a Beckhoff industrial PC to try. We tried it for a week and we didn’t see any random crashes, but it still crashed the real-time when I tried to do an online change, and it also crashed the IDE almost every time I recompiled the program. In fact that’s the reason we had to stop the test with Beckhoff’s hardware after only one week. I needed to compile a change and couldn’t get it to compile. It did work on our 3rd party PC (an HP desktop PC).

Now, I don’t think these are insurmountable problems. Beckhoff is still coming out with new versions on a regular basis. Their new support for 64-bit windows operating systems is on the horizon. TwinCAT 2 seems stable and I’m sure TwinCAT 3 will get there eventually. However, for the moment, if you’re considering the plunge, I suggest waiting about a year before bothering to check it out. If you just need the speed, consider TwinCAT 2, as even though it doesn’t take advantage of multiple cores it will likely do what you need and is a much more mature product at this point.

· ·

Dec/11

10

Safe(r) Data Collection from a PLC

There’s been a lot of discussion recently about the dangers of connecting automation equipment to networks, and yet there are significant pressures to do so. Of course, I don’t ever think that you should take a PLC and put it on an internet accessible IP address, but it’s certainly common practice to connect industrial automation equipment to internal LANs to facilitate data collection. People in the front office need to push production planning information down to the production floor, and they need real-time data on what’s going on (not to mention for historical data logging, historians, etc.).

It’s all too common to throw a PLC on the same network as your front office, and I’ve seen it blow up. What happens is something invariably goes wrong on the office network (someone plugs two ports together on the switch in the boardroom, or someone brings in an infected music player and plugs it in, or the DNS server at head-office goes down and the local DNS doesn’t work correctly… I’ve seen a lot). However, you want your machines to keep going when this happens.

This is all made worse now that (a) industrial automation equipment is more commonly based on off-the-shelf commodity hardware and software (e.g. windows PCs) and (b) the people writing malware can actually spell PLC now. Up to this point there’s been some form of security through obscurity.

If you have a local IT staff that’s on the ball, you really should be getting them to handle the network layout. On the other hand, if you’re in a small facility with limited resources, there’s a lot you can do by making some simple design choices that will go a long way towards improving the reliability and security of your systems.

Most automation cells now come with an Ethernet switch already built-in. Typically this is an industrial spec. DIN-rail mounted one. It’s not fancy, but it’s supposed to survive in a panel. These Ethernet switches are there to connect your PLC to your HMI, and increasingly to connect your PLC to Ethernet-based I/O like Ethernet/IP, etc. The common (and wrong) thing to do is to drop a network cable from your plant network to your panel and plug it right into this Ethernet switch. This creates some technical problems right off the bat:

The automation devices typically have fixed IP addresses (I personally prefer this because it means these devices aren’t dependent upon an external DNS or DHCP server – two less dependencies are good). Chances are that these IP addresses won’t work on your plant network, so you have to manage those IPs at the plant level. You’re opening yourself up to someone with the wrong IP on their laptop pouncing on your PLC’s IP address, and then bam, your machine is down.

A much better way is to place some kind of Router with NAT between the plant network and the machine’s Ethernet Switch:

Now if you’re just a little manufacturer with two machines out back and your data-collection link isn’t critical, you can probably get away with one of those home routers from Best Buy that you’d use to connect your laptop and your desktop at home to your cable modem. Note that it doesn’t need to be wireless, and you’re probably better off if it isn’t. The way you hook it up is to connect the Internet (Uplink) port on the router to the plant network and run a cable from one of the ports on the LAN side to the existing Ethernet switch in the machine. If your data needs to be a bit more reliable, consider buying some kind of Cisco router with NAT capability (but you’ll be going from the $50 range to many hundreds of dollars – your choice).

Now, when you configure it, you want to make sure that you turn off the port forwarding function, the DMZ function, disallow remote administration, and block all anonymous internet traffic (these should be default settings, but it’s good to check). Also, make sure the router’s local IP address doesn’t conflict with the PLC’s and HMI’s, and make sure they have the same subnet. Typically you’ll want to either turn off DHCP on the local side, or limit it to a range that won’t conflict with the fixed IPs. DHCP is handy when you connect your laptop to the programming port. Now what you’ve done is made it somewhat invisible from the plant side. Some piece of malware scanning for devices on your plant network should just see a black hole.

Now on the PLC side, you can now initiate a connection to the data collection server even though the data collection server can’t connect to the PLC (in the same way that your home computer can connect to Google, but Google can’t get to your PC – theoretically). Note that a piece of malware on your data collection server or on one of the routers/switches in your plant network could intercept this communication, and own your PLC, but at least you’ve significantly reduced the surface area of attack. Not perfect, but reasonable at this time, depending on the sensitivity of your equipment. I’m assuming you’re not enriching uranium or providing drinking water to my community.

(I’m going to be talking specifically about Allen-Bradley products now – sorry.)

So how do you get the data from the PLC to the data collection server? In the old days you’d have some software on the server like RSSQL, and it used a product like RSLinx Enterprise and as far as I know, it initiated the connection to the PLC. That won’t work in this case. Sometimes you’d throw an OPC server in there, and have some kind of historian that would log tags to a database. That OPC server, obviously, needs to be able to initiate a connection to the PLC. To use a router with NAT, you’d need to port-forward from the router to the PLC (or to the OPC server if it was inside the machine network). That’s undoing a lot of our protection.

What you need to do is initiate the connection from the PLC, and have the Data Collection computer act as a Server. One way to do this is with a 3rd party Ethernet card, like this MVI56-GEC card from Prosoft for the ControlLogix line. I have used that in the past to connect to a server, but it involves a lot of ugly PLC coding. It’s your only option if you have to conform to someone else’s protocol though.

If you just want to write data directly into a SQL database, there are 3rd party products that will let you do this (basically a SQL Server connector card).

But there is an option without buying any new hardware. The ControlLogix/CompactLogix lines can send Unsolicited CIP messages, and you can find products that can receive these messages in the PC world, like CimQuest’s NET.LOGIX product. It can act as a server and receive data directly from the PLC – either individual tags, or even arrays of UDTs. The code on both ends is relatively simple, so all you have to pay for is the NET.LOGIX runtime license, which is cheaper than the hardware alternatives. Note that you can also do this with PLC5 and SLC500 devices, though there’s some more effort involved.

I hope that’s enlightening. This is by no means a perfect solution, but it’s reasonable for now. It doesn’t plug the laptop hole (the programming laptop is probably still your #1 vector for malware to get into your machine network). It’s susceptible to man-in-the-middle attacks between the router and the data collection server. It’s susceptible to exploitable bugs in the router’s firmware. Beware and use your own judgement.

· ·

I think most people in our industry realize you shouldn’t connect industrial automation devices to the internet, but just in case you happen to think otherwise, here’s a quick explanation why (this is old news, by the way).

You may believe that things connected to the internet are relatively anonymous. There’s no web page linking to them, so how is Google going to find them, right?

It turns out it’s relatively easy to find devices connected to the internet, and it’s kind of like the old movie WarGames where the lead character, played by Matthew Broderick, programmed his computer to dial every phone number in a specific block (555-0001, 555-0002, etc.) and record any where a modem answered. That was called “war-dialing”. In the age of the internet, you just start connecting to common port numbers (web servers are on port 80, etc.) on one IP address at a time, and logging what you find. This is called port-scanning.

It turns out that you don’t even have to do this yourself. One free service called SHODAN does this for you, and records everything it finds at the common port numbers (web servers, FTP servers, SSH daemons, etc.) and lets you search it just like Google. It turns out that (a) most modern industrial equipment is including embedded web servers and/or FTP servers to allow remote maintenance, and (b) most web servers or FTP servers respond with some kind of unique “banner” when you connect to them, announcing who or what they are.

So, if you don’t believe that you shouldn’t be putting industrial automation equipment on the internet, here’s a little experiment you can run:

  1. Take a ControlLogix with an ENBT card and hook it directly to the internet, so it has a real IP address.
  2. Wait a couple of days.
  3. See if your IP address shows up on this SHODAN search page.

You could try the same thing with a Modicon M340.

This query for Phoenix Contact devices is particularly scary, as one of the links is a wind turbine! I was a bit scared once I opened it (it opens a publicly accessible Java applet that’s updating all the data in real-time), so I closed it. There was no password or anything required to open the page. At least the button that says “PLC Config.” appeared to be grayed out. Let’s hope that means it’s protected by some kind of password… and that it’s hardened better than every single major corporation’s website was this year.

Just want to say thanks to DigitalBond for pointing out this SHODAN search for all Advantech/Broadwin WebAccess deployments around the world too.

·

There’s a lot of stuff that falls under the term “functional programming,” but I’m just going to focus on the “functional” part right now, meaning when you define the value of something as a function of something else.

In ladder logic, we define the values of internal state (internal coils or registers) and outputs. We define these as functions of the inputs and internal state. We call each function a “rung”, and one rung might look like this:

Ladder diagram of Inputs A and B, and Internal State C

There’s something slightly odd going on in that rung though. You might say that we’ve defined C recursively, because C is a function of A, B, and itself. We all know, of course, that the PLC has no problem executing this code, and it executes as you would expect. That’s because the C on the right is not the same as the C on the left. The C on the right is the next state of C and the C on the left is the previous state of C.

Each time we scan, we redefine the value of C. That means C is an infinite time-series of true/false values. Huh?

Ok, imagine an array of true/false (boolean) values called “C”. The lower bound on the array index is zero, but the upper bound is infinite. C[0] is false (the value when we start the program). Then we start scan number 1, and we get to the rung above, and the PLC is really solving for is this:

Ladder logic defining C[1] as a function of A, B, and C[0]

If that were actually true (if it had an infinite array to store each coil’s value), then the ladder logic would be a truly functional programming language. But it’s not. Consider this:

Two ladder logic rungs with inputs A and B, internal coil C, and output D

In all modern PLCs, the first rung overwrites the value of C, so the second rung effectively uses the newly computed value for C when evaluating D. That means D[1] is defined as being equal to C[1] (the current state value of C). Why is this weird? Consider this:

Two previous rungs with the rung order reversed

By reversing the order of the rungs, I’ve changed the definition of D. After the re-ordering, D is now defined as C[0] (the previous state value of C) rather than C[1]. This isn’t a trivial difference. In an older PLC your scan time can be in the hundreds of milliseconds, so the D output can react noticeably slower in this case.

In a truly functional language, the re-ordering either wouldn’t be allowed (you can’t define D, which depends on C, before you define C) or the compiler would be able to determine the dependencies and re-order the evaluation so that C is evaluated before D. It would likely complain if it found a circular dependency between C and D, even though a PLC wouldn’t care about circular dependencies.

There are a few of reasons why PLCs are implemented like this. First, it saves memory. We would have to double our memory requirements if we always wanted to keep the last state and the next state around at the same time. Secondly, it’s easier to understand and troubleshoot. Not only does the PLC avoid keeping around two copies of each coil, but the programmer only has to worry about one value of each coil at any given point in the program. Third, the PLC runtime implementation is much simpler. It can be (and is) compiled to a kind of assembly language that can run efficiently on single threaded CPUs, which were the only CPUs available until recently.

Of course this comes with a trade-off. Imagine, for a moment, if rung-ordering didn’t matter. If you could solve the rungs in any order, that means you could also solve the rungs in parallel. That means if you upgraded to a dual-core CPU, you could instantly cut your scan time in half. Alas, the nature of ladder logic makes it very difficult to execute rungs in parallel.

On the other hand, we can still enforce a functional programming paradigm in our ladder logic programs if we follow these rules:

  • Never define a coil more than once in your program.
  • Don’t use a contact until after the rung where the associated coil has been defined.

That means there should only be one destructive write to any single memory location in your program. (It’s acceptable to use Set/Reset or a group of Move instructions that write to the same memory location as long as they’re on the same or adjacent rungs).

It also means that if coil C is defined on rung 5, then rungs 1 through 4 shouldn’t contain any contacts of coil C. This is the harder rule to follow. If you find you want to reference a coil before it’s defined, ask yourself if your logic couldn’t be re-organized to make it flow better.

Remember, someone trying to solve a problem in a PLC program starts at an output and uses cross references to move back through the program trying to understand it. Cross referencing from a contact to a coil that moves you forward in the program doesn’t require any logical leaps, but cross referencing to a coil later in the program means you need to logically think one scan backwards in time.

Benefits

While ladder logic isn’t a truly functional language, you can write ladder logic programs in the functional programming paradigm. If you do, you’ll find that your outputs react faster, and your programs are easier to understand and troubleshoot.

·

Mar/11

30

More about Stuxnet, on TED

I’ve been enjoying a lot more TED recently now that I can stream it directly to our living room HDTV on our Boxee Box. Today it surprised me with a talk by Ralph Langner called “Cracking Stuxnet: A 21st Century Cyber Weapon”. I talked about Stuxnet before, but this video has even more juicy details. If you work with PLCs, beware; this is the new reality of industrial automation security:

· ·

<< Latest posts

Older posts >>

Theme Design by devolux.nh2.me