NI Counter Read Task
Learn how to acquire counter data from NI devices with Synnax.
For the task lifecycle, see Task Basics.
Task Configuration Reference
Channel Types Reference
Frequency (ci_frequency)
ci_frequency)Measures the frequency of digital pulses.
Edge Count (ci_edge_count)
ci_edge_count)Counts rising or falling edges on a digital signal.
Period (ci_period)
ci_period)Measures the time between edges of a periodic signal.
Pulse Width (ci_pulse_width)
ci_pulse_width)Measures the width of pulses in a digital signal.
Semi Period (ci_semi_period)
ci_semi_period)Measures the half-period of a periodic signal.
Two Edge Separation (ci_two_edge_sep)
ci_two_edge_sep)Measures the time between two different edges of a signal.
Velocity Linear (ci_velocity_linear)
ci_velocity_linear)Measures linear velocity using a quadrature encoder.
Velocity Angular (ci_velocity_angular)
ci_velocity_angular)Measures angular velocity (rotational speed) using a quadrature encoder.
Position Linear (ci_position_linear)
ci_position_linear)Tracks linear position using a quadrature encoder.
Position Angular (ci_position_angular)
ci_position_angular)Tracks angular position (rotation angle) using a quadrature encoder.
Duty Cycle (ci_duty_cycle)
ci_duty_cycle)Measures the duty cycle of a periodic signal.
Important Rules
- One task per module -> Only one running task can claim a module at a time.
- Unique ports -> A counter port can appear only once in a task.
- Stream rate -> For sample rates under 50 Hz, set the stream rate equal to the sample rate. Above that, keep the stream rate under 50 Hz.
How-To
Console
Python
TypeScript
Configure and run task
import synnax as sy
from synnax import ni
client = sy.Synnax()
# Retrieve device
counter_dev = client.devices.retrieve(name="Mod1_Counter")
# Create index channel
ctr_time = client.channels.create(
name="ctr_time",
is_index=True,
data_type=sy.DataType.TIMESTAMP,
retrieve_if_name_exists=True,
)
# Create data channels
frequency_ch = client.channels.create(
name="frequency",
index=ctr_time.key,
data_type=sy.DataType.FLOAT32,
retrieve_if_name_exists=True,
)
edge_count_ch = client.channels.create(
name="edge_count",
index=ctr_time.key,
data_type=sy.DataType.UINT32,
retrieve_if_name_exists=True,
)
angular_pos_ch = client.channels.create(
name="angular_position",
index=ctr_time.key,
data_type=sy.DataType.FLOAT32,
retrieve_if_name_exists=True,
)
# Create and configure task
task = ni.CounterReadTask(
name="NI Counter Read Task",
sample_rate=sy.Rate.HZ * 100,
stream_rate=sy.Rate.HZ * 25,
channels=[
ni.CIFrequencyChannel(
channel=frequency_ch.key,
device=counter_dev.key,
port=0,
min_val=1,
max_val=10000,
units="Hz",
edge="Rising",
meas_method="DynamicAvg",
),
ni.CIEdgeCountChannel(
channel=edge_count_ch.key,
device=counter_dev.key,
port=1,
active_edge="Rising",
count_direction="CountUp",
initial_count=0,
),
ni.CIPositionAngularChannel(
channel=angular_pos_ch.key,
device=counter_dev.key,
port=2,
units="Degrees",
decoding_type="X4",
pulses_per_rev=1024,
initial_angle=0.0,
z_index_enabled=False,
),
],
)
client.tasks.configure(task)
# Start task and read data
with task.run():
with client.open_streamer(["frequency", "edge_count", "angular_position"]) as streamer:
for _ in range(10):
frame = streamer.read()
print(frame) Edit task configuration
# Retrieve existing task
task = client.tasks.retrieve(name="NI Counter Read Task")
task = ni.CounterReadTask(internal=task)
# Update task-level configuration
task.config.auto_start = True
task.config.stream_rate = int(sy.Rate.HZ * 50)
# Update frequency channel configuration
task.config.channels[0].min_val = 10
task.config.channels[0].max_val = 5000
task.config.channels[0].meas_method = "LowFreq1Ctr"
task.config.channels[0].terminal = "PFI0"
# Update edge count channel configuration
task.config.channels[1].active_edge = "Falling"
task.config.channels[1].initial_count = 100
task.config.channels[1].terminal = "PFI1"
# Update angular position channel configuration
task.config.channels[2].pulses_per_rev = 2048
task.config.channels[2].initial_angle = 90.0
task.config.channels[2].z_index_enabled = True
task.config.channels[2].terminal_a = "PFI7"
task.config.channels[2].terminal_b = "PFI8"
task.config.channels[2].terminal_z = "PFI9"
# Apply changes
client.tasks.configure(task) Configure and run task
import { Synnax } from "@synnaxlabs/client";
const client = new Synnax();
// Retrieve device
const [counterDev] = await client.devices.retrieve({ names: ["Mod1_Counter"] });
// Create index channel
const ctrTime = await client.channels.create(
{
name: "ctr_time",
isIndex: true,
dataType: "timestamp",
},
{ retrieveIfNameExists: true },
);
// Create data channels
const frequencyCh = await client.channels.create(
{
name: "frequency",
index: ctrTime.key,
dataType: "float32",
},
{ retrieveIfNameExists: true },
);
const edgeCountCh = await client.channels.create(
{
name: "edge_count",
index: ctrTime.key,
dataType: "uint32",
},
{ retrieveIfNameExists: true },
);
const angularPosCh = await client.channels.create(
{
name: "angular_position",
index: ctrTime.key,
dataType: "float32",
},
{ retrieveIfNameExists: true },
);
// Create and configure task
const task = await client.tasks.create({
name: "NI Counter Read Task",
rack: counterDev.rack,
type: "ni_counter_read",
config: {
sampleRate: 100,
streamRate: 25,
channels: [
{
type: "ci_frequency",
channel: frequencyCh.key,
device: counterDev.key,
port: 0,
minVal: 1,
maxVal: 10000,
units: "Hz",
edge: "Rising",
measMethod: "DynamicAvg",
},
{
type: "ci_edge_count",
channel: edgeCountCh.key,
device: counterDev.key,
port: 1,
activeEdge: "Rising",
countDirection: "CountUp",
initialCount: 0,
},
{
type: "ci_position_angular",
channel: angularPosCh.key,
device: counterDev.key,
port: 2,
units: "Degrees",
decodingType: "X4",
pulsesPerRev: 1024,
initialAngle: 0.0,
zIndexEnabled: false,
},
],
},
});
// Start task
await task.start();
// Read data
const streamer = await client.openStreamer([
"frequency",
"edge_count",
"angular_position",
]);
for (let i = 0; i < 10; i++) {
const frame = await streamer.read();
console.log(frame);
}
// Stop task
await task.stop();
await streamer.close(); Edit task configuration
import { ni } from "@synnaxlabs/client";
// Retrieve existing task
const task = await client.tasks.retrieve({ name: "NI Counter Read Task" });
// Parse and update configuration
const config = ni.counterReadConfigZ.parse(task.config);
// Update task-level configuration
config.autoStart = true;
config.streamRate = 50;
// Update frequency channel configuration
const frequency = config.channels[0] as ni.CIFrequencyChannel;
frequency.minVal = 10;
frequency.maxVal = 5000;
frequency.measMethod = "LowFreq1Ctr";
frequency.terminal = "PFI0";
// Update edge count channel configuration
const edgeCount = config.channels[1] as ni.CIEdgeCountChannel;
edgeCount.activeEdge = "Falling";
edgeCount.initialCount = 100;
edgeCount.terminal = "PFI1";
// Update angular position channel configuration
const angularPosition = config.channels[2] as ni.CIPositionAngularChannel;
angularPosition.pulsesPerRev = 2048;
angularPosition.initialAngle = 90.0;
angularPosition.zIndexEnabled = true;
angularPosition.terminalA = "PFI7";
angularPosition.terminalB = "PFI8";
angularPosition.terminalZ = "PFI9";
// Apply changes
await client.tasks.create({
key: task.key,
rack: task.rack,
name: task.name,
type: task.type,
config,
});