Good morning ladies and gents,
I'm hoping that somebody can show me the most effective/efficient way to log data without having to poll a 'record' button. I've created a small example using a producer/consumer architecture where I want two things to happen:
1. Continuously Read data and display to a waveform chart.
2. Send data to a queue to be recorded when the 'record' button is pressed.
I've looked into the Queue Message Handler architecture and I'm starting to implement something with a different program that I'm working on but I always get stuck when trying to implement this simple recording feature. I've thought about placing the DAQmx read function inside an event structure and using the event timeout to control the desired loop timing...then have a separate shift register for a boolean constant that I could update with separate start and stop recording latched buttons (this would essentially control the case structure with the enqueue element). But I have much more going on in the program that I'm working on and this method won't work (because there are 4 more tasks other than the AI task in this small example).
I don't use queues very often so I'm sure that there's a simple way to just discard the data if I don't want to record it but I thought that it might be less CPU intensive if I didn't send the data to the queue in the first place unless I want to record it.
Any suggestions or help would be greatly appreciated.
Solved! Go to Solution.
Try putting the "record" button in an event structure. Look at the Queued Message Handler examples. It will probably result in three parallel loops, with one being the event handler actually reading your buttons, one handling the result of the messages generated by the event handler, and a third loop with the actual data acquisition
As a regular QMH user, here are some quick thoughts:
- I'd have an independent QMH loop for the AI DAQ task. It'd handle messages like "Config AI", "Start AI", "Stop AI", "Exit". When the task was running, it would push data into the queue used by my main application loop.
- My main application loop would have a shift register containing things like the booleans you described plus a whole bunch of other stuff that helps define the app's operating state. They would be bundled into a typedef'ed cluster. The main app would be the brain of the operation and decide whether or not to send a copy of the data off to a file logging loop
- Thus, I'd have an independent file logging loop as well. There'd be messages like "Config", "Write Data", and "Exit". Maybe that's about it. When not writing, it'd just idly sit waiting at the Dequeue and not burn CPU.
The QMH pattern allows any loop to talk to any other loop, but I find it more tidy to centralize the "brain" of the app to be in the main loop. The AI DAQ loop only has to report its data up to the main loop and doesn't have to concern itself with any application logic about whether logging is happening or not. The main loop will dequeue the data for display purposes and in the case where it does, it can also make decisions about whether or not to send a copy off for logging. I keep logging separate b/c file access can sometimes slow things down, so I want it happening in an independent loop to keep the main loop responsive.
Thanks for the reply. I have been working on this actually. Maybe I will try to finish the program (as much as possible) and then upload again. I was hoping to have my head wrapped around this so I don't get trapped in a corner a few days down the road and have to start all over again.
The program i'm working on is based on the QMH. It has 5 loops: an event handling loop, a UI loop, a data acquisition and control loop, a data logging loop and a data display loop. In the QMH with logging template, the user presses the start button to start acquiring data and recording data at the same time. The data is read and then sent to a queue and a notifier in the acquisition loop. The notifier is used to display the data and the queue is used to log data as it comes in.
I want the program to have a "monitoring" capability where nothing is being recorded, just monitored on screen, until the user presses a record button. I just figured that I shouldn't be sending the data to the queue if I don't want to record it.
I will play around with the QMH a little more and re-post when I have something that won't waste anybody's time.
Thank you for the suggestions. The shift register in the "Main" loop will make things easier. I'll re-post as soon I can with the actual program.
For the application you posted, I think it can all be done in one loop, no need for QMH, unless you want to expand your program later.
Here are some steps:
Here's an example of the states you may go through to configure the DAQ.
DAQ: Stop (if running)
DAQ: EndTask (if running)
I like mcduff's suggestion. Sounds like a clean way to bring it all into 1 loop, preventing a lot of potential complications. I like the QMH in general, but there's a price to pay in overhead and indirectness. For a small-ish app, there's probably more cost than benefit.
Funny you should mention the JKI state machine. I was just watching a tutorial online about it the other day. I will download it and see if the architecture will work for me. Hopefully I get this done in the next few days and I can re-post to make sure that i'm not missing something critical.
I really appreciate all of the suggestions and advice from everyone.
Unfortunately I can't upload the final VI. However, I ended up using a different structure from what I originally said was the "solved" solution. I'm using a queued message handler structure. The JKI state machine would also work but I had already put in so much time with the other structure I decided to stick with it. If I have any spare time, I will refactor the VI into the JKI state machine (for learning purposes).