LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Dr. Damien's Development - The Xylophone Project III - Specifications

Feedback on the GUI was excellent and the following changes will be made:

  1. The in–tune indicator will be changed from a red/green indicator to a green on/off indicator to accommodate color blind users. This does not impact the functionality in any meaningful way.
  2. The OK and Cancel buttons on the dialogs will be changed to both be adjacent to one another (like the configuration dialog).
  3. Controls will be added to the configuration dialog to set the parameters for the data acquisition. A tab control will be used to separate the analysis configuration (already shown) from the new acquisition configuration. The acquisition configuration will include acquisition rate, bit depth, and acquisition length.

We now have the GUI roughed out and the method of data acquisition determined. It is time to look at program architecture. It is highly tempting and very easy to simply paste the demo acquisition code behind the GUI concept and call it good. This may be OK for a home project (which this actually is), but does not result in robust, maintainable code.

 

As is normal for this type of code, there are two main loops — GUI and data acquisition. For GUI use, I prefer a synchronous, event driven state machine. For data acquisition, a simple state machine will work. Data acquisition will be bundled into an object. Communication will be handled with queues and user events.

 

Let's look at the communication in a bit more detail, since it will be a major determinant of the stability and ease–of–maintenance of the code. Do not neglect planning at this stage. It will save you endless headaches later on. Build in flexibility. You can expect things to change as you learn new things in the course of development.

 

We will need the following communications pathways:

  1. Data acquisition command queue - datatype is a bundle containing an enum for the command and a variant for the data; used to send commands to the data acquisition state machine
  2. Data acquisition data queue - datatype is a waveform datatype for the data bundled with an error cluster for error reporting; used to publish data from the data acquisition; assumes a single consumer
  3. Exit user event - datatype is a boolean; used by all dialogs to signal close in the event of a main panel close
Message Edited by DFGray on 02-20-2009 03:50 PM
Message Edited by DFGray on 02-20-2009 03:51 PM
Message 1 of 4
(4,849 Views)

Now for the data structures. We have identified the following:

  1. Configuration parameters
  2. Calibration parameters
  3. Data acquisition parameters

While we could conceivably put these all in the same data set, the code will be more scalable if we break it up. We will use LabVIEW objects to encapsulate the data. This also allows us to associate methods with each data set. We can also make singleton data objects from them if, as in the data acquisition case, we would like to access the same object in different parts of the code. This is done by loading the object into a single–element queue (you can also use an action engine).

 

Are there any other objects we may want to create? Yes! We need a sound analysis system to determine the resonant frequencies and the notes they represent. The data for this is just the configuration data (mode intensity cutoff, trigger level, data length, A frequency, etc.). Thus, the methods for the configuration data will be the analysis. We will be using even tempered tuning for now, but future use may expand to other tuning styles such as Pythagorean or one of the various meantone tunings.

 

Finally, is there any code out there we can reuse? The answer to this question is almost always yes. However, make sure you look at integration costs and licensing issues. In this case, there is a project that has a lot of code we can use. Check out NI Musical Instrument Tuner.

 

Were this a real project, I would write all this information up into a specification and put it under source code control as a living document. Said specification would be updated as the project advanced and would serve as input for the help and documentation for the project. We would also look into such subjects as panel resizing for vision impared users, color–blindness issues, and localization. Since it is a home project, I will not do this.

 

Next week, we start actual coding. Smiley Happy

Previous Installments

Message Edited by DFGray on 02-20-2009 03:51 PM
Message 2 of 4
(4,848 Views)

Thank you very much again. I actually was waiting friday afternoon for that post of yours, to get some inspiration for my own architectural design studies. Following such a project week by week is a greate way to exchange and learn. Once this series is finished, we should discuss to continue with a new project, maybe some of the great architects of the community could maintain one... (I guess Breakpoint would be the place to talk then...).

 

But to get conversation on techs: I not yet really get the complete archtecture. Maybe you could provide as with a scetch/draft. I like graphics (and my favorite programming language is...), simple bubble-arrow-style is standard in my own coding notes, uml earns bonus points.

 

Here are my open questions:

* Concerning GUI loop: will it be that Event-State moves to proper react on event state or do you drive a queued state machine from the event loop?

* Concerning DAQ loop: where are the in and out points of the queue located? Do we write to a data object via queue? Is it a producer/consumer pattern inside the Aquire state? Do we send the data to the GUI loop(s)?

* Configuration Windows: How will you call them, to be in need of the event? You could just place the Configuration Dialog in a locked Event case.

 

Some comments on the concept (as far as I understood it now):

* Data acquisition data queue, assumes a single consumer: Easy to scale up creating a multiplexer VI (input queue is dequeued, output queue array gets the data enqueued in a for loop).

* Reuse Code: Never forget OpenG. I personally like the Configuration VIs.

* Instead of boolean data type for 'Exit User Event' I would use an enum (in this case only the element Exit), because I can scaled it if necessary and the overhead is zero.

* For the communication pathways, there was a brilliant nugget by Ben how to link queues to a type defed data (and it works with events, notifieres as well).  Makes it easy to change the code if necessary.

 

Felix

0 Kudos
Message 3 of 4
(4,784 Views)

Open questions answered:

 

  • Concerning GUI loop: will it be that Event-State moves to proper react on event state or do you drive a queued state machine from the event loop?
    The event structure will be a state in a queue driven state machine, placing commands on the queue.  The queue data type will be a strict typedef enum command and a variant for data.  The queue cluster will also be strictly typedefed.  Thus, the commands will execute synchronously with the events. I have used separate event structure and command state machine loops in the past, but have always had more issues with it than combining the two.

  • Concerning DAQ loop: where are the in and out points of the queue located? Do we write to a data object via queue? Is it a producer/consumer pattern inside the Aquire state? Do we send the data to the GUI loop(s)?
    Input of the queue is in the acquisition loop.  Output will be either in analysis or calibration, depending on what is running at the time.  My original idea was to use a user event to signal the GUI loop to analyze the data (either for display or calibration).  Data rate is fairly low and the update rate will be about 10Hz, so the GUI loop should not be flooded due to this.  However, a cleaner architecture may be separate loops for the analysis and calibration, said loops (state machines) being embedded in the appropriate objects and always running.  The loops would trade off being consumer, depending on what functionality is currently active.

  • Configuration Windows: How will you call them, to be in need of the event? You could just place the Configuration Dialog in a locked Event case.
    The configuration windows would be called using the Run method and auto cleaning their references when the button for that window is pressed.  They would be modal so interaction with the root window would not be possible while the configuration window is up.  This allows the GUI loop to keep executing while the configurations are up.

 

I originally intended to include some graphics for the architecture, but ran out of time. Smiley Sad

 

Message 4 of 4
(4,729 Views)