DQMH Consortium Toolkits Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Stuck at design of a DQMH module

Hey everyone,

 

for the last couple of days, I've tried to design a DQMH module that handles communication to a device under test (in the end being used in conjunction with TestStand).

The device is a serial device that has some caveats...

 

When I list all the requirements / behaviors, I get the following list:

  1. The device sends, as one of its functions, data as a response to requests.
  2. The device also sends data event-based (something in the device changes, and it communicates that to the outside world)
  3. I have low-level commands (restarting device, sending passwords, reading memory regions, etc.)
  4. I have high-level "functions" that are combinations of low-level commands (commands executed after each other), some data manipulations and smaller other stuff (calculating sepcific data, etc.)
  5. Messages in itself contain info regarding length of message at fixed position
  6. Replies are sending back the CMD (one exception being an ACK message that is common for all CMDs that only send back an ACK)

So far, I designed the following apporach:

  • EHL forwards to MHL (standard)
  • MHL sends out requests to device and adds expected response (including the events for the reply) to an array of expected responses (type-def cluster) in a DVR
  • Separate helper loop pulls for "BytesAtPort" every couple milliseconds and then reads the message (based on length with received data)
    This data is then compared to the array of expected responses in the DVR:
    If it matches one entry, that one entry is removed, received data is processed and then send back to the "caller" as a reply (overall event is Request/Reply in DQMH).
  • If it is not found in the expected answers list, the message is being processed based on the CMD that it is a response to and that information is save to be later requested via the API or shown to the user.

This works so far, BUT ....

I can't wrap my head around the following use cases:

  • high-level "functions" that are combinations of low-level commands executed after each other:
    Here I would need to perform intermediate steps in the MHL (send a cmd, process response, use data from response for next cmd), while each of these steps is in itself probably a Req/Reply in the DQMH module, since that CMD needs also be available independently. 
  • It is rather cumbersome since every CMD with a response needs two VIs (one for sending asynchronously, one for processing the response), since they are called at different places in the code.

The goal was to achieve this coexistence of Reply/Reponse with the device and the added benefit of also having event-based messages.

 

I can't seem to shake the feeling that this not the KISS-solution to the idea / problem.

Could someone more experinced maybe give a point in the direction as to what might be a good solution for this scenario.

I consider this quite common, especially with for example CANopen systems (responses come at various times with other messages in-between and the received message needs to be mapped to the corresponding request (that was sent a long time ago, maybe).

 

Thanks !

 

Cheers

Niels 

0 Kudos
Message 1 of 12
(4,221 Views)

Hi Niels,

 

A couple of questions for you to clarify your problem:

 

Do you have two DQMH modules in your example here?  One for managing and the other for communicating to the device or are you just using one?

 

The bits I'm confused about are:

"MHL sends out requests to device and adds expected response (including the events for the reply) to an array of expected responses (type-def cluster) in a DVR"  - When you say "requests", do you mean you're calling requests of another module, or just calling a VISA VI to write a command for instance?

 

"...and then send back to the "caller" as a reply (overall event is Request/Reply in DQMH)" - Which caller?  Where is the call coming from - is this the request you talk about in the MHL?  I can't see how this would work, because if you're in the MHL waiting for a reply, you won't ever get a response?

 

 

Christopher Farmer

Certified LabVIEW Architect and LabVIEW Champion
DQMH Trusted Advisor
https://wiredinsoftware.com.au

0 Kudos
Message 2 of 12
(4,180 Views)

Hi Christopher,

 

thanks for responding so quickly...

 

To answer your questions and to clarify my problem(s) a litte:

I have one DQMH module.

This module is called from the outside by either TestStand or for now the API Tester.

This module should handle all communication with the DUT.

 

The bits I'm confused about are:

"MHL sends out requests to device and adds expected response (including the events for the reply) to an array of expected responses (type-def cluster) in a DVR"  - When you say "requests", do you mean you're calling requests of another module, or just calling a VISA VI to write a command for instance?


Your are right, I mixed up the terms and used request for both comunication types, to the DQMH and to the DUT.

In this case, I meant, that the MHL sends a message via VISA / UART to the DUT and then, when an answer is expected from the DUT, adds an entry to the array of expected responses from the DUT. This entry in the array includes the event, with which the DQMH module sould response to its caller. This is done, so that, when my separate helper loop receives the correct response from the serial interface, it can use the event, provided by the caller of the DQMH, to respond to the caller.

 

"...and then send back to the "caller" as a reply (overall event is Request/Reply in DQMH)" - Which caller?  Where is the call coming from - is this the request you talk about in the MHL?  I can't see how this would work, because if you're in the MHL waiting for a reply, you won't ever get a response?


I think this correlates with what I wrote before. Caller refers to the outside caller of the DQMH module. 

The whole idea behind this "list of expected responses" was to ensure, that the MHL sends the message to the DUT, but does not wait for the response to stay "non-blocked" (reading from serial is handled in the helper loop).

I got this idea, since the DUT sometimes needs a couple of seconds to complete a command and reply.

Furthermore, the DUT might send event-based messages, so I might send out a commmand, the DUT send me an event-based message and then the actual reply to my command. And the event-based message shouldn't be lost etiher.

 

EDIT:

Regarding "higher"-functions that consist of several low-level functions executed after each other:

I would like to use the same events (API) for the low-level functions as when calling them directly..
This is not really "atomic" as per https://delacor.com/simple-dqmh-dos-and-donts/..
But somehow it does not (yet) feel right to duplicate those command calls ..

I'm thinking, that maybe adding another helper loop for these higher-level functions might be a solution...
This loop then sends the low-level-functions to the module (ala "itself") through the EHL and can wait for reply, which is generated identically from the first helper loop.

 

I draw a quick diagram of the structure, since I cannot share code. If necessary, I might be able to boil the code down to something showing my issue.

 

Thanks!

 

Cheers

Niels 

0 Kudos
Message 3 of 12
(4,172 Views)

Niels,

 

I don't know if I like that your "reply" is coming from the helper loop.  I would discourage you not to take the reply from the MHL where it typically would be, and putting it into the helper loop as you currently do it.  You are breaking the DQMH architecture as a result.  Curious to know what Fab would say about this.

 

What might be better is if you used Roundtrips instead of Request and Wait for Reply events.

 

By using a Roundtrip, the reply from the helper loop (where you marked #6 in your diagram) would be a broadcast instead of a Reply to a request.

Christopher Farmer

Certified LabVIEW Architect and LabVIEW Champion
DQMH Trusted Advisor
https://wiredinsoftware.com.au

0 Kudos
Message 4 of 12
(4,143 Views)

Hi Christopher,

 

sending the reply from the helper loop was kind of a necessity, since the outside caller (TestStand) needs to wait for that answer (and using broadcasts for this makes it quite cumbersome in TestStand).

 

For me, the MHL wasn't the definitive place to send the reply... Curious for Fab's response as well...

 

 I'm currenty thinking about using two DQMH modules (one that just forwards simple CMDs and handles sequences of CMDs), while the other handles the actual low level commands. 

 

Thanks !

 

Cheers

Niels 

0 Kudos
Message 5 of 12
(4,129 Views)

@ngblume wrote:

 

 

For me, the MHL wasn't the definitive place to send the reply... Curious for Fab's response as well...

 


I wouldn't think it would matter.

Sam Taggart
CLA, CPI, CTD, LabVIEW Champion
DQMH Trusted Advisor
Read about my thoughts on Software Development at sasworkshops.com/blog
GCentral
0 Kudos
Message 6 of 12
(4,114 Views)

Hey,

 

I implemented it as two DQMH modules now, and it works as expected and was quite easily done.

Still curious, if there is another, "better" solution out there; better in the sense of "easier to implement with DQMH"..

 

When using two modules, I would like to forward some status updates from the low-level DQMH to the high-level DQMH..
When starting the low-level DQMH during initialization of the high-level DQMH, I get the refs for the broadcast events.

But where would be the best place to register for those??
When looking at the VI Testers, the event loop to register those to, is obvious, but in the case of another DQMH not so much for me..
First idea would be to have them registered with another helper loop.. Seems doable, but also slightly weird...

Cheers

Niels 

0 Kudos
Message 7 of 12
(4,091 Views)

Hi Niels,

 

My apologies that I had not checked the forums in several days. I am so grateful that one of our DQMH Trusted Advisors was here to give you sound advice. Thanks to Chris!

 

As you mentioned, this is a very common approach, so much that we internally have a DQMH template for serial devices. Actually, we have more than one template. There is the template for the devices that can be set on streaming mode and there is a separate template for the serial devices that return a package via the serial port when we send a command.

 

Our templates have a similar structure to what you designed minus the DVR. We implemented the communication via VISA with a serial device class. Because I insist on doing unit tests, our commands and reply formatting are separated from the VISA calls. This makes it easier to simulate VISA communication. A full send command wait for a response code is implemented then using three VIs: The VI the forms the Command, the VI that sends the Command via VISA, the VI that compares the response to the expected response format. 

 

Things get complicated when, like in your case, the device can be sending other messages outside of when it is being talked to (how rude! 😉 ). In those cases, you do need a helper loop that is monitoring constantly the serial port and you can easily get into a situation that the VI above that was parsing responses gets a generic message that has nothing to do with the command sent.

 

I have been trying to think of different ways to implement that and I keep coming back to your DVR approach. I believe we had to implement something similar when we had to communicate with third-party software that sent JSON messages via UDP. I will have to dig out that code, but I believe we did use a DVR in that case and it as very similar to what you describe. I will try to find the code during the weekend.

 

By the way, a sneak peek to our serial device code is found in the second video of Tip 5 on this blog post:

http://delacor.com/tips-and-tricks-for-a-successful-dqmh-based-project/

 

The approach of 2 DQMH modules sounds OK to me too, especially if this helps you separate the continuously monitoring the port from the actual requests and wait for replies. I would have to take a look at the code to give you more useful advice. 

 


@ngblume wrote:

Hey,

 

I implemented it as two DQMH modules now, and it works as expected and was quite easily done.

Still curious, if there is another, "better" solution out there; better in the sense of "easier to implement with DQMH"..

It is really hard to find the "best" solution, it sounds that your solution works well for you. Our solution with the classes works well for us. Both are good solutions because they were straightforward to implement and they are maintainable. If you end up having circular dependencies between these two modules, that would be OK too because your two modules are meant to always be used together.

 


@ngblume wrote:

Hey,

 

When using two modules, I would like to forward some status updates from the low-level DQMH to the high-level DQMH..
When starting the low-level DQMH during initialization of the high-level DQMH, I get the refs for the broadcast events.

But where would be the best place to register for those??

Inside the high-level DQMH, you have several options:

1) start the low-level DQMH module outside the large Error case that houses the MHL and EHL. This will give you the registration for the events right there.

2) start the low-level DQMH module inside the initialization case, in this case, you would have to create a private event that when handled at the EHL case, registers for the DQMH low-level DQMH module. You could also just start the low-level DQMH module in this EHL case. In this case, you would still have to wire the Obtain Broadcast Events for Registration.vi outside of the Error case, so you can "declare" your event types.

 

Here is a thread that describes option 2:

https://forums.ni.com/t5/Delacor-Toolkits-Discussions/Module-broadcasts-registered-but-events-never-...

 

A longer thread that describes both options:

https://forums.ni.com/t5/Delacor-Toolkits-Discussions/Registering-to-broadcast-events-from-many-modu...

 

I hope this helps!

Thanks again for your trust in DQMH and in our team.

 

Fab

For an opportunity to learn from experienced developers / entrepeneurs (Steve, Joerg, and Brian amongst them):
Check out DSH Pragmatic Software Development Workshop!

DQMH Lead Architect * DQMH Trusted Advisor * Certified LabVIEW Architect * Certified LabVIEW Embedded Developer * Certified Professional Instructor * LabVIEW Champion * Code Janitor

Have you been nice to future you?
Message 8 of 12
(4,073 Views)

Hi Fabiola,

 

thanks for adding to the discussion and no worries!

As you said, the Trusted Advisors helped greatly.

 


@FabiolaDelaCueva wrote:

Our templates have a similar structure to what you designed minus the DVR. We implemented the communication via VISA with a serial device class. Because I insist on doing unit tests, our commands and reply formatting are separated from the VISA calls. This makes it easier to simulate VISA communication. A full send command wait for a response code is implemented then using three VIs: The VI the forms the Command, the VI that sends the Command via VISA, the VI that compares the response to the expected response format. 


Same here, since sending the commands is identical (most of the times) and often includes several common tasks (asserting lines like RTS, etc.)

Only difference: our third VI is extracting the message content after it has been matched by an identifier or something similiar by our "receiving engine" (for lack of a better wording)..

 


@FabiolaDelaCueva wrote:

Things get complicated when, like in your case, the device can be sending other messages outside of when it is being talked to (how rude! 😉 ). In those cases, you do need a helper loop that is monitoring constantly the serial port and you can easily get into a situation that the VI above that was parsing responses gets a generic message that has nothing to do with the command sent.

 

I have been trying to think of different ways to implement that and I keep coming back to your DVR approach. I believe we had to implement something similar when we had to communicate with third-party software that sent JSON messages via UDP. I will have to dig out that code, but I believe we did use a DVR in that case and it as very similar to what you describe. I will try to find the code during the weekend.


Yeah, I feel you.. These chatty modules 😉
An example of code would be greatly appreciated...
I got the feeling, that pretty much every multi-master bus would need something like this (CAN for example).

UDP kind of is like a multi-master bus (in a way)...

 

One question came up while progressing with the two modules...
We will have different time-outs for different Reply-Response events.

This can easily be achieved by creating a control for the time-out in the individual "calling" VI of the Public API.

But this is a "client-side" timeout. The module itself doesn't know what duration the time-out of the response-event created by the client is/was set to.

Is this correct?

 

My idea was to have the module have the expected response in its DVR for a time duration a little less than the time-out for the reply-request event, that caused the module to send out the command and placed the expected response in the list in the first place.

When this duration expires, the expected response is simply removed from the expected-reponses-list, since even when the correct answer would be received now, it would be too late to reply with it to the caller (creator of the event).

Any specific reason why this information is not automatically included in the Argument CTL of an event? And exposed automatically at the "calling" VI of the Event's Public API?

 

Thanks !

 

Cheers

Niels 

 

0 Kudos
Message 9 of 12
(4,021 Views)

Hi,

 

@FabiolaDelaCueva did you get a chance to look for the source code?

 

Thanks !

 

Cheers

Niels

0 Kudos
Message 10 of 12
(3,958 Views)