Let’s consider a common scenario in control system development: You’ve created an automation feature that orchestrates multiple devices via channel access. The sequence of actions is simple, but you must ensure that each step begins only after the previous one has completed successfully. How can you achieve this reliably?
Here are three options:
- Execute a step and wait some time before executing the next one.
- Execute a step and poll the device to check if the step has been finished
- Use the native Channel Access feature - putNotify to do the job.
Why Option 1 is problematic
The first option is the least reliable. Relying on fixed delays can lead to unpredictable behavior. If time isn’t the decisive factor in determining the success of a step, a simple time-based approach can cause errors.
Polling: A better, but imperfect solution
Option 2, polling, is more effective but introduces complexity. Client logic must implement the polling mechanism, which adds to the development effort. Frequent polling increases network traffic, potentially leading to performance issues, especially in a large installations.
The putNotify solution: Clean and elegant
Option 3—using the putNotify (or processNotify in newer versions of EPICS Base)—is the most robust and efficient solution. It simplifies client logic by eliminating the need for polling and reduces network traffic.
So, how do we use it? Let’s break it down.
The putNotify mechanism allows you to trigger a record and get notified whenn the process completes. For a detailed description of the mechanism look at the EPICS Application Developer’s Guide, section 5.11
For now, let’s stay with the simplified version of the mechanism, which could be simplified to
To use this mechanism, we can use the BUSY record which you can find in the busy module. It is basically a modified BO record that does not return immediately but pretends to be “busy” until another record changes its state to “Done”.
How It Works
The Busy record waits for some external condition or process to change its state to “Done”. Typically it is handled by device support. You can read more on how it works here.
A Simple Example
Let’s try the most straightforward example: putting a value to the bo record that starts some process.
Database:
record(bo, process){
field(ZNAM, "0")
field(ONAM, "1")
field(OUT, "busy PP")
}
Notice that caput returns immediately. What if the process takes time, and we would like to wait until the process is finished? Let’s add the busy record to the setup. (I’m not going to cover installation process, I assume that the EPICS base and support modules are installed on your machine).
Our database looks like the following.
record(bo, process){
field(ZNAM, "0")
field(ONAM, "1")
field(OUT, "busy PP")
}
record(busy, busy){}
record(bo, process-done){
field(DOL, "0")
field(OMSL, "closed_loop")
field(OUT, "busy PP")
}
Here’s what happens:
- The
process
record triggers the busy record. - The
busy
record remains “Busy” until another record changes its state to “Done”. - The
process-done
record eventually finishes the job, forcing thebusy
record into the “Done” state. This record is processed by the internal logic, which determines when the task triggered by theprocess
record has completed.
To run the put command with putNotify mechanism, use the following command:
$ caput -c process 1
The command will wait until the process-done
record is triggered.
By using the putNotify mechanism, you can ensure that each step of your automation sequence waits for the previous to finish, leading to more robust and reliable control systems. Obviously, it is on developers of individual device drivers to use the busy record in their implementations.
How to use it from IOC?
We can utilise a sscan record for that, but scanning is a topic for another time.
Final Thoughts
The putNotify feature is often overlooked and re-implemented at higher levels of the controls system.
Whether you’re new to EPICS or a seasoned developer, using busy
record will improve the robustness of your automation.
Happy controlling!