DEPRECATED as of Diablo (Version 2.0) UNSUPPORTED as of Hassayampa (Version 3.0)
The PLC module implements custom controller models. This allows modelers to write "C" code that is a) compiled at runtime, b) able to read and write data in other objects, c) able to override or replace the default object PLC code implemented by plc_class, and d) written in a simple, familiar and efficient programming language. The PLC module also implements a network communications object that allows PLC control code objects to communicate with each other.
To define PLC objects you must load the PLC module:
module plc { libpath "/plc/lib"; // specifies the runtime libraries incpath "/plc/include"; // specified the runtime include files }
The compiler used by the PLC module depends on the platform on which GridLAB-D is running. For Windows systems, the compiler is MinGW Version 5.1.3, which can be downloaded from SourceForge or from the PNNL GridLAB-D website at http://www.gridlabd.org/downloads/MinGW-5.1.3.exe. On Linux systems, the native compiler is used. The PATH environment variable is used to locate the compiler executable gcc.
The runtime libraries and include files are required for PLC code to be compiled and linked when a model is loaded. These must be specified correctly for your installation. Typically, these are installed in the etc/rt/include and etc/rt/lib folders in the GridLAB-D folder.
PLC objects implement a machine internally which is built from the PLC code. The machine is compiled, linked and converted to a .dll or .so file for Windows or Linux, respectively.
Note: Linux system with enhanced security must permit loading of .so files created by GridLAB-D at runtime. At this time, the simple way to do this is to disable SElinux. A better solution from a security standpoint would be to allow unconfined executables to use libraries that are not labeled texrel_shlib_t, but there seems to be no way to label anonymous libraries before they are created at runtime. See https://svn.pnl.gov/Gridlab-D/ticket/200 for more information about this issue.
Control code
PLC code is implemented in source files with the extension .plc. A PLC controller is defined using a PLC object, with the source property specifying the .plc file from which the controller is compiled:
object plc { source "myfile.plc"; parent controlled_object; // the object that myfile.plc controls }
The basic structure of a PLC controller source file is as follows:
/* define your macros */ #define HEAT 0 #define COOL 1 #define OFF 2 #define HYST 1.0 #define LOCKOUT 300.0 /* define your local data */ int state = OFF; /* link to object data */ BEGIN_DATA DOUBLE(Tair) DOUBLE(heating_setpoint) DOUBLE(cooling_setpoint) END_DATA /* map to object data local names */ #define Tair DATA(double,0) #define heating_setpoint DATA(double,1) #define cooling_setpoint DATA(double,2) /* define initialization procedure */ INIT { state = OFF; return 0; /* return the time delay to first sync */ } /* define control code */ CODE(dt,dev) /* dt is elapsed time, dev is ptr to machine data */ { switch (state) { case OFF: if (Tair<heating_setpoint-HYST) { state = HEAT; /* turn on heat */ return 0; /* state changed, force iteration */ } else if (Tair>cooling_setpoint+HYST) { state = COOL; /* turn on cooling */ return 0; /* state changed, force iteration */ } break; case HEAT: if (Tair>heating_setpoint+HYST) { state = OFF; /* turn off */ return LOCKOUT; /* lockout time */ } break; case COOL: if (Tair<heating_setpoint-HYST) { state = OFF; /* turn off */ return LOCKOUT; /* lockout time */ } break; default: break; } return 1; /* advance by 1 tick */ }
Network communications
PLC object can communicate with each other by referencing the network over which they are linked. Use the comm object to define a communications network and reference it from the PLC objects that are connected to it.
object comm { name net1; latency random.pareto(1,3); reliability 0.99; bitrate 1.5 Mb/s; timeout 10 s; } object plc { name from; source mysrc.plc; network net1; } object plc { name to; source mysrc.plc; network net1; }
To send a message to another object in PLC code, use the SNDMSG macro:
CODE(dt,dev) { if (dt>0) SNDMSG("to","test message"); return delay; }
To receive a messages from another object in PLC code, use the RCVMSG macro:
CODE(dt,dev) { char buf[1024]; char src[64]; if (RCVMSG(src,buf)) printf("message from %s is '%s'" return NEVER; }
Version
The PLC module was introduced in Allston (Version 1.0) but has only rarely been used since. It has been deprecated since Diablo (Version 2.0).
As of Hassayampa (Version 3.0) the PLC module is no longer supported but the module code will be left in Navajo (trunk) for reference purposes. You can create PLC code using intrinsic class plc function and you can create custom control code for individual object properties using external transforms.
TODO: reference the communications module when completed.