Hi Pavel,
This is indeed a bit tricky. You probably want the readback go to 1 when the scope is armed and go to 0 when the scope is done? Does the scope provide any asynchronous way to tell you when it is done? Unfortunately, I don't have a manual for this device. With GPIB, devices often can be programmed to send a SRQ when they are done with a time consuming activity. In that case the recipe is as follows:
Before arming the scope, set a status record to 1. When you get the "done" signal, set the status record to 0. You have to set the status before arming the scope so that you don't have a race condition if the scope is done very quickly. Thus you need an additional layer of records, one for the "user interface" and one for the "device interface" and set the status in between.
record(seq, "$(P)$(R)Arm") {
field(DESC, "Process this to start")
field(DOL1, "1")
field(LNK1, "$(P)$(R)ArmStatus PP")
field(DOL2, "1")
field(LNK2, "$(P)$(R)TrigArm PP")
}
record(bi, "$(P)$(R)ArmStatus") {
field(ZNAM, "STOP")
field(ONAM, "ARMED")
}
record(bo, "$(P)$(R)TrigArm") {
field(DESC, "Arm the trigger")
field(DTYP, "stream")
field(OUT, "@devTPS20xx.proto TrigArm $(PORT) $(A)")
field(ZNAM, "STOP")
field(ONAM, "ARMED")
}
record(bi, "$(P)$(R)WaitDone") {
field(DTYP, "stream")
field(INP, "@devTPS20xx.proto WaitDone $(PORT) $(A)")
field(SCAN, "I/O Intr")
field(FLNK, "$(P)$(R)SetDone")
}
record(seq, "$(P)$(R)SetDone") {
field(DOL1, "0")
field(LNK1, "$(P)$(R)ArmStatus PP")
}
TrigArm {
out "ACQ:STOPA SEQ";
out "ACQ:STATE %{OFF|ON}";
}
done=SRQ_code_for_done;
done_timeout=max_msec_to_wait_for_acquisition;
WaitDone {
event($done) $done_timeout;
out "ACQ:STATE?";
in "1";
}
But I have to admit that I have never really used the event command, because I don't have such a device. So it may not work :-)
If your device does not support asynchronous events, you probably have to poll. In this case the possible race condition is different and you have to arm the scope first, then start polling like this:
record(seq, "$(P)$(R)Arm") {
field(DOL1, "1")
field(LNK1, "$(P)$(R)TrigArm PP")
field(DOL2, "1")
field(LNK2, "$(P)$(R)ArmStatus PP")
}
record(bi, "$(P)$(R)ArmStatus") {
field(ZNAM, "STOP")
field(ONAM, "ARMED")
}
record(bo, "$(P)$(R)TrigArm") {
field(DESC, "Arm the trigger")
field(DTYP, "stream")
field(OUT, "@devTPS20xx.proto TrigArm $(PORT) $(A)")
field(ZNAM, "STOP")
field(ONAM, "ARMED")
}
record(bi, "$(P)$(R)PollDone") {
field(DTYP, "stream")
field(INP, "@devTPS20xx.proto PollDone $(PORT) $(A)")
field(SCAN, "1 second")
field(SDIS, "$(P)$(R)ArmStatus")
field(DISV, "0")
field(FLNK, "$(P)$(R)CheckDone")
}
record(calcout, "$(P)$(R)CheckDone"){
field(INPA, "$(P)$(R)PollDone")
field(CALC, "A")
field(OOPT, "When Zero")
field(OUT, "$(P)$(R)ArmStatus PP")
}
PollDone {
out "ACQ:STATE?";
in "%d";
}
Note that the PollDone polls only while ArmStatus is 1.
The poll rate depends on your application, of course.
Does this help?
Dirk
Pavel Masloff wrote:
Dear all,
I have a Tektronix scope (TPS2024). I am using StreamDevice. I know how to set the scope's parameters. These are simple commands with the SCAN field = PASSIVE.
One record (the Trigger Single Sequence button) is causing me some pain. When the scope is triggered (end of measurement), I need a readback signal to change its state (=0).
So far my commands were only one way (except for the initializaion). I send, nothing comes. Here is what I use:
record(bo, "$(P)$(R)TrigArm") {
field(DESC, "Arm the trigger")
field(SCAN, "Passive")
field(DTYP, "stream")
field(OUT, "@devTPS20xx.proto TrigArm $(PORT) $(A)")
field(ZNAM, "STOP")
field(ONAM, "ARMED")
field(PINI, "")
}
TrigArm {
ReplyTimeout = 2000;
out "ACQ:STOPA SEQ";
out "ACQ:STATE %{OFF|ON}"; @init {
out "ACQ:STATE?";
in "%i";
}
}
So I need the same @init code in the TrigArm protocol (out "ACQ:STATE?";in "%i";). How can I do that?
The "ACQ:STATE?" command will have an answer ("1"=Trigger Armed, "0"=Trigger Not Armed).
I have tried using another record (with forward link), but to no avail.