coder . cl » proview http://coder.cl web developer & system programmer Sat, 03 Nov 2012 12:37:47 +0000 en hourly 1 http://wordpress.org/?v=3.4.2 proview i/o layers http://coder.cl/2012/11/proview-io-layers-2/ http://coder.cl/2012/11/proview-io-layers-2/#comments Sat, 03 Nov 2012 12:37:41 +0000 Daniel Molina Wegener http://coder.cl/?p=2940 ProView provides a nice I/O API. All devices are controlled through a pair of API calls for reading and writing data from signals. You cannot use channels directly, so every channel should be bound to signals for I/O. All write requests are made using io_write and read requests are made using io_read, where both methods have their context in the ProView application. All devices that should be controlled through any ProView application should use the Process flag set to User2 with value 8. The problem is how to deal with I/O calls centralized in two API calls rather than using device specific I/O calls. Your code should be consistent enough to support that I/O method.

We are currently using Hierarchical State Machines, and once a state requires channel usage, the state machine stops its executions, runs the I/O calls io_read and io_write and continues its execution on the next scan cycle. Device synchronization is using single boolean variables holding read/write states as semaphores and reviewed on each task request. The entire framework is designed as it is running a PLC program, so you have a scan → read → write cycle. All state machines are pausing its execution on channel requests because they must not use the communication channel concurrently and we cannot use a locking mechanism.

We have logical composite modules to hold the device structure, where a device uses the same physical levels as rack, card and channel, but with its logical level as rack, card and signal. This allows a better organization and binding of devices along the project structure. Modularity is important, so we are using device classes to hold each device structure. Channels remain untouched, and we are writing and reading data exclusively from signals, despite we know some calls to access channels directly.

The device organization is pretty clear. Since we are using ModBus, we organize signal groups according to register groups in the device for each register block that we want to read or write. Even more for coil registers, where the are almost organized in 2^n groups, thanks to the class BaseComponent, which allows that kind of abstraction, rather than using ModBus modules and cards directly.


© Daniel Molina Wegener for coder . cl, 2012. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2012/11/proview-io-layers-2/feed/ 0
hierarchical state machines http://coder.cl/2012/10/hierarchical-state-machines/ http://coder.cl/2012/10/hierarchical-state-machines/#comments Mon, 29 Oct 2012 15:33:00 +0000 Daniel Molina Wegener http://coder.cl/?p=2921 I need to work with a hierarchical state machine. The main problem that I am currently facing is how to pass messages or trigger events on each event transition. Since I am using C Plus Plus, I will use class methods. In this case, I will use a hardware device class method. On each state transition, an event will be thrown, and the given event should trigger an action — in this case a class method — that will complete the state transition. The advantage of the hierarchical state machine is the fact that you can manage composite hardware devices without problems, because each sub-device can be handled individually with its own state, but increases the complexity of the program.

On this case, I will iterate over the list of units on the scheduler — where each unit is a composite device — it will assign a new work state on each device, calling the run method on the device object. The run method will launch the child state machine of the required action, but the parent state machine only has few states storing the device status, so the processing scheduler knows which event should be triggered on each scan cycle. The required state transitions on the parent state machine, which are informational rather than hardware related, will be useful handling nested event handling.

Each cycle will determine whether read or write actions should be triggered, even if they are manual or automatic operations on each device, and only then the program will be able to call read and write once they are required. There are some actions not using the communication channel, so I can avoid calling read and write, enhancing the application performance a little, but still I will need to check the device state to check for some automatic reads, required to display the device state and ModBus holding registers.

You can find several models of hierarchical state machines, but I prefer to write one using events bound to class methods, where each class method drives an action on the device. This approach is simpler than others using signals and similar event handling methods, but I need to keep the source code as simple as possible, because increasing the complexity should increase the development time. Finally, the unit class will be only a gateway to the each hardware device, where each state will be triggered by the scheduler. Before this model, I was using a priority queue using messages, very similar to message queues, but is required on this system, to have direct access to the device state, and that message queue is not so synchronous as it is required, where a direct feedback from the device should be placed on each state transition.

Now I have finished the scheduler and the state machine processor, I just need to complete the integration between each component and I will deliver the new device management application. Also, the HMI has changed a little, and the new model allows some direct actions like resetting the device and its state.


© Daniel Molina Wegener for coder . cl, 2012. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2012/10/hierarchical-state-machines/feed/ 0
mutability on states machines http://coder.cl/2012/09/mutability-on-states-machines/ http://coder.cl/2012/09/mutability-on-states-machines/#comments Sun, 30 Sep 2012 15:52:32 +0000 Daniel Molina Wegener http://coder.cl/?p=2814 The basic definition of a state machine is a set of states S, with a subset of initial states I, another subset of final states F, and a set of transitions between states T, and every state s’Ss”S where ISFS, and each element on T { s’, s”, h }, with s’ as the current state, s” as the next state and h as the state action. On my current automation project where I am using ProView, I have each device controlled by state machines, and each user or automatic control request is queued on a priority queue, where the highest priority is executed replacing any previous execution state, because we have only one communication channel. So the basic state machine definition is not enough to hold every environmental variable that we are using to control each device.

The state machine model includes on each transition a basic model defined as { s’, s”, g, f, h }, with s’ as the current state, s” the next state, g a boolean function evaluating the environment, f as guard boolean function preventing errors and h as action function. Where g is similar to f, but it covers the feasibility of the state change, because it evaluates if the device state (offline, online + automatic, online + manual), and f evaluates if the request is feasible according to the current composite device state (pump + valve + manometer), where each operation request was written as follows.


struct fcu_request_s {
    bool     channel;
    bool     done;
    bool     nobreak;
    int      errors;
    int      cycle;
    fcu_io  *device;
    pwr_tUInt16          operation;
    fcm_task_prio_t      priority;
    struct timespec      start_t;
    struct timespec      current_t;
    struct timespec      end_t;
    fcu_state_machine_t  *machine;
};

Where every boolean member is evaluated using the boolean function g, integer members are evaluated using the boolean function f, and if both function are not blocking the action, the action h is executed.

HMI

HMI (the image was modified to be shown).

Finally the state machine is mutable, because there are dynamic states which are triggered by boolean functions, and every transition is not strict, they are only a behaviour template rather than strict states to be used on each transition. From the processing node, each HMI signal is checked against the boolean functions, and each state transition is strictly evaluated before executing the action. This is more representative than single state transitions from the original state machine model, allowing better control. Where we are using dynamic programming to hold state transition tables and previously evaluated boolean functions which are common to the composite device state.


© Daniel Molina Wegener for coder . cl, 2012. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2012/09/mutability-on-states-machines/feed/ 0
dynamic control on state machines http://coder.cl/2012/09/dynamic-control-on-state-machines/ http://coder.cl/2012/09/dynamic-control-on-state-machines/#comments Fri, 14 Sep 2012 12:35:00 +0000 Daniel Molina Wegener http://coder.cl/?p=2786 We are doing pretty good advances on the ICS/DCS that we are doing. The current code base is using the STL std::priority_queue as operation request queue, but we are changing the task request priority each time that the communication channel is being used by any transition that requests the Profibus channel. We cannot saturate the communication channel with requests, because it runs on a very low bandwidth connection, so each request should be correctly measured, where all operations on the machinery is being directed by states machines with dynamic priorities of execution, and the STL priority queue is doing a good job. But was a little bit complex to think in terms of source code with the model presented as state diagrams and flow control diagrams on a whiteboard, and took me about one week to finish the final skeleton of the primary source code.

Now just remains operation details, such as state machine definitions for each operation that is required for the machinery operations that system will handle. The system has two main kinds of operations, automatic operations and manual operations, where manual operations have a higher priority than automatic ones, also automatic operations can be interrupted by manual operations, so the state machine that is running an automatic operation can be interrupted by any manual operation. Each state transition is monitored checking the system state, looking if a requested a manual operation should replace the current automatic operation, or the automatic operation should be interrupted by another automatic operation with a higher priority.

The algorithm — now that is implemented and not placed as diagram on the whiteboard — looks much simpler, and the basic algorithm looks as follows.


req = dev_get_request(MAIN_CONFIG, NUM_DEVICES);
if (req != NULL) {
    queue_task(req);
}

while (!channel && (req = check_queue())) {
    if (req->done) {
        break;
    }

    req->device->run(req);
    if (!req->channel) {
        continue;
    }

    sts = io_write(io_ctx);
    if (EVEN(sts)) {
        errh_Fatal("ra_fcm: io_write error, %m", sts);
        fcm_io_alarm(req->device, FCM_IO_WRITE);
    }

    sts = io_read(io_ctx);
    if (EVEN(sts)) {
        errh_Fatal("ra_fcm: io_read error, %m", sts);
        fcm_io_alarm(req->device, FCM_IO_READ);
    }

    if (req->nobreak) {
        channel = false;
    } else {
        channel = true;
    }
}

The dev_get_request method checks if there is a pending request, automatic or manual, if there is a pending request, it is being queued, and immediately the process starts processing the queued items, where they can be finished in one step or not, and the device runs the state machine referenced by the request, if the state machine transition uses the I/O channel, the ProView methods io_write and io_read are called, then, if the transition requests a no-break operation to make a continuous usage of the communication channel, it keeps running the state machine. Otherwise the state machine breaks its operation and seeks another operation request in the queue. The check_queue method seeks the proper prioritized request on the queue, where its priorities are changing inside the state machine on the run method.

But the state machine runner — placed on the device as run method — as an abstraction of the managed device by the priority queue, where there are several devices to manage, schedules their tasks using a simple algorithm. The real complexity is placed on the operation of each device, and the algorithm itself is an abstraction of the generalized state machine that we are running.


if (dev_state == DEV_ST_INACTIVE) {
    dev_state = DEV_ST_ONLINE;
}

request->nobreak = false;
machine->channel = false;
request->channel = false;

for (c = 0; c < machine->num_states; c++) {
    tr = &(machine->states);

    if (tr->curr_st != dev_state) {
        continue;
    }

    if (!tr->guard(tr, machine, request, this)) {
        break;
    }

    if (!operate(tr, machine, request)) {
        break;
    }

    errh_Info(st_msg_fmt, fcu_state, tr->next_st, tr->curr_st);
    dev_state = tr->next_st;

    if (tr->next_st == machine->final_state) {
        request->done = true;
        break;
    }

    if (tr->channel) {
        chn = true;
        request->nobreak = tr->nobreak;
        machine->channel = true;
        request->channel = true;
        break;
    }

}

return chn;

The guard checks environmental variables, and if there are good environmental conditions to operate, then it starts operating the device according to the current transition, that holds the action as enum type, with a simple switch statement to check the action that should be taken on the state transition. On a successful operation and the proper prioritization, the queue is reordered outside the state machine runner, allowing queued operations to trigger alarms if they are not finished, among other similar error checking and environment checking routines. So, the system keeps working, alerting the user through the HMI if there is any condition that never meets the required operation. ProView has several ways to alert users about the system conditions, and we are using almost everything that we can. I think that this system is very well structured and now running dynamic priorities is even more stable than using plain task requests, mainly due to environmental variables. This scheduler looks preemptive, but it is not.


© Daniel Molina Wegener for coder . cl, 2012. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2012/09/dynamic-control-on-state-machines/feed/ 0
scheduler using priority queues http://coder.cl/2012/09/scheduler-using-priority-queues/ http://coder.cl/2012/09/scheduler-using-priority-queues/#comments Sun, 09 Sep 2012 13:55:58 +0000 Daniel Molina Wegener http://coder.cl/?p=2768 As you know I am working on an Industrial Control System — ICS/DCS to be more specific — and this system requires a task schedule to activate some pumps with a very strict calendar, monitoring the amount of liquid that has been passed through the valve, and it should allow manual operations, interrupting the automatic operation of that node on the plant. This seems to be difficult to implement, as I wrote in past posts, we are using a priority queue that contains task requests, where every priority is entirely dynamic, and dependent on the state of the current state machine that is being executed according to the operation request.

During the state machine execution, each state transition has a guard ensuring that the step that will take place on the transition is guaranteed to be executed depending on the environment, if not the step is reserved to the next PLC scan cycle — do you remember that ProView operates C and C++ applications like PLC programs?. The same guard ensure that the operation on the pump will take the required minutes to deactivate the pump, meeting the task calendar. Once the pump is active, its task priority — which is hold on the request data structure — changes its priority, and using the top() and pop() methods of the STL std::priority_queue, is extracted from the queue, the priority is changed, and it is pushed again on the queue using the push() method.

All requests that are using the communication channel have the higher priority, because we have only one communication channel, so we must ensure some concurrency on the channel usage, and we call the io_read() and io_write() ProView functions only once it is required, ensuring that the communication channel is used by one device at time. I think that this is the biggest problem of the system, because the communication channel is very small, and shared between several devices, and it must be used concurrently. But locks are not an option. If the channel blocks due to its usage, the system should continue its work and must keep its system review — reviewing channel status and signal status, and reviewing the error status for several devices.

Since several requests are not using the communication channel, the queue never gets saturated, and every transition is executed. It only blocks on communication channel usage, but it calls the io_read() and io_write() ProView functions rather than using some kind of lock, like semaphore or similar one. Also, errors are not allowed, the code should not have any programming error, and it is being traced by strace(1) and valgrind(1). Also, we are thinking to check the model using spin(1), I have started some Promela code related to the processing model, at least it looks well for now. It will probably get more complexity on the future, but the model looks well, and the code seems to be really good.


© Daniel Molina Wegener for coder . cl, 2012. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2012/09/scheduler-using-priority-queues/feed/ 0
generalized state machines http://coder.cl/2012/08/generalized-state-machines/ http://coder.cl/2012/08/generalized-state-machines/#comments Fri, 03 Aug 2012 11:59:56 +0000 Daniel Molina Wegener http://coder.cl/?p=2644 Defining state machines is not so hard as it appears. Initially you can build constructs that can help on building automata processing much friendly than using plain code. Starting from the idea that you can place your state machine inside data structures allowing friendly editing without modifying the processing code. Any stateful processing can be migrated to state machines. As any automata can be represented in a state diagram and then it can be migrated to plain data structures. Even if you are using a purely functional programming language, you can place a stateful processing data structure to be processed as automata.

On a recent project, the project manager has requested to me to code a state machine. Its initial design is not generalized. Along two design sessions and some sample code and constructs I think that I have finally made an abstract state machine, with various reductions, based on the model designed by the project manager on the design sessions, structured mostly as automaton, with very simple state transitions, but I have added error and wait conditions, allowing more friendly error processing and wait events. Mainly because as ProView application it has several similarities to PLC programs, where each cycle can operate one time due to the protocol restrictions, but also it allows multiple operations in one cycle because it can send larger packages with multiple requests.

Generalized State Machine

Generalized State Machine

On each cycle, once the I/O layer is initialized, the device error state is checked, on failure it reports errors using ProView alarms, waits the next cycle and then operates again checking the device state. If no error is detected, it operates immediately once it can do it according to its cycle. And the state machine above is a generalized or abstract state machine, considering CST and OST as checking and operating states, where it is has a normalized transition between both states with the proper error handling states.


typedef struct fcu_sm_trans_s fcu_sm_trans_t;

struct fcu_sm_trans_s {
    fcu_op_state cst;
    fcu_op_state nst;
    fcu_op_state fst;
    bool alarm;
    bool wait;
};

/* pump and valve transtion table */
fcu_sm_trans_t AUTO_FCU_TRANSITION[] = {
    { FCU_ST_OFFLINE             , FCU_ST_DISCONNECTED      , FCU_ST_OFFLINE      , false, wait  }
    , { FCU_ST_DISCONNECTED      , FCU_ST_COPY_READ_POS_P   , FCU_ST_ERROR        , true , false }
    , { FCU_ST_COPY_READ_POS_P   , FCU_ST_COPY_WRITE_POS_P  , FCU_ST_ERROR        , true , false }
    , { FCU_ST_COPY_WRITE_POS_P  , FCU_ST_COPY_READ_POS_V   , FCU_ST_ERROR        , true , false }
    , { FCU_ST_COPY_READ_POS_V   , FCU_ST_COPY_WRITE_POS_V  , FCU_ST_ERROR        , true , false }
    , { FCU_ST_COPY_WRITE_POS_V  , FCU_ST_READ_POS_P        , FCU_ST_ERROR        , true , false }
    , { FCU_ST_READ_POS_V        , FCU_ST_READ_POS_V        , FCU_ST_ERROR        , true , false }
    , { FCU_ST_READ_POS_V        , FCU_ST_READ_BURN         , FCU_ST_ERROR        , true , false }
    , { FCU_ST_READ_BURN         , FCU_ST_READ_PRES         , FCU_ST_ERROR        , true , false }
    , { FCU_ST_READ_PRES         , FCU_ST_WRITE_POS_P       , FCU_ST_ERROR        , true , false }
    , { FCU_ST_WRITE_POS_P       , FCU_ST_WRITE_POS_V       , FCU_ST_ERROR        , true , false }
    , { FCU_ST_WRITE_POS_V       , FCU_ST_READ_POS_P        , FCU_ST_ERROR        , true , true  }
    , { FCU_ST_ERROR             , FCU_ST_OFFLINE           , FCU_ST_ERROR        , true , true  }
};

And here you have sample transition table for one the controlled devices — which is not the final transition table, because we still do not have the final model implemented, but we have the proper abstraction to implement it — with error handling and wait conditions. The model is very similar to functional guards, where there are some conditions checked, including the error condition, and then the state is processed passing to the next state in the next cycle. Seems that the original model for this kind of processing is present in this paper, and seems that it is fully meeting an IPO model.


© Daniel Molina Wegener for coder . cl, 2012. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2012/08/generalized-state-machines/feed/ 0
dynamics and actions in proview http://coder.cl/2012/07/dynamics-and-actions-in-proview/ http://coder.cl/2012/07/dynamics-and-actions-in-proview/#comments Thu, 26 Jul 2012 12:17:45 +0000 Daniel Molina Wegener http://coder.cl/?p=2628 Graphical objects in ProView are providing two types animations and behavior attributes, where both can be highly customized. Dynamics are those animations related on how the object operates with the environment — mouse and keyboard — and the logical plant nodes. At the other side, actions are those XTT commands triggered with the user interaction. So, for example we have the Electric > ControlSwitch sub-graph, which has the action DigShift, but we can change the DigShift action to ToggleDig, allowing a digital input switching between True and False, and preserve the rotate animation which is inherited from its definition.

Is really nice to have such type of graphical objects, because we can mix different types of animations, user interface behaviour and XTT commands, allowing almost any type of control to be created, including custom sub-graph objects, which can be linked with custom C or C++ programs. You just need to remember the $object and $local object references once your are instantiating the sub-graph object, mainly once they are pointing to logical plant nodes. Thanks to this flexibility, you can manage for example a simple PushButton, and make it work as SwitchButton, and make it work as ControlSwitch to toggle a digital input value.

Rotate Animation Configuration

Rotate Animation Configuration

For example we can use a PumpAnim2 sub-graph object and change its dynamics to be a rotating animation, rather than using its default, we just need to ensure that the dynamic is linked to the proper object — for example an analog signal on rotate animations — and configure each dynamic attribute correctly, as it was done using the rotate facto on the case above.

Toggle Button

Toggle Button

You have many options to use in your HMI once you are building your ICS applications using ProView. You can read the Design Guide, the Ge Reference Manual, the SubGraph Reference Manual and the Operator Guide. The Operator Guide mainly contains the list of XTT commands, if you need to use any XTT script based commands to work the logical plant. This is really nice, because you can trigger — with a proper design — custom actions inside your rt_appl based application if you need make something complex, like distributing some task in a period, like moving a pump for 20 minutes and monitoring how filled is a tank, blocking its pumping action if it is required. Tasks like that are complex to implement using PLC programming, so a good C or C++ application can do that.


© Daniel Molina Wegener for coder . cl, 2012. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2012/07/dynamics-and-actions-in-proview/feed/ 0
abstracting plant nodes in proview http://coder.cl/2012/07/abstracting-plant-nodes-in-proview/ http://coder.cl/2012/07/abstracting-plant-nodes-in-proview/#comments Sun, 22 Jul 2012 22:48:33 +0000 Daniel Molina Wegener http://coder.cl/?p=2619 As you know I am working on a ProView project. It has a logical and physical distinction between plant and station nodes. Physical nodes are mainly controlled by logical nodes, including user defined applications written in C, C++ or Java. On this case we are using C and C++, C for low level ProView calls and C++ to create a nice object oriented interface. A very good approach is found on ProView General Data Handler or GDH API, where you can have access to the full node hierarchy using GDH calls. This allows managing nodes in all levels, even if you want to create new nodes in run-time. This is very nice, so I have defined a C++ class device to manage each device automatically and due to the algorithm complexity we cannot use PLC programming.

To abstract plant nodes you have two kinds of object attributes that you can use. The $IoConnect and the $SigChanCon will bring you the proper plant node reference to control the signal related device. For example if you use the gdh_NameToObjid() GDH call on that attribute reference, you will get the reference to the card object, on the card object you can get the reference to the rack object and set the send request operation to true on the next scan cycle. For example the SendReq on the PnWriteReq Profibus device object or the SendOp attribute on the Modbus module object. So, you do not really need to know the path of the plant node or create a direct reference to the plant object that you need to control.


sts = gdh_NameToObjid(nm.c_str(), &oid);
if (EVEN(sts)) {
        errh_Error("prov_io::get_sendop_link() -> 1. Error Reading %s", nm.c_str());
        return nm;
}

ss.str("");
ss.clear();
ss << nm.substr(0, nm.find_last_of(".")) << ".IoConnect";
ionm = ss.str();

sigcon_a = reinterpret_cast<pwr_taddress>(&sigcon);
sts = gdh_GetObjectInfo(ionm.c_str(), sigcon_a, sizeof(sigcon));
if (EVEN(sts)) {
        errh_Error("prov_io::get_sendop_link() -> 2. Error Reading %s", ionm.c_str());
        return nm;
}

memset(par_dev_name, 0, SEND_OP_BUFF_SZ);
sts = gdh_AttrrefToName(&sigcon, par_dev_name, SEND_OP_BUFF_SZ, cdh_mName_volumeStrict);
if (EVEN(sts)) {
        errh_Error("prov_io::get_sendop_link() -> 3. Error Reading %s", ionm.c_str());
        return nm;
}

sts = gdh_NameToObjid(par_dev_name, &devid);
if (EVEN(sts)) {
        errh_Error("prov_io::get_sendop_link() -> 4. Error Reading %s", par_dev_name);
        return nm;
}

For example the code above displays an example on how to get the plant node using the $IoConnect attribute. Finally gets the Object ID of the connected plant node, allowing real control. Also, always remember to use the cdh_mName_volumeStrict flag to guarantee that the full volume path of the node will be used, allowing GDH to get the real path of the object without wasting time on finding mounted volumes and trying to make a difference between them.

With this approach, I am thinking to write some API helpers, something with the same behavior of the XML XPath standard, to allow finding nodes and node references without too much effort. I think that this will help a lot with open(), close() and scan() methods on the rt_appl class, allowing faster C and C++ development. This framework is really nice. I would like it to be more open, and I think that the authors would create a public repository and create a centralized development model like is seen in other platforms like FreeBSD.


© Daniel Molina Wegener for coder . cl, 2012. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2012/07/abstracting-plant-nodes-in-proview/feed/ 0
proview graphic classes http://coder.cl/2012/07/proview-graphic-classes/ http://coder.cl/2012/07/proview-graphic-classes/#comments Mon, 02 Jul 2012 23:14:31 +0000 Daniel Molina Wegener http://coder.cl/?p=2563 ProView provides a nice interface to build custom device classes, I/O classes and graphic classes, mainly to build processing graphics. In our current project we have many device configurations which are subject of repeated configurations. To avoid repetitive work we are using classes, of all kinds. Custom process graphics as components can avoid repetitive work with equal configurations and specific processing graphics. I have made a sample HMI — Human Machine Interface — to control some devices which will be used on the real plant.

Is nice to have that kind of configurations, we have several classes for almost all layers and node types — both physical and logical nodes — allowing a higher level of abstraction and avoiding repeated configurations. We just need to setup the UnitId property on most objects — due to its Modbus base classes.

Device Classes

Device Classes

Also, as graphic component, we have configured some generic nodes — for logical nodes and I/O classes — where we have some nice interfaces as samples because the definitive HMI is not really defined yet. Still we are defining some algorithmic behavior of the controlling program, which is being developed using C and C++. Rather than defining an IoConnect reference attribute, you should create an object reference attribute and all sub-graph objects should be connected using $object as base reference, as it is being done using IoConnect object references.

Sample HMI

Sample HMI

As this happens on the ProView side, the same happens on the C and C++ programming side. The code base has all device classes defined as they are ProView classes with their custom I/O methods and controlling logic. Also there are some signal transformations as it is being done by PLC programs but implemented in C, just to ensure that some signal objects have the proper representation as analog devices — like the percent needle.

So, finally is nice to work with this framework, it is very flexible, so the graphic object is being connected to the device node in the following picture.

Device Connection

Device Connection

© Daniel Molina Wegener for coder . cl, 2012. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2012/07/proview-graphic-classes/feed/ 0
proview I/O layers http://coder.cl/2012/06/proview-io-layers/ http://coder.cl/2012/06/proview-io-layers/#comments Sun, 10 Jun 2012 02:01:44 +0000 Daniel Molina Wegener http://coder.cl/?p=2516 Understanding the I/O layers on ProView is a must. If you understand the I/O layers, you will be able to configure channels and signals grouped in classes allowing a very good usage and abstraction of the devices that are being examined and manipulated from ProView. For example a Profibus device can have 8 digital input channels for its status, but they should be grouped a custom class using an array of digital channels with Bit8 as data representation, so they are used as object attributes rather than separate channels, if you do not configure the proper class, you will be wasting your time configuring separate channels for each device, leading to some mistakes. Just imagine that you want to configure 50 devices with the same number of channels for its status, you will need to configure 50 times each channel. So, you really need to know about the I/O layering on ProView.

The I/O layers are represented by an I/O Context, Agents, Racks, Cards and Channels. An I/O Context, is an I/O virtual space for I/O operations, where one or more Agents can work separately, but sharing some data, where you can use only on I/O Context from each Application. An Agent is a protocol layer, where each Agent can work as protocol handler, for example there is a Profibus and Modbus agents, where each Agent connects to one or more endpoints. Then comes one or more Racks where they are groups of Cards, and each card is grouping Channels.

ProView I/O Layers

ProView I/O Layers

Also the ProView system has a class hierarchy implementation, where each Agent, Rack and Card class is allowing sub-classing. This allows some custom devices to be configured easily over some other generic devices, for example those which are handled by Profibus and Modbus protocols. For example we have created our own classes to handle some very specific devices. So, ProView is great for building custom ICS systems. For example it has support for a Siemens ET200S-2AI device as Card and some other devices, but it is so customizable that you can build your own classes for any level.

Siemens ET200S

Siemens ET200S

We currently have made some custom classes for our project, almost on all levels, this is really nice. You just need to read the documentation and have a deep knowledge on C and C++ programming languages. Java is supported, but it is not so good to be used in soft real-time systems, as we have configured our processing stations. Also we cannot use PLC programming due to the algorithm complexity, like priority queues and task scheduling. Also it has some very nice features, like mapping between nodes and plant nodes automatically using a single IoConnect attribute on the mapped component, to allow automatic connections between channels on device classes and signals in I/O components. There are many useful features around the I/O system in ProView that can make it a very good framework for ICS systems. For example I am very sure that you will love to work with GDH, because it is really one of the best abstraction layers that I have seen.


© Daniel Molina Wegener for coder . cl, 2012. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2012/06/proview-io-layers/feed/ 0