05-24-2021 02:10 AM
Hi,
I my test sequences, I usually make the user press a "start button" to start the test sequence (or press "enter" on keyboard).
Now I want to make this also automatic, so there is an USB6001 analog input that when it's 0V when the fixture (bed of nails) is open, and 5V when it's closed. When the fixture is closed, my loop will receive the event to start (just like the click on the start button, or the enter key pressed).
So I thought about DQMH module would be a perfect fit for this.
I originally thought that a DQMH is a "state machine that can communicate with external modules or VIs".
But after the following considerations, I think a DQMH is not always a state machine.
I am doing this module like this:
MESSAGES TO THE MODULE (from outside):
MESSAGES (BROADCASTS) FROM THE MODULE (to registered handlers that are outside):
05-24-2021 06:59 AM
Hi Konan,
You are correct - a DQMH module in its default state (or more simply the Queued Message Handler design pattern), is not a state machine. For a good discussion on state machines with DQMH, take a look at Joerg's reference design here: https://forums.ni.com/t5/Random-Ramblings-on-LabVIEW/Parsing-State-Machines-An-Iterative-Design-Proc...
With regard to Check, be careful about using "Self messaging" in a Queued Message Handler. We used to do this a fair bit and it got us into trouble in the early days of us using DQMH, because you can't guarantee things will happen when you need them to, or in the order you're expecting. A helper loop might require more code, but it is a safer choice.
One way to handle this is to have a helper loop do regular quick reads of the input, and call the TEST STARTED broadcast when AI > 5V. From here, you can put the state (Open or Closed) onto the MHL queue each time the state changes, and place it in the MHL internal data.
So when the Check Request is received, you can simply reply with the current state.
I don't see why you need Test Finished. Is your DQMH module also controlling a digital output? I wouldn't expect your DQMH module needs to know the test status.
05-24-2021 09:33 AM
I have an INGUN fixture/bed of nail.
It is manual so the operator will have to "close it" so the nails contacts the DUT and the test sequence can start.
I am using a USB6001 (among other things), in particular I have cabled things so that:
I call my DQMH module as "AutoStart".
When my Functional Test Software starts, I do this:
In my FunctionalTest, I handle the "StartTest" broadcast event (I am registered to it as user event), and inside the event handler I just call ButtonStart.ValueSignal(True) on my UI button.
In this way I have automatically binded the start of the test sequence to an analog input.
Now the test will start....
Notice that in this moment the DQMH module is IDLE. It has only fired the event "StartTest" and it's just idle, waiting other messages.
after some seconds.... when test sequence state machine will end (either PASS or FAIL), I SEND a "TestFinished" to my DQMH module.
I need to send this because I need to "rearm" the start.
The user must OPEN the fixture (and I need to know this), insert another DUT, and close the fixture
So inside the "TestFinished" DQMH event handler, I check for the opening (read Dev1/ai6, and see if it is <0,5 --> still closed --> automessage TestFinished, ELSE send "Check" message ---> the fixture has been opened and now I will check for the closure.
05-24-2021 01:58 PM
I would definitely go with a "proper" state machine in a separate helper loop. Of course I'm biased because we took some time to develop such a reference design based on SSDC's fantastic design (thanks Chris for mentioning it) for ourselves and we're very happy with it; it's quite easily reusable, too.
Putting myself out there, and trying not to sound too dogmatic, I'll say the following:
- In my opinion, a regular DQMH module is not a state machine. Steve Watts gave a very interesting presentation on state machines at GDevCon #2, talking about many aspects and going into the details.
- Self-messaging is not a tool we use in our work (i.e. we don't allow it). It is much harder to read/follow, and Chris already mentioned potential problems with the missing atomicity and race conditions.
- In the majority of cases, a helper loop takes much less effort to create than it pays you back in terms of readability and stability.
From the bottom of my heart, I suggest you take another look at creating a proper state machine in a helper loop.
Also, feel free to use or copy our reference design. At the very least, you can make an informed decision to ignore it after giving it a brief glance. We're hosting the open-source repo containing our state machine template on GitLab:
https://gitlab.com/hampel-soft/dqmh/hse-module-templates
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 )
05-25-2021 08:59 AM
I'm not sure to get the right picture of the software architecture here, but I'm going to give my approach to this kind of situation.
This is obviously complementary to Joerg's reply. 🙂
I'd try to separate the autostart from the module that runs the test sequence:
This approach gives you more modules, but 2 of them are simple and decoupled from the rest of the application.
There are also no differences for your test sequence module to be in auto-start or in manual, and you can reuse it in another application where the start is handled differently.
Does it make sense in your use case?
05-25-2021 10:14 AM
I don't use DQMH myself, but I do have experience deciding on how to divide up a problem into "Modules", and I think you are not necessarily designing a simple/natural Module for your test "fixture".
Your fixture is something that is "Open" or "Closed", so the most natural and simple "Fixture" DQMH module would be one with a single Broadcast User Event called "fixture closed" true/false. When the Fixture reports closed, then some other module (perhaps called "Test Executor") will decide what to do. There is no need to complicate use of the Fixture Module by needing "Check" or "Test Started/Finished" messages. And it needs no State beyond Open/Closed (possibly plus "Fault").