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

Citect performs writes to the PLC in an asynchronous manner. That is when you write to the PLC, the write takes a little time to get to the PLC. During this time, Citect will continue to run and do other operations, like run more Cicode. If the other Cicode assumes that the write has completed immediately, then you may encounter some problems. Citect tries to hide the asynchronous write as much as possible but there are some limitations as detailed below. 

If you have the following Cicode:

PLC_VAR = 1234;
Prompt("Variable is " + PLC_VAR : ####);

The first line is a write to the PLC. When Citect executes this line of Cicode, it will generate a request to the I/O Server to write the value 1234 into the PLC variable called PLC_VAR. Citect will then execute the next line of Cicode before the PLC write has been completed. Citect does this so that the Cicode is not stopped while waiting for the slow PLC. As the write to the PLC has not completed, you may think that the next line of Cicode will display the last value of PLC_VAR and not the value 1234. The Cicode will display the correct value (1234), as whenever Citect writes into the PLC, it will first update it local copy of the variable - any following Cicode will get the correct value.

This solution will not work under some conditions as Citect may keep more than one copy of a PLC variable, and only the one associated with the current Cicode is updated. The other variables will contain the old value of the PLC variable until they are refreshed (with a read from the PLC). There is a separate data area for each display page, Cicode function library, alarms, trends and reports. If you write to a PLC variable from a page keyboard command, the copy of the PLC variable associated with that page will be updated, however the copy associated with other pages and all the Cicode functions is not updated until the next read. If you call a Cicode function that assumes the write has completed it will get the last value.

You can work around this limitation by writing to the PLC variable in the Cicode function. All Cicode functions share the same PLC variables so the writes will operate as expected.

TestFunc(INT nValue)
   PLC_VAR = nValue;

Another side effect of this operation is that you may think that Citect has successfully written to the PLC, when in fact it may later fail because of some hardware fault or configuration error, (eg write to an input register). Under some critical conditions, you may want to check that the write has in fact completed. Whenever a write fails to the PLC, a hardware error is generated, but the associated Cicode cannot be notified or use the IsError() function as that Cicode has executed way past the PLC write. You may verify a critical write by calling the function ReRead() just after the write, and then verify the value of the variable. ReRead() will force Cicode to reread all PLC variables associated with the current Cicode so you can check the new value.

PLC_VAR = 1234;
   Prompt("Write failed");

Under these conditions the data will be read from the physical PLC and not from the I/O Server cache, as the I/O Server will invalidate any cached data associated with a PLC write. This will allow you to test for a completed write. Note that other Cicode tasks running at the same time will not be waiting on the ReRead so they may see the old or new value - depending on if they are using the same copy of the PLC variable. You can also stop Citect from writing to the local copy of the variable by using the function CodeSetMode(0, 0).

See also Q1075 for details on how Citect reads from a PLC.