-
Notifications
You must be signed in to change notification settings - Fork 3
DAQ
At the heart of the MEL library is the DAQ framework, which abstracts low level access to various devices into easy-to-use and flexible C++ Daq classes. At present, MEL provides interfaces for the following DAQs with plans to integrate more in the near future.
| DAQ | Header | Operating System(s) |
|---|---|---|
| Quanser Q8-USB | <MEL/Daq/Quanser/Q8Usb.hpp> |
Windows |
| Quanser Q2-USB | <MEL/Daq/Quanser/Q2Usb.hpp> |
Windows |
| NI myRIO | <MEL/Daq/NI/MyRio/MyRio.hpp> |
NI Linux Real-Time |
A Daq object can created and opened in the following way:
MyRio myrio;
if (!myrio.open())
return 1; // the device did not open, fail-fastOnce a DAQ is open, it can be enabled:
myrio.enable()The distinction between open() and enable() is that open() simply initializes communication between the software and hardware drivers, while enable() sets the device to its initial state (e.g. setting initial digital or analog outputs to 0 V or some other values).
Each Daq contains a number of Modules. A Module can be thought of as a bus or bank of same-type I/O channels. MEL currently implements the following Module types:
| Module | Description | Physical Units | C++ Type |
|---|---|---|---|
| AnalogInput | Channels which read analog voltages | V | Voltage (aka double) |
| AnalogOutput | Channels which write analog voltages | V | Voltage (aka double) |
| DigitalInput | Channels which read TTL logic levels | TTL | Logic enum |
| DigitalOutput | Channels which write TTL logic levels | TTL | Logic enum |
| DigitalInputOutput | Channels which can read or write TTL logic levels | TTL | Logic enum |
| Encoder | A quadrature encoder input | counts | int |
Modules are contained within Daqs as member variables, and may be organized in different ways to match the physical hardware configuration. For example, the Modules on Q8Usb are accessed directly through the class itself (e.g. q8.AO, q8.DI, q8.encoder, etc.), while MyRio provides an intermediate abstraction for each connector interface (e.g. myrio.mxpA.DO, myrio.mspC.encoder, myrio.mxpB.AI).
Each Module contains a number of Module::Channels. Channels can be retrieved in two ways:
Encoder::Channel enc1 = myrio.mspC.encoder[1]; // bracket operator overload
AnalogOutput::Channel ao0 = myrio.mspC.AO.get_channel(0); // member functionThe current value on Channels of Input type Modules can be retrieved like so:
int counts;
counts = enc1.get_value(); // with a channel variable, or ...
counts = myrio.mspC.encoder[1].get_value(); // with the Module, or ...
counts = myrio.mspC.encoder[1]; // automatic conversionLikewise, the current value on Channels of Output type Modules can be set like so:
double voltage = 5.0;
ao0.set_value(voltage); // with a channel variable, or ...
myrio.mspC.AO[0].set_value(voltage); // with the Module, or ...
myrio.mspC.AO[0] = voltage; // automatic conversionSetting or getting the current value on a Module only sets or gets the buffered value stored in memory. To synchronize this value with the real-world, you must explicitly update inputs and outputs. You can do this at three levels: the Daq level, the Module level, or the Channel level. Here are a few examples:
myrio.update_input(); // updates all inputs on each myRIO connector
myrio.update_output(); // updates all outputs on each myRIO connector
myrio.mspA.update_input(); // updates all input modules on connector A
myrio.mxpB.AO.update(); // updates all channels on AO module of connector B
myrio.mspC.AI[1].update(); // updates only analog input channel 1 on connector CYou are encouraged to call functions which update DAQs or Modules together over per-Channel updates. Usually these functions will use a more efficient read/write operation from the underlying device API.
| Example | Description |
|---|---|
| ex_q2usb.cpp | General overview of Q2-USB usage |
| ex_q8usb.cpp | General overview of Q8-USB usage |
| ex_q8usb_loopback.cpp | Performs loopback on all analog and digital Q8-USB channels |
| ex_mryio.cpp | General overview of myRIO usage |