// Analog input quick start for C# / .NET.
//
// Works with every model on the site — only the device and channel names change.
//
// 1. Add a reference to NationalInstruments.DAQmx.dll
// 2. dotnet run --project DaqQuickStart -- Dev1 ai0:3
//
// The synchronous read loop below is the simplest correct pattern. For
// continuous acquisition use a DaqStream / AnalogMultiChannelReader with a
// callback, or an async Task, so the UI thread is never blocked.
using System;
using System.Linq;
using NationalInstruments.DAQmx;
internal static class DaqQuickStart
{
private static int Main(string[] args)
{
string device = args.Length > 0 ? args[0] : "Dev1";
string channels = args.Length > 1 ? args[1] : "ai0:3";
Console.WriteLine($"Device : {device}");
Console.WriteLine($"Channels : {channels}");
Console.WriteLine();
try
{
ReadSinglePoints(device, channels, samples: 10);
ReadBufferedBlock(device, channels, rate: 10_000.0, samplesPerChannel: 1_000);
}
catch (DaqException ex)
{
Console.Error.WriteLine($"DAQ error ({ex.Error}): {ex.Message}");
Console.Error.WriteLine("Check the device name with NI MAX or the configuration utility.");
return 1;
}
Console.WriteLine("Done.");
return 0;
}
/// Software-timed single-point reads — for slow signals.
private static void ReadSinglePoints(string device, string channels, int samples)
{
Console.WriteLine($"Single-point reads on {device}/{channels}");
Console.WriteLine(new string('-', 56));
using (Task task = new Task())
{
task.AIChannels.CreateVoltageChannel(
$"{device}/{channels}",
nameToAssignToChannel: "",
terminalConfiguration: AITerminalConfiguration.Rse,
minimumValue: -10.0,
maximumValue: 10.0,
voltageUnits: AIVoltageUnits.Volts);
AnalogSingleChannelReader reader = new AnalogSingleChannelReader(task.Stream);
for (int i = 0; i < samples; i++)
{
double value = reader.ReadSingleSample();
Console.WriteLine($" {i + 1,3} {value,10:F5} V");
System.Threading.Thread.Sleep(200);
}
}
Console.WriteLine();
}
/// Hardware-timed block using the device sample clock.
private static void ReadBufferedBlock(
string device,
string channels,
double rate,
int samplesPerChannel)
{
Console.WriteLine($"Buffered acquisition on {device}/{channels}");
Console.WriteLine($"{rate:N0} S/s, {samplesPerChannel:N0} samples per channel");
Console.WriteLine(new string('-', 56));
using (Task task = new Task())
{
task.AIChannels.CreateVoltageChannel(
$"{device}/{channels}",
nameToAssignToChannel: "",
terminalConfiguration: AITerminalConfiguration.Rse,
minimumValue: -10.0,
maximumValue: 10.0,
voltageUnits: AIVoltageUnits.Volts);
task.Timing.ConfigureSampleClock(
signalSource: "",
rate: rate,
sampleClockActiveEdge: SampleClockActiveEdge.Rising,
sampleQuantityMode: SampleQuantityMode.FiniteSamples,
samplesPerChannel: samplesPerChannel);
AnalogMultiChannelReader reader = new AnalogMultiChannelReader(task.Stream);
double[,] data = reader.ReadMultiSample(samplesPerChannel);
int channelCount = data.GetLength(0);
for (int ch = 0; ch < channelCount; ch++)
{
double min = double.MaxValue;
double max = double.MinValue;
double sum = 0.0;
for (int i = 0; i < samplesPerChannel; i++)
{
double v = data[ch, i];
if (v < min) min = v;
if (v > max) max = v;
sum += v;
}
Console.WriteLine(
$" ch{ch}: {samplesPerChannel:N0} samples " +
$"min {min,+9:F4} V max {max,+9:F4} V mean {sum / samplesPerChannel,+9:F4} V");
}
}
Console.WriteLine();
}
}