Applies To:
  • CitectSCADA 1.00, 1.01, 1.10, 1.11, 1.20, 2.00, 2.01

Some types of PLCs support a Hot Standby configuration. With this configuration, two PLCs are used to provide fault tolerance at the PLC level. If one PLC fails, the other will start processing and take control of the I/O. When a changeover occurs, the I/O Server should also start reading the PLC data from the Standby PLC. However when the primary PLC fails, communication to the I/O Server may not also fail. If this happens, the I/O Server assumes that the PLC is OK and will continue to communicate to the dead PLC.

The I/O Server will only switch from a Primary to a Standby PLC when it detects failure of the communication channel. If the communication channel does not fail, then the I/O Server will communicate to the wrong PLC. 

If you can detect when the primary PLC has failed, then you can tell the I/O Server to switch from the Primary to the Standby PLC. The Cicode function UnitControl allows you to disable communication to any (or all I/O Devices) on an I/O Server. When you disable communication to an I/O Device and there is a Standby I/O Device available, then that I/O Device will become active.

To detect failure of the primary I/O Device: (1) Create a watch dog bit in the PLC. (2) Make a timer in the PLC that will toggle the state of the bit at (say) a 10 second period. (3) In Citect, write a Cicode task to check the bit, and, if the bit does not change state after a timeout period, switch to the Standby PLC - by calling UnitControl("MyPLC", 1, 1);

INT watchTimeout = 30;
INT bUnitFailed;
   INT lastWatchDogBit;
   INT okTime;
   INT nowTime;
      nowTime = TimeCurrent();
      IF WatchDogBit <> lastWatchDogBit THEN
         okTime = nowTime;
      IF nowTime > okTime + watchTimeout THEN
      /* unit failed disable if not already disabled */
         IF NOT bUnitFailed THEN
            UnitControl("MyUnit", 1, 1);
            bUnitFailed = TRUE;
      /* unit ok re-enable if not already enabled */
         IF bUnitFailed THEN
            UnitControl("MyUnit", 1, 0);
            bUnitFailed = FALSE;
      lastWatchDogBit = WatchDogBit;

You can only run this function on the I/O Server. Create a task on startup of the I/O Server to call this function. Note that you should be very careful with the use of UnitControl to disable an I/O Device, because the I/O Server cannot communicate to that I/O Device once it is disabled.

The function UnitControl() has been renamed to IODeviceControl() in version 3.0 and later. UnitControl() is still available to allow easy upgrading of your existing projects, however UnitControl() is no longer documented in the manuals or on line help. To allow for easier maintenance of your projects you should change all references to UnitControl() to IODeviceControl().