LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

QMH | How to implement timed I/O communication

Hello everybody,

 

I just started a new project and wanted to use QMH architecture for this. I started by looking into the LabView template and got it customized to fit my use case but now I got to a point where I can't figure out how to effectively implement timed operations in QMH design. One requirement to the project is to communicate in a bidirectional manner with a hardware device.

 

Requirements for device communication:

- Reliably perform a read operation at an adjustable time interval.

- Perform a write operation immediately if e.g. some buttons on the gui were pressed or values changed.

- Prohibit simultaneous read & write operations.


If I only use one message handler queue for these requirements, which gets invoked only in a certain time interval, I can't react to incoming write messages.
If I use multiple handlers/queues, I must control simultaneous read & write which interfers with the timing aspect.

How would you implement this? Am I maybe missing some key idea?

 

Thanks in advance.

0 Kudos
Message 1 of 12
(2,142 Views)

Could you elaborate?  "Read periodically and Write on demand" sounds easy to do with one loop.  

0 Kudos
Message 2 of 12
(2,130 Views)

"Read periodically and Write on demand" is exactly the thing I want to do.

So e.g. I have one message handler loop for this purpose.

If I want to perform a read at e.g. every 200ms, I would dequeue a message only every 200ms and after the read has finished I would append another read message and wait again 200ms. But in between the loop won't iterate and I can't react to write messages.

I could use another loop to send a read message every 200ms to the message handler. which then won't need to wait at all.
I guess there must be a simpler solution.

0 Kudos
Message 3 of 12
(2,107 Views)

Ah.  There are multiple ways to do timed periodic actions for a loop.  I use at least three, including having a "metronome" loop sending timed messages, as you suggest.   So go with that. 

 

The "send a message to yourself after a wait" is usually a poor technique, and it annoys me that such things get used in NI templates.  In general, I recommend against even looking at NI templates; they are pretty dreadful designs.

Message 4 of 12
(2,062 Views)

What I have done is use the timeout capability of the queue to time periodic actions.  In my latest iteration, I have a class that holds the queue reference, what the timeout for the queue should be, and the case to run when the queue times out.  The timeout is set to -1 by default, meaning the queue will never time out as it is waiting for a message.  When the start command comes through, I set the timeout to (using your example) 200ms and the timeout case to be "Read".  My QMH will then perform a read approximately every 200ms while still able to receive incoming messages.  Incoming messages can mess up the timing.



There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 5 of 12
(2,045 Views)

@crossrulz wrote:

Incoming messages can mess up the timing.


One can correct for that by the method of a "calculated timeout".  Keep track of the next scheduled read time and calculate the difference to the current time.  If at or past the scheduled time, then do the read and record the new next scheduled time, else use the difference in milliseconds as the timeout.  This can give driftless timing that isn't messed up by incoming messages.

0 Kudos
Message 6 of 12
(2,009 Views)

@drjdpowell wrote:

@crossrulz wrote:

Incoming messages can mess up the timing.


One can correct for that by the method of a "calculated timeout".  Keep track of the next scheduled read time and calculate the difference to the current time.  If at or past the scheduled time, then do the read and record the new next scheduled time, else use the difference in milliseconds as the timeout.  This can give driftless timing that isn't messed up by incoming messages.


...at the expense of needing to distribute this "timeout behavior" knowledge into multiple message cases.

 

I tend to opt for your first suggestion -- the independent loop whose job is to send messages at a constant time interval.  (Plus, of course, means for starting and stopping the "sends" as well as loop termination.)   A little extra distributed knowledge tends to be required, but usually (IMO) less than the 1-loop recalculated timeout method.

 

To the OP:  these are just minor quibbles.  Any of these approaches can work out -- some are simpler to implement, others are more regular in timing.  There's not a universal *best* way, just different kinds of trade-offs to be made.

 

 

-Kevin P

 

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
0 Kudos
Message 7 of 12
(1,997 Views)

@Kevin_Price wrote:

@drjdpowell wrote:

@crossrulz wrote:

Incoming messages can mess up the timing.


One can correct for that by the method of a "calculated timeout".  Keep track of the next scheduled read time and calculate the difference to the current time.  If at or past the scheduled time, then do the read and record the new next scheduled time, else use the difference in milliseconds as the timeout.  This can give driftless timing that isn't messed up by incoming messages.


...at the expense of needing to distribute this "timeout behavior" knowledge into multiple message cases.


1. That is easy enough to take care of with class methods, possibly outside of the cases (I have not explored this at all yet).

2. 99% of the things I am using a QMH for have other hardware that is taking care of the timing (think DAQ here) or I don't care how exact the timing is (remote terminals).



There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 8 of 12
(1,991 Views)

@Kevin_Price wrote:

...at the expense of needing to distribute this "timeout behavior" knowledge into multiple message cases.

 


I not sure what you mean.  This is usually a single subvi located in one place, not in any message case.

0 Kudos
Message 9 of 12
(1,981 Views)

@drjdpowell wrote:

@Kevin_Price wrote:

...at the expense of needing to distribute this "timeout behavior" knowledge into multiple message cases.

 


I not sure what you mean.  This is usually a single subvi located in one place, not in any message case.


Gotcha.  I was too quick to *assume* that timeout changes would need to be handled in each of (possibly) several distinct message cases where changes were possible.  But I hear ya, you can also do it outside of all the message cases, and have other approaches for only changing it when needed.

 

What I've *actually* done is:

1. created a library for "scheduled messages" that would spawn a process dedicated to sending a specific message at a fixed interval.  This is no different in principle from having a separate loop, it just encapsulates the functionality for re-use.

2. modified the QMH template to include internal support for similar "scheduled messages".   This includes wrapper functions for dequeuing that also have knowledge of any "scheduled messages".   Now that it's integrated 'inline" as part of our mostly generic QMH template, this is what I actually use most of the time.  There are still occasions where I use the spawned process approach, but it's pretty rare any more.

 

But apart from these bigger infrastructural kinds of code, I think the simplest path forward for the OP is either a separate message-sending loop or some kind of timeout-reaction.  The main consideration is whether timing consistency matters a lot (separate sending loop, or recalc'ed timeout value) or not (const timeout value, where actual timeouts are relatively rare or insignificant).

 

 

-Kevin P

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
Message 10 of 12
(1,967 Views)