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

Question: I'm writing a driver using the Citect Driver Tool Kit - DDK. My protocol uses a single poll command that is sent to the PLC. The reply can contain any of several message types. My problem is how to synchronize these various kinds of messages with the requests in the Driver Control Block. The only way I can imagine is to buffer the PLC message and wait for the corresponding Citect request since I cannot discard the PLC message more than 2-3 times.

Is the correct way, i.e. to buffer the messages? 

This is the correct way to develop the driver. This type of driver we call a Back End / Front End protocol driver. This type of driver has two parts. The back end will communicate with the PLC without receiving any requests (DCBs) from Citect. It will normally poll the PLC at some regular time period off the CPU command. The back end will place the PLC data into memory buffers. The front end of the driver will process the DCB's from Citect. To complete a DCB, the front end will extract the data from the memory buffers. The memory buffers will end up being a memory image of the PLC data. For example if each I/O Device contains 2048 bits and 512 registers allocate enough memory to hold all the data for each I/O Device. You can do this on startup of the driver when it tries to initialise the I/O Device.

There will need to be some communication between the front and back end to handle writes to the PLC. In this case the front end will pass the write commands to the back end and be serviced in the normal way. You may also need to tell the back end what to poll from the PLC, as you don't want to waste time polling data from the PLC which Citect will not ask for.

Some PLCs report changes in data by exception, ie they only send you a message when some digital or register has changed state. Many Distributed Control Systems work in this way. This type of protocol driver should also be developed as a back end / front end driver. The entire PLC would be read on startup and then polled for exceptions. You may also want to poll the PLC at a low rate, just in case you miss an exception - for example read the entire PLC over a few minute cycle or while there is no exceptions.

This type of driver can give quick responses from the front end, as all read data will be returned immediately from memory buffers. You may have to tune Citect for this quick response as Citect will try to read the data as fast as possible. For example to display data on a page, Citect will request all the data. When the data is returned (very quickly in this case), the page will be updated and then Citect will ask for the data again. This can mean that Citect will generate unnecessary requests to the I/O Server, and also receive the same data in response. This is only a minor problem as it will just waste CPU and Network traffic if running I/O Server on a LAN.

There are two ways to compensate for this effect. The first is you may artificially slow down Citect request rate for data. After each display of the page data, Citect waits a small amount of time before requesting the data again. This time defaults to 100ms and you may change it using the parameter [PAGE] Delay=<time in ms>. You should also adjust the alarm processing time with the parameter [ALARM] ScanTime=<time in ms>. You should adjust these values so that Citect will update at a similar rate to which the data is being read from the PLC. For example, if it takes the back end driver 2 seconds to poll the PLC, then adjust the alarm scan time to 2000 and set the page delay to 2000 minus the time to display the page, say 1000ms.

The second way is to artificially slow down the front end driver. When the front end receives a read request it could just queue the request and then service it a small time later, eg off the CPU poll. This will give an effective response time of 55 ms, which is still fast.

See also Q1073, Q1075