NI Counter Read Task
Learn how to acquire counter data from NI devices with Synnax.
For task lifecycle management, see the Task Basics page.
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
- Sample rates -> All channels in a task sample at the same rate. Create separate tasks for different rates.
- One task per module -> Only one running task can claim a module at a time.
- Stream rate optimization -> For low-rate tasks (< 50 Hz), set the stream rate to the sample rate. For high-rate tasks, keep stream the rate < 50 Hz for better performance.
- Port validation -> Counter ports cannot be duplicated within the same task.
How-To
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="Counter Read Task",
sample_rate=sy.Rate.HZ * 100,
stream_rate=sy.Rate.HZ * 25,
data_saving=True,
channels=[
ni.CIFrequencyChan(
channel=frequency_ch.key,
device=counter_dev.key,
port=0,
min_val=1,
max_val=10000,
units="Hz",
edge="Rising",
meas_method="DynamicAvg",
),
ni.CIEdgeCountChan(
channel=edge_count_ch.key,
device=counter_dev.key,
port=1,
active_edge="Rising",
count_direction="CountUp",
initial_count=0,
),
ni.CIPositionAngularChan(
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_enable=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="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_enable = True
task.config.channels[2].terminalA = "PFI7"
task.config.channels[2].terminalB = "PFI8"
task.config.channels[2].terminalZ = "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({ name: "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: "Counter Read Task",
type: "ni_counter_read",
config: JSON.stringify({
sample_rate: 100,
stream_rate: 25,
data_saving: true,
channels: [
{
type: "ci_frequency",
channel: frequencyCh.key,
device: counterDev.key,
port: 0,
min_val: 1,
max_val: 10000,
units: "Hz",
edge: "Rising",
meas_method: "DynamicAvg",
},
{
type: "ci_edge_count",
channel: edgeCountCh.key,
device: counterDev.key,
port: 1,
active_edge: "Rising",
count_direction: "CountUp",
initial_count: 0,
},
{
type: "ci_position_angular",
channel: angularPosCh.key,
device: counterDev.key,
port: 2,
units: "Degrees",
decoding_type: "X4",
pulses_per_rev: 1024,
initial_angle: 0.0,
z_index_enable: false,
},
],
}),
});
// Start task
await task.executeCommandSync("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.executeCommandSync("stop");
await streamer.close(); Edit task configuration
// Retrieve existing task
const task = await client.tasks.retrieve({ name: "Counter Read Task" });
// Parse and update configuration
const config = JSON.parse(task.config);
// Update task-level configuration
config.auto_start = true;
config.stream_rate = 50;
// Update frequency channel configuration
config.channels[0].min_val = 10;
config.channels[0].max_val = 5000;
config.channels[0].meas_method = "LowFreq1Ctr";
config.channels[0].terminal = "PFI0";
// Update edge count channel configuration
config.channels[1].active_edge = "Falling";
config.channels[1].initial_count = 100;
config.channels[1].terminal = "PFI1";
// Update angular position channel configuration
config.channels[2].pulses_per_rev = 2048;
config.channels[2].initial_angle = 90.0;
config.channels[2].z_index_enable = true;
config.channels[2].terminalA = "PFI7";
config.channels[2].terminalB = "PFI8";
config.channels[2].terminalZ = "PFI9";
// Apply changes
await client.tasks.create({
key: task.key,
name: task.name,
type: task.type,
config: JSON.stringify(config),
});