Skip to content

USB device stops communicating below certain polling threshold #931

@slartz42

Description

@slartz42

Bug Report

When polling a USB device below a certain frequency, it simply stops communicating even though the driver and device buffer have not overflowed

Repro or Code Sample

import nidaqmx
from nidaqmx.stream_readers import AnalogMultiChannelReader
import numpy as np
import time

RATE = 1024.0
CHANNEL = "Dev2/ai0"  # adjust as needed
DURATION = 300
MAX_BUF = 1024
POLLING_FREQUENCY = 32

with nidaqmx.Task() as task:
    task.ai_channels.add_ai_voltage_chan(CHANNEL)
    task.timing.cfg_samp_clk_timing(
        rate=RATE,
        sample_mode=nidaqmx.constants.AcquisitionType.CONTINUOUS
    )
    reader = AnalogMultiChannelReader(task.in_stream)
    print(f"Rate: {task.timing.samp_clk_rate}")
    print(f"Driver buffer: {task.in_stream.input_buf_size}")
    print(f"Onboard buffer: {task.in_stream.input_onbrd_buf_size}")

    data = np.zeros((1, MAX_BUF))
    task.start()
    start = time.perf_counter()
    total_read = 0
    last_print = start
    stall_start = None

    while time.perf_counter() - start < DURATION:
        avail = task.in_stream.avail_samp_per_chan
        if avail > 0:
            n = min(avail, MAX_BUF)
            reader.read_many_sample(data[:, :n], number_of_samples_per_channel=n)
            total_read += n
            stall_start = None

        now = time.perf_counter()
        if now - last_print >= 2.0:
            elapsed = now - start
            hw = task.in_stream.total_samp_per_chan_acquired
            print(f"[{elapsed:6.1f}s] read={total_read}, hw={hw}, rate={total_read/elapsed:.1f} Hz, avail={avail}")
            last_print = now

        if avail == 0 and total_read > 100:
            if stall_start is None:
                stall_start = time.perf_counter()
            elif time.perf_counter() - stall_start > 2.0:
                hw = task.in_stream.total_samp_per_chan_acquired
                print(f"STALLING")

        time.sleep(1/POLLING_FREQUENCY)

    task.stop()
    elapsed = time.perf_counter() - start
    print(f"Program Complete")

Expected Behavior

The device should keep returning data as long as the buffers have not overflowed

Current Behavior

The device shows no data in avail_samp_per_chan after running for some time at polling rates ~32 hz or lower. This issue doesn't occur if I poll at ~100 Hz.

Possible Solution

I thought this might be a Windows issue with USB selective suspend, but I have this disabled. I have also replicated this issue on two different PCs with two different USB devices (6001 / 6003). This is either a Windows issue or an nidaqmx issue as I never had this problem in the past.

Context

Try to log data in Python with a polling interval of 16 - 32 Hz. I'm using avail_samp_per_chan to determine the size of my numpy array slice.

Your Environment

Processor Intel(R) Core(TM) i7-14700F (2.10 GHz)
Installed RAM 32.0 GB (31.8 GB usable)
System type 64-bit operating system, x64-based processor
Edition Windows 11 Home
Version 25H2
OS build 26200.7840
Experience Windows Feature Experience Pack 1000.26100.291.0
Python Version: 3.13.6 (also tested 3.14.0, same results)
nidaqmx: 1.4.1 (I tried up to three versions prior with no change)

AB#3758354

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions