forked from kalamara/plcemu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
README
516 lines (360 loc) · 13.6 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
PLC-EMU is a Programmable Logic Controller EMUlator for automation applications on linux with digital/analog IO cards, with C functions, Ladder Diagrams,or IEC61131-compliant Instruction List/Structured Text. It is a cheap and open alternative to PLCs.
### Table of contents
[OVERVIEW](#OVERVIEW)
[DEPENDENCIES](#DEPENDENCIES)
[Hardware](#Hardware)
[Comedi](#Comedi)
[User space](#Userspace)
[Simulation](#Simulation)
[YAML](#YAML)
[Messaging](#Messaging )
[Unit testing](#Unittesting )
[CAPABILITIES](#CAPABILITIES)
[INSTALLATION](#INSTALLATION)
[CONFIGURATION](#CONFIGURATION)
[PROGRAMMING](#PROGRAMMING)
[Ladder Diagram](#LadderDiagram )
[Instruction List](#InstructionList )
[INTERFACE](#INTERFACE)
[Command Line](#CommandLine )
[Distributed UI](#DistributedUI )
[ISSUES](#ISSUES)
<a name="OVERVIEW"/>
# OVERVIEW
PLC-EMU stands for Programmable Logic Controller EMUlator. This means PLC-EMU is a tool for emulating PLCs on a Linux box, using I/O cards. This way you can build a cheap alternative to PLC's, for use with automation applications.
<a name="DEPENDENCIES"/>
# DEPENDENCIES
<a name="Hardware"/>
## Hardware
First of all, you need to install one or more digital I/O cards.
PLC-EMU works in two modes: through comedi, and in user space.
Additionally, File Simulation mode is supported in case no hardware is available.
<a name="Comedi"/>
### Comedi
In Comedi mode, all you need to do is install and set up the apropriate Comedi driver for your card, and copy the setup values to PLC-EMU's config file.
Consult www.comedi.org for a list of compatible cards, and instructions on comedi.
<a name="Userspace"/>
### User space
In user-space mode, you need to know the base IO address space of your cards,
and which area of it the card uses for reading (read offset) and writing (write
offset). For pci cards, run
> lspci -vvv
to find out the base address. The rest should be found in the cards' manual.
<a name="Simulation"/>
### Simulation
In File Simulation mode, PLC-emu can be configured to read input bytes from
an ASCII text file and send outputs to another text file.
<a name="YAML"/>
## YAML
PLC-EMU configuration files are in YAML format, and so PLC-EMU v. 2 onwards depends on libYAML.
See the official project page https://github.com/yaml/libyaml for details.
<a name="Messaging"/>
## Messaging
From version 2 onwards there are extensions for network distribution. Serialization of all network messages is done in YAML format, and the messaging layer is implemented using ZeroMQ.
Although networking extensions are disabled by default, to enable networking ZeroMQ is required.
See http://zeromq.org/ for details.
<a name="Unittesting"/>
## Unit testing
The PLC core library comes with a harness of hundreds of unit tests, however these tests require CUnit to run.
See http://cunit.sourceforge.net/
<a name="CAPABILITIES"/>
# CAPABILITIES
PLC's are real time controllers whose function is to periodically read inputs, run several real time
tasks, and control outputs, in a steady time period, which in commercial PLC's
varies usually from 2 to 10 milliseconds. PLC's are the standard platform for
automation applications, and can they can be programmed in one or more
of the 4 programming languages as defined by IEC116131-3:
Instruction List, Ladder Diagram, Function
Block Diagram, or Structured Text.
PLC-EMU emulates this function: In a configurable time cycle, it will read the
inputs from your card, run a task as programmed by the user, and send the
appropriate outputs back to the card.
Apart from inputs and outputs, PLC-EMU also holds an internal "address space"
of a user-defined number of memory variables which you may use in your programs.
It also supports Timer and Blinking Timer (Pulse) registers, whose number and function
can as well be configured by the user.
<a name="INSTALLATION"/>
# INSTALLATION
Checkout a snapshot from github, or alternatively
download the tarball from www.sourceforge.net/projects/plcemu and unzip the source files in a directory.
Then run in superuser mode
>./configure;
>make;
>make install
This should create an executable named "plcemu" and a text file named "config.yml"
If you dont have the comedi libraries, run configure with the option:
>/.configure --enable-uspace
Note that you dont need this if you have
the comedi libraries, but you havent set up comedi for some reason.
If you don't have actual hardware, run configure with the option
>/.configure --enable-sim
for text simulation mode.
If you want to enable the distributed user interface, you can configure with the option
>/.configure --enable-ui
<a name="Hardware"/>
# CONFIGURATION
Edit a config.yml file, which holds configuration variables and
their values in yml format.
An example config.yml as included:
STEP: 10 #time cycle in milliseconds
PIPE: plcpipe #UNIX path of named pipe polled for commands
#hardware
HW: STDI/O #just a text tag that appears in a footer
#user space interface:
USPACE:
BASE: 50176 #hardware address base
WR: 4 #write offset
RD: 0 #read offset
#COMEDI interface:
COMEDI:
FILE: 0 #device and subdevice nodes of comedi driver.
SUBDEV:
IN: 0
OUT: 1
#SIMULATION IO
SIM:
INPUT: sim.in
OUTPUT: sim.out
#PROGRAM
PROGRAM:
- 2
- INDEX: 0
ID: "gcd.il"
#Digital Inputs
DI:
- 16
- INDEX: 0
BYTE: 0
ID: A
- INDEX: 1
BYTE: 0
ID: B
#Digital outputs
DQ:
- 2
- INDEX: 0
BYTE: 0
ID: OUTPUT
#Memory registers (integers)
MREG:
- 4
- INDEX: 0
ID: RESULT
VALUE: 64
- INDEX: 1
ID: TEMP
#Memory variables (real numbers)
MVAR:
- 6
- INDEX : 0
ID : N
VALUE : 1.0
- INDEX : 1
ID : MEAN
- INDEX : 2
ID : M2
- INDEX : 3
ID : DELTA
- INDEX : 4
ID : ONE
VALUE : 1.0
#Timers
TIMERS:
- 2
- INDEX: 1
RESOLUTION: 10
PRESET: 10
#Blinking timers
PULSES:
- 2
Everything up to the PROGRAM tag, is system configuration.
The sequences from the PROGRAM tag onwards represent the logic blocks of the PLC.
The number after the block name represents the size of the block sequence, ie. how many block instances are allocated.
The key - value pairs after the size are the blocks' parameters.
INDEX represents the position of the specific block in the sequence, eg. input 5 would have INDEX: 5
ID is a unique string identifier for the specific block.
The rest are block - specific parameters.
These parameters can be edited in runtime.
<a name="PROGRAMMING"/>
# PROGRAMMING
You can edit a text file with a task in LD or IL in your favorite text editor and then load it into PLC-EMU (see below).
<a name="LadderDiagram"/>
### Ladder Diagram
.ld files are in Ladder diagram format.
The version of LD PLC-EMU supports, consists of the following operators and
operands.
<a name="Operators"/>
#### Operators
These are the accepted symbols that can exist along with the operands.
'-' propagates a boolean state horizontally, from left to right.
Thus, it works as a logical "AND".
'+' changes line and can join states of up to 3 different lines,
like a logical "OR" .
'|' propagates a state vertically, both ways between aligned "+" nodes.
'!' negates the state of the following operand like a logical "NOT"
'(' open contact. this propagates a state directly to an output. the following operand must be an output.
')' negate contact. this propagates the opposite of a state to an output. the following operand must be an output.
'[' set coil. if this is ON, thestate of an output is set. the following operand must be an output.
']' reset coil. if this is ON, thestate of an output is reset. the following operand must be an output.
';' end of line. anything after that is considered "comments".
Blank characters interrupt lines, so be careful.
<a name="Inputoperands"/>
#### Input operands
These can appear anywhere in a line before a '(', followed by a valid
non negative index. Valid values of indexes are dependant on the operand and
the configuration. This means, that if you have 16 timers and 64 inputs, you
can write t14 and i62, but not t45 or i567.
In every cycle, their values are polled and propagated to the diagram.
Accepted symbols (case sensitive) are:
'i' digital input state
'q' digital output state
'r' rising edge of digital input
'f' falling edge of digital input
'm' pulse state of counter
't' output of timer
'b' output of blinker
'c' true, if serial input byte equals following index
<a name="Outputoperands"/>
#### Output operands
These symbols must follow operator '(' and be followed by a valid index.
Each output operand should appear only once.
'Q' digital output
'M' pulse of counter
'T' timer
'W' write following number to serial output.
<a name="LD Example : Triple Majority Circuit"/>
### LD Example : Triple Majority Circuit
; triple majority circuit
; https://en.wikipedia.org/wiki/Triple_modular_redundancy
i0---i1----+---------(Q0
i2---i0----+
i1---i2----+
<a name="InstructionList"/>
### Instruction List
Alternatively, you can define a IEC61131-3 compatible Instruction List program in .il files.
Currently, subroutines are not implemented.
Just like standard Instruction List, all instructions store their result to an internal Accumulator register, while "ST" stores the Accumulator's value to its operand.
A line of an IL program, shall follow the format:
[label:]<operator>[<modifier>[%<operand\><byte>[</bit>]]|<label>][;comment]
Supported Operators are:
) close parenthesis (pop instruction from stack)
S set output
R reset output
AND
OR
XOR
LD load
ST store
ADD
SUB subtract
MUL multiply
DIV divide
GT >
GE >=
NE <>
EQ ==
LE <=
LT <
JMP jump to label
Modifier symbols recognized are:
( open parenthesis (push instruction to stack)
! negate
? conditional
Operands are the same as in LD, with the difference that it is assumed that they are Words (unsigned Integers), unless noted otherwise with the symbol '/'. As defined in the IEC standard, each instruction supports its own set of data types and modifiers, according to the following scheme:
Instruction |Modifiers |Data Types
----------- | ------------- | -----------
) |N/A |N/A
S |N/A |BOOL
R |N/A |BOOL
AND |!,( |BOOL/WORD
OR |!,( |BOOL/WORD
XOR |!,( |BOOL/WORD
LD |! |BOOL/WORD
ST |! |BOOL/WORD
ADD |( |BOOL/WORD
SUB |( |BOOL/WORD
MUL |( |BOOL/WORD
DIV |( |BOOL/WORD
GT |( |BOOL/WORD
GE |( |BOOL/WORD
NE |( |BOOL/WORD
EQ |( |BOOL/WORD
LE |( |BOOL/WORD
LT |( |BOOL/WORD
JMP |? |CHARACTER STRING
<a name="IL Example : GCD"/>
### IL Example : GCD
; greatest common divisor
; https://en.wikipedia.org/wiki/Euclidean_algorithm
LD %i0
ST %m0
EQ %m3
JMP?end
LD %i1
ST %m1
EQ %m3
JMP?end
while:LD %m0 ; A
EQ %m1 ; A == B
JMP?endwhile ; while(A != B)
LD %m0
LT %m1 ; A < B
JMP?reverse
LD %m0
SUB %m1 ; A - B
ST %m0 ; A = A - B
JMP while
reverse:LD %m1 ; B
SUB %m0 ; B - A
ST %m1 ; B = B - A
JMP while
endwhile:LD %m0 ;
ST %q0 ; output gcd
end: LD %m3;
<a name="C API"/>
## C API
TBD
<a name="INTERFACE"/>
# INTERFACE
Executing plcemu from the command line
Usage: plcemu [-c config file] [-h]
Options:
-c uses a configuration file like the one described in section 5, other than config.yml
-h displays this help file
<a name="CommandLine"/>
## Command Line
The default UI for version 2.0 onwards is command line based.
This is just a std prompt where the PLC's internal state in YAML format is monitored, while PLC commands can be issued.
Supported commands:
START
start plc loop
STOP
stop plc loop
HELP
display help message
QUIT
close the UI
EDIT <sequence><index><key: value>
Edit a configuration for any input, output or other sequence block.
The key: value pair can be any of the parameters in the configuration of the specific block.
FORCE<sequence><index><value>
This will force a value on a sequence block for debugging purposes.
UNFORCE<sequence><index>
Reverts the FORCE command.
<a name="DistributedUI"/>
### Distributed UI
Optionally any kind of UI and any number of UI instances can be connected over zeromq sockets, locally or remotely.
The UI should continuously receive the PLC state in YML format in a PUB / SUB configuration, and asynchronously send commands in a REQUEST / REPLY fashion.
To enable remote UI, run
>/.configure --enable-sim
<a name="Example UI client"/>
#### Example UI client
See cli-zmq.c for an example command line remote UI client that implements the same functionality as the default command line interface.
<a name="Legacy"/>
### Legacy (ncurses)
There are plans for reimplementing a ncurses based zeromq client with the same functionality as the legacy PLC-EMU UI.
Currently no ncurses dependency exists.
<a name="ISSUES"/>
# ISSUES
Please send feedback, questions, suggestions, requests, help(?) to:
(kalamara AT users.sourceforge.net)