INDUSTRIAL CONTROLLERS: PAC,PLC & LINUX

For more info visit: Absolutelyautomation.com


Linux support for industrial hardware like PAC or PLC, in the case of the big and well known brands is basically non-existent. Some hardware is based on "exotic" architectures, however the vast majority have in their guts an x86 or ARM based system (Linux friendly architectures!), but the development and management tools remain developed for Windows operating system!

There are so many reasons (commercial, technical, philosophic) that perpetuates same situation. Searching on the web, we can find some PLC/PAC related applications developed for Linux, but practically all of them are communication drivers (for the open and well documented protocols!) , developed by enthusiasts


OPTO22, FORTH

Some time ago, developing a little implementation of RFB protocol in an PAC, in a Wireshark session deliberate unintentionally left open, when uploading a new program, some clear text strings were visible, probably control commands or parts of the program being downloaded!

Digging a bit more in the application for program loading, an interesting option was discovered: "Download FORTH File". Searching in the web "Opto22" and "FORTH" throws some papyri scanned manuals: How to program Opto22 LC2/LC4 (very outdated hardware!) controllers in FORTH!

With that document, the next natural thing was to open all the generated files with a HEX editor and search some FORTH code inside. The results of the analysis were:

* Manufacturer's application generates many types of files (config, initializations, program code)
* All files were encoded in clear text.
* The programming language used wasn't strictly FORTH

Finding that not a single standard programming language was used to program a PAC is a little pitfall, however, finding that all files were encoded in clear text are good news for programming PACs from non factory supported operating systems like Linux, Mac, etc.

DOWNLOADING PROGRAMS.

The first step for an approaching to an alternative programming tool, is to know how the original application download an already created program. A simple blink application was used and the way the application talks with the PAC was analyzed using Wireshark. After downloading many different programs, the event sequence was discovered:

Also, there are a couple of additional commands like get PAC info (available memory, errors, etc), stop program, start program, erase program, etc. that were investigated and implemented!

A python app named O22termeng was developed, is capable of downloading programs to the PAC and send the aforementioned commands

GENERAL STRUCTURE OF A PROGRAM

Now, having a very basic PAC management tool, the control strategy files were studied in detail, and the info gathered is the following:

A sample control strategy "BLINK" was created. It is composed of two tasks: One toggles a digital output and increments a counter every second. The second one look if the counter is exactly divisible by 5 (modulo 5) and turns on a digital output if the condition is valid, if not turns it off

BLINK.crn1

In this file there is a line where lies the name of the program " BLINK ". The rest of the lines look like some kind of memory space assignation for variables and I/O. No changes were noticed in those lines with different downloaded and analyzed programs.

_END NEW $$$.RUN
: FILENAME ." BLINK " ;
1 0 $VAR *_HSV_SEMA
1024 0 $VAR *_HSV_TEMP
200 0 $VAR *_HSV_INIT_IO
0 IVAR ^_HNV_INIT_IO

BLINK.crn2

In this file three things were found:

- Tasks that compose the program: Powerup, slowblink, _INI_IO. Powerup is the default task, can't be renamed nor deleted. slowblink was created in the manufacturer program, and _INIT_IO is probably is an internal task that initializes hardware automatically

- Variables used in the program: countervar and modvar

- I/O hardware pin alias: In this particular case digital pins 0 and 3 were assigned alias:
DIGITAL_OUT_1 and DIGITAL_OUT_4

0 TASK &_INIT_IO
0 TASK &Powerup
0 TASK &slowblink
0 IVAR ^countervar
0 IVAR ^modvar


$0000000000000000.. 32769 1.000000 0.010000 0.000000 2001 $7F000001 0 MBOARD %SELF_RACK
SPOINT 0.0 OUTPUT 0 %SELF_RACK
0 POINT ~DIGITAL_OUT_1
SPOINT 0.0 OUTPUT 3 %SELF_RACK
0 POINT ~DIGITAL_OUT_4

BLINK.crn3

This file is a little bit longer than the previous. Seems like in the initial part, tasks, and all types of variables are grouped in arrays and near the end initialization of countervar and modvar to 0 are visible. Notice also that the digital pins are by default inputs "0", and the ones that will be used as outputs must be written to "1" ($..0009 pins 0 and 3)

: W_INIT_IO
CONFIG_PORTS
$0000000000000009.. %SELF_RACK ENABLES!
" %SELF_RACK (1/1)" *_HSV_INIT_IO $MOVE 0 ^_HNV_INIT_IO @!
%SELF_RACK ENABLE
" Initializing variables" *_HSV_INIT_IO $MOVE
0 ^countervar @!
0 ^modvar @!
" " *_HSV_INIT_IO $MOVE

Task files (Powerup.ccd, slowblink.ccd)

In these files lies the program code, for each task programmed. There are two things here: code blocks, and code block list near the end.

T: T0
DUMMY
0_0
0_1
0_3
0_5
0_7
0_10
T;
&Powerup ' T0 SETTASK

Each block is labeled a_b, where a is task number and b is a "block id" inside that particular task. Block numbers coincide with the block numbers shown in the manufacturer's application and probably are used for the block-by-block debugging mode.

The following is an example of a code block:

: 1_1
TRUE

1 LINE.NUM
^modvar @@
1 <
LAND
IF -4 ELSE -3 THEN JUMP ;

Each label is preceded by a colon (:), next LINE.NUM instruction preceded by a line number. This line number coincides with line numbers shown in the manufacturer's development app and are probably used for line-by-line debugging mode

Some portions of the code, closely resemble FORTH specially the IF statement where the condition was BEFORE the word "IF" !

A block finishes with a JUMP instruction followed by a semicolon (;). JUMP instructions are relative, not absolute.