@Jamie: There is nothing wrong in the syntax you have written. The answer might come from the triggering process. Is the calculation triggered naturally following the input of one the point or is it clock-based?
If your points (tags) are not coming from the same data source and/or the same scan class (frequency of acquisition or sampling), a natural scheduling might cause to wrongly evaluate the result of your equation as you get because when the calculation is triggered, both fresh discrete value and interpolated discrete value (using the past one) will be used.
A clock-based PE calculation will minimize the chance that one of the points has "old" value. You can also modify your equation to verify how old is the value returned by TagVal function; and if it is more than n seconds (or minutes, or hours) you write another discrete value such as "Calc Failed" or "I/O Timeout".
Dear Jamie Smith,
I think the equation you actually want is:
IF TagVal(tag1, '*')="OK" AND TagVal(tag2, '*') = "OK" THEN "OK" ELSE "FAILED"
The above equation will return "FAILED" if either tag1 or tag2 has a value that is not "OK". The equation you are currently using...
IF TagVal(tag1, '*')="OK" OR TagVal(tag2, '*') = "OK" THEN "OK" ELSE "FAILED"
...will return "FAILED" only when both tag1 and tag2 have values that are not "OK".