Sequential Control (was Updated PLC Book on-line)

M

Michael Griffin

There are two sides to the error detection question. One is in detecting that something is wrong, and the other is to determine what is wrong, and create alarms to notify the operator of this.

To deal with the second matter first, I do all of the alarm decoding in a separate subroutine. The decoding of faults into alarms is completely separate from the machine sequence. When a fault is detected, I do a one shot scan through the fault decoding logic for that sequence to determine what was not in the correct state. The reason for the one shot is to capture
a snap shot of the machine state at the moment the fault occured. This allows intermitent faults to be captured and displayed as an alarm. Each
independent sequence needs to be dealt with separately, so that you don't try to decode a cylinder which is in mid stroke on a part of the machine that was still running.

To decode faults into alarms I simply look at the actual outputs and inputs for each device (e.g. a cylinder). For example, if I turn a valve on to extend a cylinder, the extended sensor should go on, and the retracted sensor should go off. This results in four possible alarms per cylinder (two for each sensor). This can be resolved in four simple rungs of ladder logic.
To reduce the amount of typing required (and typing mistakes), I created a subroutine to encapsulate this logic. The subroutine takes as
parameter inputs one actuator and two sensors, and has four alarm bits as output parameters. I believe that I submitted this subroutine (FDECODE) to the PLC archive a while ago. There is also a second version (FDECOD1) for cylinders with only one sensor. Some special cases need custom alarm decoding logic, but the two subroutines I wrote seem to cover 95% of the cases.

So far I have been detecting that faults exist (but not decoding them) in the sequential part of the program by passing through the state of the logic which examines the inputs to decide whether to advance to the next step. This is then examined by a common fault timer. If the inputs to an active step are not not true for a period of time (i.e. the step times out), then the fault timer will trigger the fault decoding logic as described above.

I'm not entirely sure this is the best way to do things, but it was a natural progression from previous ways of doing things which were established by other people. There are however some pros and cons to it.

Pro - It conserves timers, which can be an issue with Siemens PLCs, as you only get so many, and we have run out of timers on a couple of large applications (this is unusual though).
Pro - A fault condition will be flagged if the sequence is not able to advance because of an input condition. This keeps a fairly close match between the sequence transition logic and the fault detection (although you might forget to include an actual alarm message).

Con - It may be more trouble than it's worth.
Con - It isn't a universal solution, and I end up having individual fault timers for some special situations anyway.
Con - You have to be careful in making sure that devices which use the same fault timer are actually dependent upon each other, or you will end up displaying erroneous alarms messages together with the correct ones.


Perhaps I should just give every device its own individual fault timer? I know that some people do this. It should be possible to incorporate the fault detection and alarm generation into a single subroutine, which would make that logic re-usable. I can ignore the need to conserve timers and deal with that problem separately if it ever comes up again since most
of our machines are fairly small.
I should think that I would still need some sort of overall fault timer to make sure the sequence is still transitioning. This could trigger a general alarm message along the lines of "Unknown Pick and Place Sequence Fault", or something similar if no other alarm was decoded. This would cover situations where a fault condition was not programmed properly.

I haven't described how I handled single step manual control. If you are interested we can thrash through that. I would be interested though in your comments on faults and alarms.

**********************
Michael Griffin
London, Ont. Canada
**********************

 
Michael:
> The basic step/transition structure of Grafcet is so simple and limited,
> that a few formatting instructions would give a reverse-compiler enough
> hints to reconstruct any graph.

It almost sounds like it should be possible to reconstruct the graph even without the formatting instructions... Unless the original compiler was
optimizing, it should just be a matter of recognizing the patterns, and then going with the combination that gives the least code left over.

Just have to be a bit careful that the code left over is treated right.

No, I don't want to write it, I have enough to do as it is... (like integrating a stepladder into the LinuxPLC - it's in there, but it's not
connected to anything yet).

Jiri
--
Jiri Baum <[email protected]>
http://www.csse.monash.edu.au/~jiribvisit the MAT LinuxPLC project at http://mat.sf.net
 
M

Michael Griffin

At 15:13 16/08/01 +0600, Vladimir E. Zyubin wrote:
&lt;clip>
>I am sorry I can not catch the point...
>Why do you try to find a solution of the well-known problem in LD terms?
&lt;clip>
>There is a lot of quite adequate means for the task in question in the
>world. State languages, for example... They were made for sequential control.
>Well, LD is being "positionated" by vendors as a simple mean we can use without
>any knowledge. But this firstly means that LD has limitations of using.
<clip>
>There are different tasks and there are different tools.
&lt;clip>
The reason is that with many PLCs, ladder is all you have to work with. Yes it would be nice to work at a higher "level", but if the hardware decision is based on other criteria and the vendor's higher level programming software is not implemented in a useful manner or is non-existent, then you really don't have much choice.

The question then becomes whether it is possible to use some of the ideas and concepts behind the higher level programming methods (such as grafcet) while implementing the actual program with the lower level methods which are available for the hardware you are working with.
There is more to grafcet or state languages than just the actual representation. They also introduce a way of thinking about the problem. I find that they greatly clarify thinking about and describing a problem even if you don't use them to create the actual program.

**********************
Michael Griffin
London, Ont. Canada
**********************

 
M

Michael Griffin

Jiri Baum wrote:
&lt;clip>
>It almost sounds like it should be possible to reconstruct the graph even
>without the formatting instructions... Unless the original compiler was
>optimizing, it should just be a matter of recognizing the patterns, and
>then going with the combination that gives the least code left over.
>
>Just have to be a bit careful that the code left over is treated right.
&lt;clip>

I can imagine that there could be ambiguous code combinations that would be difficult to resolve when de-compiling. However, if you inserted formatting codes that marked the beginning and end of each step or transition, then the problem should become easy. A step would be defined as any code in between a "begin step" and "end step" marker pair. The markers could be numbered so the links between the steps and transitions is maintained easily. The links to the various step and transition numbers could also embedded. There is no reason to make the job of the graph editor any more difficult than it needs to be.

If you really want to do things right, then the steps (or states) and transitions could be handled in a means analoguous to subroutines. Most PLCs handle subroutines (or function blocks) as a fundamental feature - they don't simulate them with an add-on "compiler". Why not just make each step (or state) and transition a special type of subroutine? You could then edit the contents of each of these special subroutines with the same ladder editor you use for normal subroutine editing (with some restrictions on what
you are allowed to address). A special editor to create the links between them and to display the graph and check the syntax would still be needed,
but there wouldn't be any "compiler" or "de-compiler" per say.

The idea seems obvious enough.

**********************
Michael Griffin
London, Ont. Canada
**********************

 
V

Vladimir Zyubin

Hello Michael,

On Friday, August 17, 2001, 5:52:26 AM, Michael Griffin <[email protected]> wrote:

MG> At 15:13 16/08/01 +0600, Vladimir E. Zyubin wrote:
[...]
>>Well, LD is being "positionated" by vendors as a simple mean we can use without
>>any knowledge. But this firstly means that LD has limitations of using. [...]
>>There are different tasks and there are different tools.

MG> The reason is that with many PLCs, ladder is all you have to work
MG> with. Yes it would be nice to work at a higher "level", but if the hardware
MG> decision is based on other criteria and the vendor's higher level
MG> programming software is not implemented in a useful manner or is
MG> non-existent, then you really don't have much choice.

In the case the programmer ought to inform the decision-maker that the decision is wrong.
The decision is wrong because it leads to the problems with reliability and maintainability. The problems IMO are so obvious that there is no needs to list it here.

MG> The question then becomes whether it is possible to use some of the
MG> ideas and concepts behind the higher level programming methods (such as
MG> grafcet) while implementing the actual program with the lower level methods
MG> which are available for the hardware you are working with.
MG> There is more to grafcet or state languages than just the actual
MG> representation. They also introduce a way of thinking about the problem. I
MG> find that they greatly clarify thinking about and describing a problem even
MG> if you don't use them to create the actual program.

IMO, the one decision (also a palliative one) could be to use the translator that produces the code in LD terms. (Obviously, in the case the LD is just a low level linguistic means that is
invisible for the programmer during the lifecycle of the program)

Again:
IMO, the problem discussed in the thread is the problem of implementation (low level, machine presentation) of state language. All these questions should be and are concealed during programming in the real state languages. Sequential control should be done with adequate tools.

So, I see the one problem -- the wishes of the hardware vendors to defend the hardware from outsiders... well-understandable wishes...

"Hayek rulez!" :)

--
Best regards,
Vladimir mailto:[email protected]

 
M

Michael Griffin

At 14:08 15/08/01 -0400, Anthony Kerstens wrote:
&lt;clip>
>> >As for the method, I would define general bits such as:
>> >
>> >Sequence Start Permissive,
>> >Sequence Start Command,
>> >Sequence Complete Status,
>> >
>> >Sequence Step 1 Start Permissive,
>> >Sequence Step 1 Start Command,
>> >Sequence Step 1 Complete Status,
>> >
>> >etc.
>> &lt;clip>
>
>The complete status of one step may be used to initiate a start
>command of another step.
>Other conditions may also be used to modify/initiate a start command.
>The permissive usually is e-stop and modes.
&lt;clip>

I'm still not sure I understand your explanation. Is the following correct? The "Step x Start Permissive" enables the "Step x Start Command". The "Step x Start Command" somehow drives the outputs (indirectly). The "Step x Complete Status" causes the transition to the next step.
If this explanation is correct, what happens if you transition to a step, but the "permissive" is false. Do the outputs remain at the state defined by the previous step? If so, then what is the difference in the effect of the "Step x Complete Status", and the "Step x+1 Start Permissive"?


>As for the start commands, they would be used by separate device control
>logic.
>For example, a motor auto run command....
>
>Motor run permissive.
>Motor manual run command.
>Motor auto run command.
>Motor running status.
>Motor o/l fault.
>etc.
>If multiple steps need to initiate a single device, then multiple
>step start commands may go to the motor auto run command in parallel.
>
>I do this because I don't like to drive outputs directly within the
>sequence logic. I need to have the separation between sequence control
>and device control because I find it allows my logic to be better organized.
&lt;clip>

If I understand you correctly, then each output has a ladder rung with contacts representing each step ORed together (possibly with other logic ANDed with them as well). This actually sounds a lot like the "Method A" I described in a previous letter.

>> bit gets turned on during PLC power-up it can cause an unexpected logic
>> state to be assumed. How do you handle this?
>
>1. Machine operation must be initiated by the operator.
>2. I don't rely on logic states to monitor the state of the system.
>I have the state of field devices to monitor the system.
>3. Why would a bit that's not retentive be turned on during PLC power-up?

"Machine operation must be initiated by the operator." - What does this mean? That they must push the start button before it does anything? That is not the situation to which I am refering. I am refering to logic getting triggered because a bit was on which you expected to be off at power-up. However, you said (in a reply to my previous letter) you prefer explicit start-up logic, which I think covers this situation.

"Why would a bit that's not retentive be turned on during PLC power-up?" - I don't know why it would do this. It did it because the PLC
did something it wasn't supposed to, I suppose. I don't know what causes it, but I have had to fix program bugs which have been caused by it. I have seen this in several brands and models of PLC.
If it happens once only, you can usually make the problem go away by turning the power off and trying again. If it happens too often though (and is too hard to recover from), then you have to add the re-start logic that someone else forgot, and make sure that whatever is supposed to be off is actually off when you start up.

**********************
Michael Griffin
London, Ont. Canada
**********************

 
H

Higginbotham Ricky

If you want to store the entire "graph" structure on the PLC, the problem is that you have to store all that information on the PLC. Everything, even
the symbol information. That increases the amount of space needed by I don't know, say a factor of 10. You've also got to change the way the PLC operates to add all this special stuff. This isn't as much of a problem on a PC where you've got plenty of disk space, but another matter entirely on a PLC with limited memory. It doesn't really make a difference whether you
treat the logic as subroutines or not (inlined), you still run into the same data requirements.

Its not as easy a problem as it sounds, espcecially for an issue that isn't really related to the basic operation of the hardware. Its a source control problem. Its hard to justify turning away 10 customers because you generate massively bloated code, to satisfy one.

Take the time to come up with an algorithm that will generate code for such a language (don't know graph but I am working on something similiar for APE SFCs). Then see how much information you need in order to get an original program (or something close) from that. You'll see what I mean.

Ricky Higginbotham

Visit the MAT LinuxPLC project at http://mat.sourceforge.net


 
Jiri:
> >It almost sounds like it should be possible to reconstruct the graph
> >even without the formatting instructions... Unless the original compiler
> >was optimizing, it should just be a matter of recognizing the patterns,
> >and then going with the combination that gives the least code left over.

> >Just have to be a bit careful that the code left over is treated right.
...

Michael:
> I can imagine that there could be ambiguous code combinations that would
> be difficult to resolve when de-compiling.

Then the de-compilation would give you a different graph than the one you started with. This is probably not a problem - in the few cases where it does happen, it's just re-factoring the program.

More commonly, it might split large steps into sub-steps, or, more likely, join steps that have become merged in practice. Again, not a big problem, the overall structure will still be there.

> However, if you inserted formatting codes that marked the beginning and
> end of each step or transition, then the problem should become easy.
...
> There is no reason to make the job of the graph editor any more difficult
> than it needs to be.

Well, if you're retro-fitting it to an existing solution, then you have to work with the constraints it has. If all you have is the ladder, with no special formatting marks, then that's what you've got to handle.

As has been pointed out, nothing will get you back the state names; all you'll have is the state numbers. But even so such a tool should be useful. (Unless the PLC has a built-in data dictionary, but it won't.)

In some way it'd be not so much a programming tool as a reverse-engineering tool, showing you the states inherent in some (given) PLC program.

Jiri
--
Jiri Baum <[email protected]>
http://www.csse.monash.edu.au/~jiribvisit the MAT LinuxPLC project at http://mat.sf.net


 
M

Michael Griffin

At 13:26 17/08/01 -0400, Ricky Higginbotham wrote:
>If you want to store the entire "graph" structure on the PLC, the problem is
>that you have to store all that information on the PLC. Everything, even
>the symbol information.
&lt;clip>
Why would you have to store the symbols in the PLC to accomplish what I suggested? It isn't the symbolic information I am concerned about, it is the structure of the graph itself. Out of date symbols are less of a problem than a program which has to be scrapped. Some PLCs will let you store symbols in PLC memory, but that isn't what I was referring to.

>It doesn't really make a difference whether you
>treat the logic as subroutines or not (inlined), you still run into the same
>data requirements.

No, I must disagree. What you would store in the PLC is enough information to allow the graph to be reverse engineered. This would be
indicators of the start and end of each step (or state) and transition, together with the links between them. I don't see how this can be more than a fraction of the size of the graph code. Indeed, I believe that if the PLC offered direct support for graphical languages, the actual program would be smaller. Step-7 Graph must load in considerable overhead in function blocks to make up for the lack of direct support.

>Its not as easy a problem as it sounds, espcecially for an issue that isn't
>really related to the basic operation of the hardware. Its a source control
>problem. Its hard to justify turning away 10 customers because you generate
>massively bloated code, to satisfy one.

If we followed this reasoning then everyone would be writing their programs in 8051 assembly language. Very little that is found in a modern PLC is there because it is "related to the basic operation of the hardware". The reason people use PLCs is because they are designed to make life easier for people who want to make machines run. Why would anyone want to adopt
something that makes life more difficult?

When you say "its a source control problem", you are simply saying "it's the customer's problem". It is very rare that the average machine builder (or even worse - their subcontractors) can seem to deliver a valid copy of the source code to their customers at the end of a project. So what should the customer do? Should they assume they may have to scrap every
program that comes with a new machine and write their own? Why would any customer find this acceptable?

>Take the time to come up with an algorithm that will generate code for such
>a language (don't know graph but I am working on something similiar for APE
>SFCs). Then see how much information you need in order to get an original
>program (or something close) from that. You'll see what I mean.
&lt;clip>

That is not what I had in mind at all. One of the suggestions I had was that viewing step (or states) and transition as special subroutines would allow each step (or state) and transition to be created and edited with standard ladder tools. The graph tool would only define the links between them. That is, step x would be linked to transition y, which would in turn be linked to step z, etc. I don't see a need under this scenario for any code generator other than the ladder editor.

However, this particular idea was not the central argument. The point I was trying to make was that making life easier for the PLC
developers by simply dumping any problems they don't want to deal with onto their customers will not necessarily endear themselves to these customers.

I believe that this discussion started with some of the characteristics of Step-7 Graph which have so far caused us to avoid it. Can you think of any particularly persuasive reasons why we should ignore these problems?

**********************
Michael Griffin
London, Ont. Canada
**********************
 
M

Michael Griffin

At 19:41 19/08/01 +1000, Jiri Baum wrote:
&lt;clip>
>> There is no reason to make the job of the graph editor any more difficult
>> than it needs to be.
>
>Well, if you're retro-fitting it to an existing solution, then you have to
>work with the constraints it has. If all you have is the ladder, with no
>special formatting marks, then that's what you've got to handle.

Which was my point. I think that support for grafcet or other similar charts should be considered as part of the fundamental design of a
PLC. It seems to be too difficult to simply tack something on later via the programming software. That doesn't mean that an existing PLC architecture can't be modified to provide this support though.

>As has been pointed out, nothing will get you back the state names; all
>you'll have is the state numbers. But even so such a tool should be useful.
>(Unless the PLC has a built-in data dictionary, but it won't.)

I'm not worried about the symbolic names, just the over-all structure of the program. I've had to deal with out of date (or missing) symbol files many times in the past, and it's not that big of a problem compared to having to replace the actual program.

>In some way it'd be not so much a programming tool as a reverse-engineering
>tool, showing you the states inherent in some (given) PLC program.
&lt;clip>
Yes, it's a reverse engineering tool, but then any ladder editor is also a reverse engineering tool in that sense. I don't need an up to date copy of a ladder program to view what is happening in a typical PLC program. The programming software "reverse engineers" it for me. We take this for granted, when in fact the PLC had to be designed to accomodate it.
I don't think that any arbitrary PLC program could reasonably be turned into a useful graph though. This is comperable to the problem you would have in turning arbitrary statment list programs into ladder.

**********************
Michael Griffin
London, Ont. Canada
**********************

 
H

Higginbotham Ricky (External)

Michael:
> Stop thinking like a software developer, and start thinking like
>someone who wants to operate a plant. If I already *have* a satisfactory
>functioning program, why would I want to write a completely new one? What I
>am asking for is a guarantee that if I *do* need to examine an existing
>program, that I will be able to read it. You may as well say that I
>shouldn't bother keeping any program backups. After all, I can always
>re-write it (eventually).
> As for whether someone else's code is painful to read, well that is
>precisely the problem that I was hoping Graph-7 would help to solve. If it
>won't help with that, then why bother?

You shouldn't write a new one if the one you have works ok. But if you don't "have" the *complete* program, then you don't have much of a choice. You're having problems because you're not acknowledging that this is a source code issue that *you* have. Graph isn't a source control program, thats not its purpose (It won't make you toast or bring you coffee either). I doubt there
is enough interest to justify a major change to the controller, that could be counterproductive.

>> I think you have this backwards. It is not "you *can* turn out a
>>similar program", rather it is "you *have* to turn out a similar program".
>>Do you find this explanation to be well received by night shift
maintenance
>>supervisors?

Like I said, my customers dont have the same problems as you. I've never run into someone who doesn't demand a complete copy of the source as part of the package.

>>Thats funny, I was just thinking that ladder really isn't that far removed
>>from assembly language. The days of ladder are numbered, much like
assembly.
<clip>
> Could it be that ladder is still around because the alternatives
are
>so far unsatisfactory implementations?

I don't use ladder. I assume its still around because people don't want to learn anything new and like to generate work for themselves. I can see some benefits to non programmers, but from a productivity and cost standpoint its just a matter of time.


> I'm not sure I understand your point. I was asking about when Mr.
>'X' *did* turn over source and got paid, he just didn't turn over the
>*correct* source. You're simply restating the "it's a source code control
>problem" in different terms.
> Source code control systems are not completely reliable for
>companies whose primary business is computer software development. Why
would
>they work any better for companies whose business is not software development?

You didn't force mr 'X' to turn over the source. No PLC will protect you from the mr X's of the world. He/She could just as easily not delivered
anything at all, it happens, though rarely. It should be someones job to make sure the Mr X's do what they are supposed to. You can blame PLC
vendors all you want but it won't help you.


> You keep approaching the problem from the point of view of a
>software developer. PLCs don't exist for the convenience of software
>developers. They exist for the convenience of the people who want to use
>them to make things. These people don't need source code control and
>distribution problems, they already have enough problems of their own.

Hah, You don't need source control? You need it so bad your advocating integrating it into PLCs (of all places)...

> This can't be a new issue, it's just new (relatively speaking) to
>me. Are their any brands of PLC which don't have this problem with grafcet
>or state diagrams, or something similar to these?

The fact of the matter is that if you approched it as a source control issue you wouldn't have anything to complain about. That *the source* is a deliverable item that you are buying, not that a machine that *seems* to work ok is enough. Theres no way around that. Instead of complaining about how its someonelses fault you are in dire straights, maybe you should take a
look at your own internal operations and make changes accordingly. PLC programming is becomming more and more like *gasp* real programming. The hardware can handle more, and the software is becoming more and more complex
as a result. Its up to you to make sure your getting what you are paying for.

Ricky Higginbotham
 
I missed the start of this topic, so I'm not sure where the PLC Books Online came in. However, we have been using SFC's for all PLC sequencing programs for about 10-12yrs, and the method we have developed may be of interest. Comments and improvements will be very welcome.

First of all, we use SFC's as a design tool to convert the written requirements from the process engineers into a graphical representation that we then get them involved with. Once the differences between an SFC and a flowchart have been understood, this always provides useful
feedback, and we spend a lot of design time 'up front' to make sure everyone agrees with these SFC's. As someone has already said, SFCs change the way you think about the problem, and force you to structure it better, especially with regard to top-level trips, etc which enable or
disable whole sub-sequences.

We have also used a package called CADEPA as a front-end SFC drawing tool, and this has back-ends for most popular PLCs. Integration with other simple ladder logic can be a bit messy however, and we often just do a manual translation of the SFC, as follows.

Allocate 1 bit for every step and every transition, and group all step bits into words which can be cleared by a MOVE instruction when the SFC is to be disabled. The actions and transitions for each SFC are grouped together, using a separate FC (Siemens) or program file (A-B) for each SFC. We prefer NOT to use S/R logic for actions, and if an output is to be on for a few steps, it will be actioned in each step. This makes restarts safer and ensures that when an SFC is disabled, all its outputs are explicitly off.

The sequencer logic goes in a separate FC (or preferably one for each SFC), and this is where we do use S/R logic. When a step is active, AND an exit transition is true, Reset that step and Set the following step, then jump to the end so that only one state change can occur per scan. This prevents cascading through several successive steps. If 'P' (initial) actions are used, extra bits are needed for the edge detection, and 'F' (final) actions also require one extra bit and a further scan before Setting the following step. Delayed and Limited actions can either have separate timers for those steps, though it is easy to have a common 'current step' timer for each SFC (as only one step can be active).

This manual translation is routine and very quick, and has the advantage of producing a ladder program which is readable and can, if necessary, be maintained by a technician who only knows ladder. We find that a lot of changes just need an extra trip, or a further contact in the Start permissives, say, and though we always advocate updating the SFC, etc, we know that often this just doesn't happen.

The manual translation we use could easily be automated and would produce ladder in a readable format and in a structure from which an SFC could be reconstructed if necessary. CADEPA does quite well, but tends to cram all the steps, actions, transitions, and sequencers into one large program
file. Graph7 is worse and we do not like its SFC facilities very much either. APT was very good for its time (especially with its Devices, etc),
but too much is hidden many levels down, and its SFC rules are too restrictive.

Hywel Thomas
_________________________________________________________

E-Mail: [email protected]
CONTROL SPECIALISTS LTD
Hayfield, UK
 
Jiri:
> >In some way it'd be not so much a programming tool as a reverse-engineering
> >tool, showing you the states inherent in some (given) PLC program.
> &lt;clip>

Michael:
> Yes, it's a reverse engineering tool, but then any ladder editor is also
> a reverse engineering tool in that sense.

Only in the most trivial sense. A tool to extract (guess) a state diagram from ladder would give you a fair bit more.

> I don't think that any arbitrary PLC program could reasonably be turned
> into a useful graph though.

Don't know on that one - that'd probably depend on the quality of the tool versus the convolutedness of the code... and how well it matches what its author expected. A good tool should give you at least a few states, though.

> This is comperable to the problem you would have in turning arbitrary
> statment list programs into ladder.

Actually, that problem (as stated) is easy enough. It won't necessarily be any ladder you'd actually want to read, but compiling statement list to ladder won't be a problem.

The problem is making the result something that's easier to understand than the original.

Jiri
--
Jiri Baum <[email protected]>
http://www.csse.monash.edu.au/~jiribvisit the MAT LinuxPLC project at http://mat.sf.net

 
Top