drbitboy
Lifetime Supporting Member
So, the PLC is single-threaded with interrupts, right?
Whether it's "single-threaded" depends on your definition of "thread." I would assume there is only one CPU (ignoring High-Speed Counters for now), so let's assume that one single-core CPU is only ever doing one thing at a time, and if that is how we define "thread" then there is only one "thread."
However, with interrupts comes the possibility of multiple tasks, or OBs (Organizational Blocks in Siemens jargon), that may stop (interrupt) a first OB to execute a second OB before returning to the first OB, which first OB may not even know the second OB has run. If we define those OBs as "threads," then the PLC is not single-threaded.
(1) Is it possible to read in all data values at scan start, and use those for the remainder of the scan?
(2) Any new values written during an interrupt in the scan could be ignored until next scan, no?
(1) Yes; that is called the Input Map pattern; cf. this link; the Input Map pattern is related to double-buffering.
(2) Yes, but with a caveat: the trick is to prevent any new values from being written (via interrupt by another task*) during activity "(1)" i.e. while the Input Map is executing that initial read at the start of a scan.
* in this case the OPC UA server is the other task; I don't know offhand if OPC UA communications can interrupt other tasks, but from your experiment with 254 As and 254 Bs it appears that it can.
One possible solution would be to use the DIS_AIRT/EN_AIRT instruction pair, assuming that can prevent OPC UA from interrupting the scan; since you already have the non-null result (finding a corrupted 'AAA...BBB' string), it should be easy to test if DIS_AIRT/EN_AIRT can effect a null result.
Another possible solution is what @JesperMP suggested: only one process ever writes data to any one data area of memory. So each "Station" from the diagram has its own private Tags in the PLC to which to write to via the OPC UA server, and "Station X" executes the following protocol
- Before writing the block data it reads via OPC UA a bit (BOOL) in the PLC that indicates "Station X updated its data area on the PLC;"
- If that bit is 1, then it does nothing further
- If that test bit is 0, then it writes the block data via OPC UA to its private Station X Tags.
- After writing the block data is writes a 1 to that Station X bit.
The Input Map task looks at each station's bit, and when it finds one set, it reads the Station X data memory area and writes it to the common data memory area that will be used during the current scan, and it finally clears the |Station X bit." This ensures consistency because
- Only one task (thread) ever writes to any one data memory area, be it the per-Station data areas, written to by the OPC UA server from one station, or the common data memory area written to by the Input Map task.
- Two tasks write the the "Station X" bits, however
- The Station-driven OPC UA write of the Station X bit only ever writes a 1 to that bit, but only if it first finds a 0 in that bit; this is called "Set and Forget."
- The Input Map only ever writes a 0 to any Station X bit, but only if it first finds a 1 in that bit.
Last edited: