07-16-2019 05:27 PM
You want to configure your loops in a way that lets each one own it's own data and it's own status and is not dependent on other loops. Each one should have its own initialize and shutdown states. You should be able to cleanly shut down all of the loops from the user interface or from an error in any loop. Look at how this is done in main loop in the QMH template. I prefer a spoke and hub structure with most of the communication going through the main loop. The event loop should have very little code in it and just launch states in the main loop.
07-16-2019 07:59 PM
@OregonGumby wrote:
You want to configure your loops in a way that lets each one own it's own data and it's own status and is not dependent on other loops. Each one should have its own initialize and shutdown states. You should be able to cleanly shut down all of the loops from the user interface or from an error in any loop. Look at how this is done in main loop in the QMH template. I prefer a spoke and hub structure with most of the communication going through the main loop. The event loop should have very little code in it and just launch states in the main loop.
Thank you for that perspective. Definitely valuable.
07-17-2019 11:45 AM
I have a few more minutes now and just reviewed the thread more carefully.
RE: "serial comm encapsulation" (msgs #5,6):
The encapsulation you describe is similar to what is commonly termed an "Action Engine." With some careful enhancements, it's *possible* that such an approach might be sufficient for your current needs. But I agree with what crossrulz already said in msg #6 -- in the long run it doesn't scale well. Still, sometimes we just need to solve the problem that actually exists now, not the one that might possibly exist at some later date.
If you were to pursue an Action Engine style solution, here are a few tips:
On the other hand, if you were to implement VISA comm as an independent QMH loop, much of the code for the various supported messages would look just like the code for the various AE actions. The QMH loop provides a different way to encapsulate access.
With an AE, other processes must "pull" data at the moment they want it. This tends to initiate a synchronous query/response communication sequence that takes time. If lots of processes want to pull data frequently, there will be a lot of wasted waiting and possibly a lot of redundant queries.
With a QMH, it's more natural to "push" data in a manner more like publishing or broadcasting. The VISA comm loop (which knows the device) decides the appropriate rate of querying/publishing. The other processes need to be ready to receive the data asynchronously. (There's an in-between approach where the QMH can be the only writer to some flavor of global while other processes are free to query this global with no waiting.)
-Kevin P
07-29-2019 09:19 AM
@Kevin_Price wrote:
I have a few more minutes now and just reviewed the thread more carefully.
RE: "serial comm encapsulation" (msgs #5,6):
The encapsulation you describe is similar to what is commonly termed an "Action Engine." With some careful enhancements, it's *possible* that such an approach might be sufficient for your current needs. But I agree with what crossrulz already said in msg #6 -- in the long run it doesn't scale well. Still, sometimes we just need to solve the problem that actually exists now, not the one that might possibly exist at some later date.
If you were to pursue an Action Engine style solution, here are a few tips:
- It should be the *only* mediator for all VISA communication to that device.
- A corollary is that you need to support Init and Close actions.
- Another corollary is that the VISA ref should be stored internally in a shift register or feedback node. It should not come out on an output terminal. No other part of your code should use the VISA ref directly. Any capability you need should be built into the "Action Engine."
- Communications need to be "atomic". If you need to query the device for info, the single "action" needs to include both writing the command down to the device and reading the response back from the device. It's really important *not* to call the AE once with a "write" action and then followup by calling again with a "read" looking for a reply. That gives any parallel processes an opportunity to "steal" your info if they happen to call with a "read" action at just the right moment.
On the other hand, if you were to implement VISA comm as an independent QMH loop, much of the code for the various supported messages would look just like the code for the various AE actions. The QMH loop provides a different way to encapsulate access.
With an AE, other processes must "pull" data at the moment they want it. This tends to initiate a synchronous query/response communication sequence that takes time. If lots of processes want to pull data frequently, there will be a lot of wasted waiting and possibly a lot of redundant queries.
With a QMH, it's more natural to "push" data in a manner more like publishing or broadcasting. The VISA comm loop (which knows the device) decides the appropriate rate of querying/publishing. The other processes need to be ready to receive the data asynchronously. (There's an in-between approach where the QMH can be the only writer to some flavor of global while other processes are free to query this global with no waiting.)
-Kevin P
Wow, those are some great tips for action engine implementation. I took your recommendations and implemented a Serial Comm action engine, that includes Init, W, R, W/R, Flush, and close actions. I will revisit your idea of serial comm via independent QMH again in the future if my current solution has issues once I start testing. Thank you!