Get MBLogic at SourceForge.net. Fast, secure and Free Open Source 
		software downloads

Help Topics

Topic Details for MBLogicEngine

MBLogicEngine - Embedded Library


Overview:

MBLogicEngine can be used as an embedded library inside another application. This allows any application to include soft logic capabilities. This is useful when creating things like automated test systems, labelling systems and other custom PC applications which may have to interact directly with manufacturing equipment. Using MBLogicEngine allows the core of your application to be written as a normal PC application while providing a familiar PLC programming language for the parts which you wish to allow users to customise and change.


Using MBLogicEngine as an Embedded Library:

MBLogicEngine is written entirely in Python. You can therefor easily write the rest of your PC application in Python. As Python is one of the major modern programming languages, it has an extensive selection of libraries, and is intended to allow rapid development of custom applications.

Alternatively, you can embed the Python interpreter in applications written in languages such as C or C++. More information on embedding Python may be found at the main Python web site http://www.python.org/. Additionally, there are versions of Python (Jython) written to run as part of a Java system and so allow Python to be used directly in Java programs. MBLogicEngine has not however, been actualy tested with Jython.


MBLogicEngine Scan Cycle:

PLCs have what is generally termed a "scan cycle". The PLC program executes one complete "logic scan" (runs the PLC program all the way through once). Then the PLC updates its I/O and performs any general overhead functions before doing another logic scan.

To use MBLogicEngine as an embedded library in your own program you would need to regularly call the function which executes the PLC program scan. A typical program would do the following:

  1. Do whatever non-PLC functions the program normally performs.
  2. Update the input portions of the PLC data table.
  3. Call the function which executes the PLC program scan.
  4. Read the output portions of the PLC data table.
  5. Sleep for a short period of time.
  6. Repeat the process from step 1.

Initialising MBLogicEngine:

In this discussion we will assume that the code which implements the soft logic functions which emulate the desired PLC already exists (i.e. you are using an existing version). Creating your own instruction set is not described here. We will also assume that you are writing your application in Python, rather than embedding Python in C (or some other language). The examples below are illustrated with the version which is modeled on the Koyo "Click" series PLC.

Importing the Libraries

First you must import the required libraries. These must include the following:

Library File Provides
PLC compiler PLCCompile.py This is the PLC compiler. This takes the PLC program source file, checks it for errors, and converts it into a form which can be executed.
PLC interpreter PLCInterp.py This executes the PLC program each scan.
Instruction library DLCkInstructions.py
(in this example)
This is a library which defines each of the PLC instructions and provides the information required to compile them. Each different PLC which is being emulated will require a different instruction library to define its instructions.
Data table DLCkDataTable.py
(in this example)
This is a library which defines the PLC data table (the data memory). Each different PLC which is being emulated will require a different data table library to define its data table.
Run time libraries DLCkLibs.py
(in this example)
This is a library which provides run time support for the PLC instructions (e.g. math functions, etc.). Each different PLC which is being emulated will require a different set of run time support libraries. These will include a mixture of "standard" libraries (used for all PLC models) and "custom" libraries (created for that model of PLC).

Example:


	from mbsoftlogicck import PLCInterp
	from mbsoftlogicck import PLCCompile
	from mbsoftlogicck import DLCkInstructions
	from mbsoftlogicck import DLCkDataTable
	from mbsoftlogicck import DLCkLibs

Initialising the Compiler

Next, you must initialise the compiler. This provides the compiler with the list of valid instructions, plus a private data table for use by instructions which must store state information outside of the normal data table (e.g. some PLCs store differentiate or "one shot" state outside of the normal data table).

Example:


	PLCCompiler = PLCCompile.PLCCompiler(DLCkInstructions.InstrDefList,  
			DLCkDataTable.InstrDataTable)

Parameter Type Description
1 DLCkInstructions.InstrDefList List The list of instructions defining the instruction set.
2 DLCkDataTable.InstrDataTable Dictionary An empty dictionary for storing private instruction data.

The compiler should be initialised once only when your application starts up. Once it is initialised, it may be called as many times as desired until your application exits.


Compiling the PLC Program:

Before the PLC program can be executed, it must be loaded into memory and then compiled. Compiling the PLC program checks it for errors and prepares it for execution.

Loading the PLC Source Program into Memory

The compiler has a function called "ReadInFile" which reads in the source file from disk. You must pass it a string which indicates the name of the file containing the PLC program.

Example:


	PLCCompiler.ReadInFile('demoplcprog.txt')

If the file is not present or cannot otherwise be read, an exception will be raised which you must deal with.

Example:


	try:
		PLCCompiler.ReadInFile('demoplcprog.txt')
	except:
		pass
		# Do something about the error.

If there were any compile errors, we can ask for a description. The error messages are contained in a list.

Example:


	# Get any compiler error messages.
	CompileErrMsgs = PLCCompiler.GetCompileErrors()
	
	for i in CompileErrMsgs:
		print(i)

This will produce an output something like the following:

Example:


	Error in line 12 for STR CTD100
	 - One or more parameters is of an incorrect type.

Compiling the PLC Source Program

Once the PLC source file has been loaded into memory, it must be compiled. This involves checking the PLC program for obvious errors and then converting it into a form which allows it to be executed.

Example:


	plcprogram, instrcount, CompileErrors = PLCCompiler.CompileProgram()

The "CompileProgram" function takes no parameters, but it does return three values. These are:

Return Value Type Description
1 plcprogram Code Object The compiled PLC program. This will be passed to the interpreter to execute.
2 instrcount Integer Indicates the number of instructions compiled.
3 CompileErrors Boolean Indicates whether and errors were encountered. If this is False, then no errors were found. If it is True, then at least one PLC program error was found, and the compiled program is not valid and you should stop at this point.

Some types of errors may result in an exception which you must deal with.

Initialising the Interpreter

The interpreter must be initialised with the PLC program as well as the data tables and various libraries.

Example:


	MainInterp = PLCInterp.PLCInterp(plcprogram, 
			DLCkDataTable.BoolDataTable, DLCkDataTable.WordDataTable, 
			DLCkDataTable.InstrDataTable,
			DLCkLibs.TableOperations, DLCkDataTable.Accumulator,
			DLCkLibs.BinMathLib, DLCkLibs.FloatMathLib, DLCkLibs.BCDMathLib,
			DLCkLibs.WordConversions, DLCkLibs.CounterTimers, DLCkLibs.SystemScan)

The parameters in the above example are :

Parameter Type Description
1 plcprogram Code object The compiled PLC program from the compiler.
3 DLCkDataTable.BoolDataTable Dictionary The part of the data table used to store boolean data table values.
4 DLCkDataTable.WordDataTable Dictionary The part of the data table used to store word data table values.
5 DLCkDataTable.InstrDataTable Dictionary The part of the data table used to store private data table values. Not all PLCs make use if this but it is still required.
6 DLCkLibs.TableOperations Library This is a library used to provide libraries for instructions which operate on multiple registers.
7 DLCkDataTable.Accumulator Library A library which can provide accumulator and stack functions. This is not used in this version, but the parameter must still be present.
8 DLCkLibs.BinMathLib Library The binary math library. This provides all the math functions.
9 DLCkLibs.FloatMathLib Library The floating point math library. This is not used in this version, but the parameter must still be present.
10 DLCkLibs.BCDMathLib Library The BCD math library. This is not used in this version, but the parameter must still be present.
11 DLCkLibs.WordConversions Library A library which provides miscellaneous word conversion functions.
12 DLCkLibs.CounterTimers Library The library which provides counter and timer functions. Timers and counters are usually different enough between different models of PLC that they need to be implemented separately for each.
13 DLCkLibs.SystemScan Library A library which provides system scan overhead functions. These are things which must be updated between each scan..

These libraries should be already provided with a working version of MBLogicEngine and do not have to be created just to use it.

When to Compile and Initialise the Interpreter

The PLC program must be loaded, compiled, and the interpreter initialised at least once before the PLC program is executed. In addition, the PLC program may also be reloaded, recompiled, and reinitialised at any time. Re-initialising the interpreter does not affect the data table contents.


Executing the PLC Program:

Once the PLC program has been compiled and the interpreter initialised with it, the PLC program may be executed.

Updating the Data Table

The application must read and write the data table in order for MBLogicEngine to receive updated input information or to write the output information to the actuators. The interpreter provides several functions to perform this. The functions to perform this are:

Function Parameters Return Value Description
1 GetBoolData List Dictionary This is used to read the boolean data table. It takes a list of strings. Each list element represents a boolean data table address label. It returns a dictionary with the list elements as dictionary keys, and the data table data as values.
2 SetBoolData Dictionary N/A This is used to write to the boolean dat table. It takes a dictionary. The dictionary keys must be data table address labels, and the dictionary values are to be the updated data table values.
3 GetWordData List Dictionary This is used to read the word data table. It takes a list of strings. Each list element represents a word data table address label. It returns a dictionary with the list elements as dictionary keys, and the data table data as values.
4 SetWordData Dictionary N/A This is used to write to the word dat table. It takes a dictionary. The dictionary keys must be data table address labels, and the dictionary values are to be the updated data table values.
5 GetInstrDataTable N/A Dictionary This returns the entire instruction data table as a dictionary. The instruction data table is used to hold private instruction data and there is normally no reason to use this function.
6 SetInstrDataTable Dictionary N/A This takes a dictionary as a parameter and replaces the entire instruction data table. There is normally no reason to use this function.

Example:


	// Set the boolean data table.
	MainInterp.SetBoolData({'X17' : True, 'X277' : False})
	
	// Read the boolean data table.
	BData = MainInterp.GetBoolData(['Y1', 'Y367', 'C50', 'CT100'])

With GetBoolData, SetBoolData, GetWordData, and SetWordData, there is no need to request or write to data table addresses which are not used.

Special Scan Overhead Functions

Some additional functions may need to be executed as part of the scan cycle but are not part of the interpreter. The details of these depend on the particular PLC being emulated.

Calling the Interpreter

When the interpreter function "MainLoop" is called, the PLC program is executed for one complete logic scan. This function takes no parameters. Some run-time errors may cause an exception which must be handled by the application program.

Example:


	MainInterp.MainLoop()

Reading the Exit Code

After the interpreter returns, a function ("GetExitCode") may be called to read exit and diagnostic information. The following information is returned:

Return Value Type Description
1 ExitCode String his is a text string indicating the reason the PLC program exited. The exit code 'normal_end_requested' means the program has exited normally.
2 ExitSubr String This is the name of the subroutine which was active when the program exited.
3 ExitRung Integer This is the rung number which was active when the program exited.

Example:


	ExitCode, ExitSubr, ExitRung = MainInterp.GetExitCode()

Exit Codes

If no run-time errors were encountered, the program should exit with an exit code of "normal_end_requested". This exit code is set by the IL instructions that normally end the program scan. Any other exit code indicates that a run time error was encountered.

An exit code of "unexpected_end" indicates that the end of the program was encountered unexpectedly. The usual cause for this is forgetting to include the IL instruction that ends the program scan. If an "end" instruction is not encountered, the program scan will "fall off the end" of the program. There is usually no adverse consequence to this other than the expected exit code not being set.

An exit code of run "exception_error" indicates that an undefined run time error was encountered. This is always an error that terminates the scan immediately. This error should not be encountered under any normal circumstances and always indicates a serious error which prevents the program from executing correctly.


Complete Example:

The following shows a simplified example. This examples omits exception handling. The first example shows the code used to initialise and compile the PLC program.


	############################################################
	
	from mbsoftlogicck import PLCInterp
	from mbsoftlogicck import PLCCompile
	from mbsoftlogicck import DLCkInstructions
	from mbsoftlogicck import DLCkDataTable
	from mbsoftlogicck import DLCkLibs
	
	############################################################
	
	# Compiler for PLC program.
	PLCCompiler = PLCCompile.PLCCompiler(DLCkInstructions.InstrDefList, 
		DLCkDataTable.InstrDataTable)
	
	# Read in the PLC program.
	PLCCompiler.ReadInFile('demoplcprog.txt')
	
	# Compile the PLC program.
	plcprogram, instrcount, CompileErrors = PLCCompiler.CompileProgram()
	
	# Get any compiler error messages.
	CompileErrMsgs = PLCCompiler.GetCompileErrors()
	
	for i in CompileErrMsgs:
		print(i)
	
	# Initialise the interpreter with the PLC program and data table. 
	if (not CompileErrors):
		MainInterp = PLCInterp.PLCInterp(plcprogram,  
			DLCkDataTable.BoolDataTable, DLCkDataTable.WordDataTable, 
			DLCkDataTable.InstrDataTable,
			DLCkLibs.TableOperations, DLCkDataTable.Accumulator,
			DLCkLibs.BinMathLib, DLCkLibs.FloatMathLib, DLCkLibs.BCDMathLib,
			DLCkLibs.WordConversions, DLCkLibs.CounterTimers, DLCkLibs.SystemScan)

The second half of the example below shows code which must be called each scan.


	# Update the data table with new inputs. In a real application the values
	# would be variables passed in from the main application. A similar function
	# is available for the word data table. 
	MainInterp.SetBoolData({'X17' : True, 'X277' : False})
	
	# This causes the PLC program to be executed once.
	MainInterp.MainLoop()
	
	# This is gets the updated data table elements to be passed to the rest of
	# the application. 
	BData = MainInterp.GetBoolData(['Y1', 'Y367', 'C50', 'CT100'])
	
	# Get the program exit code to see if the PLC program exited normally, or
	# if there was an error.
	ExitCode, ExitSubr, ExitRung = MainInterp.GetExitCode()