Data acquisition workflow¶
This page covers what ADCL WinSoft does when you press Start DAQ during a run, where the data ends up, and how to feed it into downstream post-processing.
What happens when you press Start DAQ¶
- The application starts a
DaqWorkerbackground thread (code/adcl_winsoft/src/adcl_winsoft/daq/worker.py). - The worker opens a continuous NI-DAQmx task across all configured channels at the configured sample rate (default 5 Hz).
- Each tick, the worker reads one sample per channel, applies the per-channel slope/offset, applies the PGB matrix where applicable, derives the secondary signals (velocity, Reynolds), and writes:
- one row to the open CSV;
- one snapshot into
AppState.last_daqfor the UI; - one entry into each channel's rolling buffer (capped at 4096 samples, FIFO).
- The UI's 4 Hz refresh timer picks up
AppState.last_daqand updates the visible panels.
There are two paths from the worker into the UI — Qt signals and direct shared-state writes. The direct path is the backup that keeps the application responsive if signal delivery stalls. This is the "belt and suspenders" pattern in app.py.
CSV layout¶
Columns (typical):
| Column | Unit | Source |
|---|---|---|
t |
seconds since session start | DAQ worker timestamp |
i_pressure_static |
mA | NI-9203, raw |
i_pressure_model |
mA | NI-9203, raw |
v_pitch_angle |
V | NI-9215, raw |
mv_pgb_normal |
mV/V | NI-9237, raw |
mv_pgb_axial |
mV/V | NI-9237, raw |
mv_pgb_moment |
mV/V | NI-9237, raw |
p_static_pa |
Pa | calibrated |
p_model_pa |
Pa | calibrated |
pitch_deg |
degrees | calibrated |
pgb_n_N, pgb_a_N, pgb_m_Nm |
N, N·m | matrix-calibrated |
velocity_mps |
m/s | Bernoulli on static-ring ΔP |
re |
dimensionless | from velocity, model length, viscosity |
Exact column set depends on the channel map (daq/channel_map.py).
The filename format DDMMYY HHMMSS.fff<tag>.csv is inherited from AeroWare so existing post-processing scripts work unchanged.
Conventions for tagging runs¶
The optional <tag> in the filename is taken from the Acquisition panel's tag field. Use it to mark the run in a way the filename system can index — examples: _baseline, _naca0012_alpha_05, _smoke_only. Avoid spaces; use underscores. Avoid characters that the Windows filesystem rejects (: * ? < > | / \).
How much data per session¶
At 5 Hz with ~14 columns of doubles plus a timestamp, a CSV row is ~150 bytes. A one-hour session is roughly 2.6 MB. A full day of measurements is well under a gigabyte. Free space on E:\ is not a routine concern but check before starting if you are using a fresh drive.
Downstream post-processing¶
Post-processing is not in this repository — it lives with the individual experiments. The contract from ADCL WinSoft to downstream is the CSV format above and the matrix calibration on disk at E:\Wind_tunnel\AeroWare\Configs\N_C1_inv*.csv. If a downstream script reads the CSV and produces, say, force-vs-AoA plots, it can be invoked independently from MATLAB, Python, or a Jupyter notebook.
Validating against AeroWare¶
While ADCL WinSoft is still being validated, the workflow for a fresh calibration session is:
- Run AeroWare's DAQ pipeline (motor stopped) for a known reference condition.
- Save the AeroWare CSV.
- Run ADCL WinSoft's DAQ pipeline against the same physical state.
- Compare the engineering-unit columns. They should match to within transducer noise.
If they do not, the discrepancy is either in the channel map, the per-channel calibration, or the matrix application. Walk through daq/channel_map.py, daq/calibration.py, and the matrix file in that order.