DAQ - mahilab/MEL GitHub Wiki
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-fast
Once 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).
Modules
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
).
Channels
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 function
The 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 conversion
Likewise, 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 conversion
Updating Modules and Channels
Setting 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 C
You 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.
Relevant Examples
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 |