Skip to main content

streamreader_2d_signal/
streamreader_2d_signal.rs

1// Read a dimensioned ("2-D") signal: feed a sine wave into the reference FFT
2// function block and read amplitude spectra, where every sample is a whole
3// row of frequency bins.
4
5use opendaq::{Channel, Instance, StreamReader};
6
7fn main() -> opendaq::Result<()> {
8    let instance = Instance::new()?;
9    instance.add_device("daqref://device0")?;
10
11    let channel = instance
12        .find_component("Dev/RefDev0/IO/AI/RefCh0")?
13        .expect("reference channel not found")
14        .cast::<Channel>()?;
15    channel.set_property_value("Waveform", 0)?; // 0 = Sine
16    channel.set_property_value("Frequency", 125.0)?;
17    channel.set_property_value("Amplitude", 5.0)?;
18    channel.set_property_value("NoiseAmplitude", 0.1)?;
19
20    let fft = instance
21        .add_function_block("RefFBModuleFFT")?
22        .expect("FFT function block not found");
23    fft.set_property_value("BlockSize", 16)?;
24    fft.input_ports()?[0].connect(&channel.signals()?[0])?;
25    let signal = &fft.signals()?[0];
26
27    // Wait for the block to publish its output descriptor, then read the
28    // frequency axis off the value descriptor's single dimension.
29    std::thread::sleep(std::time::Duration::from_secs(1));
30    let descriptor = signal
31        .descriptor()?
32        .expect("output descriptor not published");
33    let dimension = &descriptor.dimensions()?[0];
34    let axis: Vec<f64> = dimension
35        .labels()?
36        .iter()
37        .map(|label| label.as_f64().expect("numeric frequency label"))
38        .collect();
39
40    // Read 5 samples.  Each sample is a full spectrum, so `read` returns a
41    // (samples x bins) matrix; retry until 5 rows have arrived (the first
42    // reads may come back short while the stream warms up).
43    let reader = StreamReader::<f64>::new(signal)?;
44    let mut spectra = reader.read(5, 1000)?;
45    for _ in 0..50 {
46        if spectra.sample_count() == 5 {
47            break;
48        }
49        spectra = reader.read(5, 1000)?;
50    }
51
52    // Print the axis down the rows and one column of amplitudes per sample.
53    // The 125 Hz tone dominates a single bin (~5, our amplitude) while noise
54    // fills the rest with small values.  The reference block labels its bins
55    // one step (31.25 Hz) below the true bin centre, so the tone lands in the
56    // 93.75 Hz row.
57    println!(
58        "{} spectrum, {} bins, {}\n",
59        dimension.name()?,
60        axis.len(),
61        dimension.unit()?.expect("dimension unit").symbol()?
62    );
63    print!("{:>12}", "freq (Hz)");
64    for sample in 1..=spectra.sample_count() {
65        print!("{:>14}", format!("sample {sample}"));
66    }
67    println!();
68    let rows: Vec<&[f64]> = spectra.rows().collect();
69    for (bin, frequency) in axis.iter().enumerate() {
70        print!("{frequency:>12.2}");
71        for row in &rows {
72            print!("{:>14.4}", row[bin]);
73        }
74        println!();
75    }
76    Ok(())
77}