OPC E-Fail and FSQL Triggers

We noticed some behaviour today with FSQL and triggers. We have a bit in a PLC that is latched; when it goes from low->high, trigger the FSQL group, and it is set to execute once. This works.

While testing the system for robustness, we killed the OPC server (Kepware). FPMI shows the red overlay and all - good. The status of the latched bit goes to E-Fail quality instead of Good, and nothing too much seems to be wrong. However, Kepware is restarted and the quality goes from E-Fail to Good. In this case, the group executes again. Not what we want.

We want to look for the low-high transition only when good - we experimented with some logic in the action items section, but not really sure what to do. Is there a way I can protect against this?

On the trigger tab in FactorySQL there is a prevent trigger caused by group start check box. Do you have that selected?

We can protect your trigger with more “action item” logic, but the behavior seems more like a bug.

IMO, the trigger evaluation should behave like a new “group start” after a “reasonable” time duration of the OPC error condition. Does this sound like what you’d expect?

Yes, this is checked. But the events wouldn’t seem like a group start - the group has been running, just loss of OPC server and then re-acquisition of it when the opc server starts back up.

[quote=“nathan”]
IMO, the trigger evaluation should behave like a new “group start” after a “reasonable” time duration of the OPC error condition. Does this sound like what you’d expect?[/quote]
I think I agree here - I want FSQL to remember it’s state when the tag quality goes from bad->good.

Hi,

Yes, I believe it must be working under the assumption that if the quality goes to BAD, the value is unknown. That means that it could transition to 0 and then back to 1 during that time, and there would be no way to know. Thus when the quality goes good again, it logs, in order to capture the most recent value after the period of uncertainty.

I think this strategy is fine for most cases, since there normally isn’t a real problem with collecting too much data (things can be paired down through querying).

At the same time, I can understand the desire to not have it do this. So, it sounds like we should really have a more complete set of nuanced trigger options… ‘prevent trigger on startup’, ‘prevent trigger on quality change’, etc.

Regards,

Sounds good!

[quote=“Colby.Clegg”]Hi,

I think this strategy is fine for most cases, since there normally isn’t a real problem with collecting too much data (things can be paired down through querying).

Regards,[/quote]

We are using the group to decide whether to write a DB entry for batch recording - we get too many ‘new’ batch inserts as duplicates when this happens and then the table is out of sync. But I do suppose per your idea I could put a LIMIT 1 as part of the SQL query when looking for that particular record, and that could ignore duplicates. Except when I want a list of all batch records - but I think I could use a DISTINCT keyword. But I would really like to remember the state FSQL is in at that time we got to EFAIL - so I do like the additional options you suggest for group triggering.

Yeah, you might be able to get what you want with the DISTINCT keyword.

I never really answered your original question because it would be fairly difficult to set up the correct trigger to prevent this, and I wanted to make sure we discussed it a bit before we got into that. However, I’ll briefly outline some ideas of what you could do…

I think that in simple terms all you really want to do is have a value that is only updated while the quality is good. Thus, you need to make the opc value an input into an action item (or multiple) which does this, and then in turn use that as the trigger.

Some useful things that might help:
-The Store/GetVariable functions
-The fact that you can get an item’s quality by appending “.DataIntegrity” to its name in a reference, ie {MyOPCItem.DataIntegrity}

There are probably a number of ways to do this, but I would do the following:

Action Item 1:
Expression- if(ToInt({TriggerItem.DataIntegrity})=192, StoreVariable("triggervalue",{TriggerItem}), null)
Ignore group trigger settings: Checked

Action Item 2:
Expression- GetVariable("triggervalue",0)
Ignore group trigger settings: Checked

Group Trigger: Action item #2.

So, the first one stores the variable if the quality is good. The second part of the IF (",null") is necessary because the IF function requires two parts. The null just doesn’t do anything.

The second just retrieves the stored value. If the quality is good, it will match the the first value. If not, it will be the last good value. Both items are set to run always so they’ll be executed irregardless of the trigger. Use the second item as the group trigger, with the “only execute once while trigger is active” option.

Hope this helps, let me know if I’ve missed anything.