Although I haven't programmed the seq for a while, here is what I believe is happening
The "monitored" variable is (in concept) similar to a volatile C variable.
The variable is automatically updated based on what is in the EPICS database (not the hardware!).
If the update of status_pv is completing after pvPutComplete, then you will experience what you describe.
If you want to trigger state changes or processing on an update (i.e. monitor) you need to use event flags
* efTest check that the flag is at 1 ( a monitor has been received since it was last cleared)
* efTestAndClear does the same and reset the flag to 0
Those commands are most often found in test (when) conditions.
Otherwise use efClear and efSet
sample code:
/* Monitored variables */
double voltageAO;
assign voltageAO to "{deviceName}:{channelId}VltgAO";
monitor voltageAO;
evflag monitorVoltageAO;
sync voltageAO monitorVoltageAO;
[...]
state channel_idleState {
entry {
seqLog("--> channel_idleState\n");
seqLog("efAO=%d, efMO=%d\n", efTest(monitorVoltageAO), efTest(monitorVoltageMO));
}
when(efTest(monitorVoltageAO) ) {
efClear(monitorVoltageAO);
} state channel_updateVoltageMIState
when(!efTest(monitorVoltageAO) && efTest(monitorVoltageMO)) {
efClear(monitorVoltageMO);
} state channel_updateVoltageAOState
exit {
seqLog("<-- channel_idleState\n");
}
}
> From:
[email protected]> To:
[email protected]> Date: Tue, 21 Jan 2014 17:42:46 -0500
> Subject: SNL monitor and pvPutComplete
>
>
> Hi,
>
> I'm using SNL to perform a potentially long put_callback, using pvPut with the ASYNC option in one state, followed by the use of pvPutComplete in the following state. Then on completion, I read another PV immediately, which has an SNL monitor on it, something like:
>
> unsigned short start_pv; assign start_pv to "{RC}:Start"; monitor start_pv;
>
> unsigned short login_pv; assign login_pv to "{DAS}:Login";
> unsigned short status_pv; assign status_pv to "{DAS}:Stat"; monitor status_pv;
>
> state idle {
> /* When we detect a user start. */
> when (start_pv == 1) {
> login_pv = 1;
> pvPut(login_pv, ASYNC);
> } state login
> }
>
>
> state login {
> when (pvPutComplete(login_pv)) {
> if (status_pv != 1) {
> /*handle error here*/
> } else {
> /*it worked */
> }
> } state thenextstate
> }
>
>
> I have a race condition between the completion of the put_callback and the status_pv variable updating due to a monitor. I sometimes read the value the status PV had before the callback completes. I've tested the underlying system quite a bit, so I suspected a problem with my SNL. I added in a pvGet(status_pv) just before I test that variable, and it seems to have solved it (which maybe just due to the extra time taken to execute the pvGet).
>
> Am I handling this situation incorrectly, or do we know of a problem with monitors in SNL (SEQ Version 2.0.14)? Is the use of pvGet on a monitored variable a bad idea? From reading tech-talk, it might be frowned upon...
>
> Or, is there a better way of doing this, using event flags?
>
> Cheers,
> Matt
>
>
>
>