04-17-2025 05:24 AM
Hi everybody,
I started a LabVIEW Project developing software for a test bench. I already structured my project in seperate modules with different tasks.
Two important modules are:
I hope I explained my case in sufficient detail.
Now my questions:
I want to avoid going into a wrong direction with the project.
I hope you can answer my questions and maybe give me some good hints about best practice to realize my project.
Fabian
Solved! Go to Solution.
04-17-2025 11:05 AM
Hey Fabian,
thanks for putting your trust into DQMH. I like what I'm seeing so far!
A few comments:
- Make a point of updating the VI icon of the module's library when creating a module. The "SNGLTN" on green background makes it difficult for me to understand which module's VIs I'm looking at.
- The Init DAQ and Start Controller requests have an array of resources as payload, but both really only need a single task. Would it be more readable and safer if the caller already selected the corresponding task to send?
- For your Acquiring module, you could consider moving everything to do with the DAQ task into the helper loop if you don't need the resource in your MHL
- Why is the DAQ task a payload of the "DAQ did init" broadcast? Could/should that task be a private resource of the module?
- You could create a typedef'ed cluster for the data on the HL shift register, similar to what the MHL has
- In the HL, you should wire all the error outs to the error terminal on the bottom right of the case structure so it gets caught and propagated
- For your Controller module, where is the DAQ task coming from? Who creates it?
- Does the controller PID loop have to run at a different rate than the Acquisition loop? The broadcast already gives timing to the Controller PID loop, perhaps you don't need the timeout event? Also beware: Each time a broadcast is received, the timeout counter is reset! So if you receive broadcasts every 100ms and your timeout is also set to 100ms, you will never actually execute the timeout case!
And as to your questions:
> Is this way to handle the data from a Broadcast ok?
Repeating the statement from above: Receiving a periodic broadcast already gives timing to the helper loop and potentially starves the timeout event.
> Is this way to implement the controller in the Helper Loop ok? My controlling process ist not very fast. I think the runtime of the controller should be 0.1 s.
Nothing wrong with that in my opinion.
> I use a lot of shift register to transfer data or information inside the Helper Loop between different states. Is that a good way or are there any other best practice ways?
I would combine all data into a single cluster on a single shift register. Make sure you're connecting all the shift registers - in the "Data Acquired" case of the controller module, you are currently losing the DAQ task reference...
> This article describes that you if you have a architecture tree you should not skip generations. But in my case I use the data from the acquisition module directly in the controller module to avoid time delays.
Again, nothing wrong with this per se. Just be aware that you've created a static dependency between those modules - you cannot use the Controller without the Acquiring module anymore.
DSH Pragmatic Software Development Workshops (Fab, Steve, Brian and me)
Release Automation Tools for LabVIEW (CI/CD integration with LabVIEW)
HSE Discord Server (Discuss our free and commercial tools and services)
DQMH® (Developer Experience that makes you smile )
04-19-2025 12:56 AM
Hello Jörg,
wow, thank you so much for all your comments and detailed hints.
> Make a point of updating the VI icon of the module's library when creating a module. The "SNGLTN" on green background makes it difficult for me to understand which module's VIs I'm looking at.
Absolutely, I just forgot this in the first module.
- The Init DAQ and Start Controller requests have an array of resources as payload, but both really only need a single task. Would it be more readable and safer if the caller already selected the corresponding task to send?
That's true. In the future I want to use more than one task or device so I prepared it already for this case.
- For your Acquiring module, you could consider moving everything to do with the DAQ task into the helper loop if you don't need the resource in your MHL
Ok, I think you wrote this in your article. "To avoid clogging the message queue and slowing down the MHL..." So thats the advantage of moving everything into the helper loop.
- Why is the DAQ task a payload of the "DAQ did init" broadcast? Could/should that task be a private resource of the module?
I'm not sure about this. Later I want to handle all the modules and Requests with a Main Module which has also the UI for the test bench. So if I send and request and sepa rate the Init DAQ to a second request "Start Acquisition" I need the information about the DAQ task in the Main Module.
- You could create a typedef'ed cluster for the data on the HL shift register, similar to what the MHL has
Ok, but this typedef cluster just bundles the datatypes so that it is more structured? Or are there more advantages?
- In the HL, you should wire all the error outs to the error terminal on the bottom right of the case structure so it gets caught and propagated
Yes, thank you for this comment.
- For your Controller module, where is the DAQ task coming from? Who creates it?
I have a request equal to the Init DAQ request from the Acquisition module. Maybe I can move this also in the HL. I just seperated the the Init DAQ (Controller) and Start Controller requests because the controller should not work automatically time.
- Does the controller PID loop have to run at a different rate than the Acquisition loop? The broadcast already gives timing to the Controller PID loop, perhaps you don't need the timeout event? Also beware: Each time a broadcast is received, the timeout counter is reset! So if you receive broadcasts every 100ms and your timeout is also set to 100ms, you will never actually execute the timeout case!
That's brilliant and the input I needed. Thank's al lot. I will bring the PID into th broadcast event of the controller HL.
> I use a lot of shift register to transfer data or information inside the Helper Loop between different states. Is that a good way or are there any other best practice ways?
I would combine all data into a single cluster on a single shift register. Make sure you're connecting all the shift registers - in the "Data Acquired" case of the controller module, you are currently losing the DAQ task reference...
Ok, that makes sense for a better overview. So I also understand you comment above.
> This article describes that you if you have a architecture tree you should not skip generations. But in my case I use the data from the acquisition module directly in the controller module to avoid time delays.
Again, nothing wrong with this per se. Just be aware that you've created a static dependency between those modules - you cannot use the Controller without the Acquiring module anymore.
Yes, that's true. I want to handel it with the Main Module which is also the UI for the test bench.
Thank you very much Jörg.