Российский производитель и разработчик сертифицированного измерительного оборудования с 1987 года


Задержка при получении измерений АЦП

Вы не вошли.

 Поиск | Регистрация | Вход 

11.07.2025 15:39:28
#1

Участник
Здесь с 11.07.2025
Сообщений: 1

Задержка при получении измерений АЦП

Приветствую!

Разрабатываю модуль на C для получения измерений с аналоговых входов L-502. Столкнулся со следующей проблемой: метод X502_Recv всегда выполняется около 4х секунд, вне зависимости от частоты АЦП и количества запрашиваемых отсчетов. Если передать таймаут меньше 4х секунд, то стабильно ничего не возвращается.
В целях дебага написал простой код, который с интервалом в 1 секунду вызывает X502_GetRecvReadyCount, и также получил весьма странные результаты.

Код:

#include <locale.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>

#include <x502api.h>
#include <l502api.h>


uint32_t calc_delay(struct timeval *start, struct timeval *stop) {
    return (stop->tv_sec - start->tv_sec) * 1000000 + stop->tv_usec - start->tv_usec;
}


int main(int argc, char** argv) {
    setlocale(LC_NUMERIC, "");
    struct timeval start, stop;
    uint64_t delta_us;
    int32_t err;

    // Получаем версию библиотеки
    uint32_t ver = X502_GetLibraryVersion();
    printf("Library version: %d.%d.%d\n", (ver >> 24)&0xFF, (ver>>16)&0xFF, (ver>>8)&0xFF);

    // Получаем количество подключенных устройств по интерфейсу PCI
    uint32_t devcnt = 0;
    L502_GetDevRecordsList(NULL, 0, 0, &devcnt);
    printf("Found %d PCI device(s)\n", devcnt);

    // Выводим список найденных устройств
    if (devcnt == 0) {
        return 0;
    }

    // Выделяем память для массива для сохранения найденного количества записей
    t_x502_devrec *devices = NULL;
    devices = malloc(devcnt * sizeof(t_x502_devrec));

    // Получаем записи о модулях L502
    L502_GetDevRecordsList(&devices[0], devcnt, 0, NULL);
    for (int i=0; i<devcnt; ++i) {
        printf("Device %d: %s (SN: %s, Flags: %x)\n", i, devices[i].devname, devices[i].serial, devices[i].flags);
    }

    // Устанавливаем соединение
    t_x502_hnd dev_hnd = X502_Create();
    gettimeofday(&start, NULL);
    err = X502_OpenByDevRecord(dev_hnd, &devices[0]);
    gettimeofday(&stop, NULL);
    printf("X502_OpenByDevRecord took %'d us\n", calc_delay(&start, &stop));

    if (err != X502_ERR_OK) {
        fprintf(stderr, "Error connecting to device: %s\n", X502_GetErrorString(err));
        return 1;
    }

    printf("Successfully connected to device!\n");

    // Освобождение ресурсов действительных записей из списка
    X502_FreeDevRecordList(devices, devcnt);

    // Очистка памяти самого массива
    free(devices);

    // Устанавливаем параметры логической таблицы АЦП
    err = X502_SetLChannelCount(dev_hnd, 1);
    if (err != X502_ERR_OK) {
        fprintf(stderr, "Error configuring ADC inputs: %s\n", X502_GetErrorString(err));
        return 1;
    }

    err = X502_SetLChannel(dev_hnd, 0, 0, X502_LCH_MODE_COMM, X502_ADC_RANGE_10, 0);
    if (err != X502_ERR_OK) {
        fprintf(stderr, "Error configuring ADC inputs: %s\n", X502_GetErrorString(err));
        return 1;
    }

    err = X502_SetMode(dev_hnd, X502_MODE_FPGA);
    if (err != X502_ERR_OK) {
        fprintf(stderr, "Error setting mode: %s\n", X502_GetErrorString(err));
        return 1;
    }

    // Устанавливаем частоту АЦП
    double f_adc = 2000.0;
    err = X502_SetAdcFreq(dev_hnd, &f_adc, NULL);
    if (err != X502_ERR_OK) {
        fprintf(stderr, "Error setting ADC frequency: %s\n", X502_GetErrorString(err));
        return 1;
    }

    // Записываем настройки
    err = X502_Configure(dev_hnd, 0);
    if (err != X502_ERR_OK) {
        fprintf(stderr, "Error configuring device: %s\n", X502_GetErrorString(err));
        return 1;
    }

    // Разрешаем синхронные потоки
    int streams = X502_STREAM_ADC;
    err = X502_StreamsEnable(dev_hnd, streams);
    if (err != X502_ERR_OK) {
        fprintf(stderr, "Error configuring input streams: %s\n", X502_GetErrorString(err));
        return 1;
    }

    // Начинаем чтение данных
    gettimeofday(&start, NULL);
    err = X502_StreamsStart(dev_hnd);
    gettimeofday(&stop, NULL);
    printf("X502_StreamsStart took %'d us\n", calc_delay(&start, &stop));
    if (err != X502_ERR_OK) {
        fprintf(stderr, "Error during startup: %s\n", X502_GetErrorString(err));
        return 1;
    }

    printf("Measurement started\n");

    uint32_t rdy_cnt = 0;
    for (int i=0; i < 10; ++i) {

        err = X502_GetRecvReadyCount(dev_hnd, &rdy_cnt);
        if (err != X502_ERR_OK) {
            fprintf(stderr, "Error during GetRecvReadyCount: %s\n", X502_GetErrorString(err));
            return 1;
        }
        printf("ReadyCount: %d\n", rdy_cnt);
        sleep(1);
    }

    gettimeofday(&start, NULL);
    err = X502_StreamsStop(dev_hnd);
    gettimeofday(&stop, NULL);
    printf("X502_StreamsStop took %'d us\n", calc_delay(&start, &stop));
    if (err != X502_ERR_OK) {
        fprintf(stderr, "Error stopping measurement: %s\n", X502_GetErrorString(err));
        return 1;
    }

    gettimeofday(&start, NULL);
    err = X502_Close(dev_hnd);
    if (err != X502_ERR_OK) {
        fprintf(stderr, "Error closing connection: %s\n", X502_GetErrorString(err));
    }
    gettimeofday(&stop, NULL);
    printf("X502_Close took %'d us\n", calc_delay(&start, &stop));

    X502_Free(dev_hnd);

    return 0;
}

Возвращает этот код следующее:

Library version: 1.1.34
Found 1 PCI device(s)
Device 0: L502 (SN: , Flags: 800400)
X502_OpenByDevRecord took 5105046 us
Successfully connected to device!
X502_StreamsStart took 1332647 us
Measurement started
ReadyCount: 0
ReadyCount: 0
ReadyCount: 0
ReadyCount: 0
ReadyCount: 17408
ReadyCount: 17408
ReadyCount: 17408
ReadyCount: 17408
ReadyCount: 17408
ReadyCount: 17408
X502_StreamsStop took 26249431 us
X502_Close took 26250668 us

Значение 17408 понятно: столько измерений будет выполнено за примерно 4 секунды при 2000Гц. Тот факт, что количество отсчетов далее не меняется, можно объяснить переполнением буфера. Но почему в течение первых 4х секунд буфер пуст, я так и не смог понять.
Попытки установить вручную шаг генерации прерываний при помощи X502_SetStreamStep ни к чему позитивному не привели.
Подскажите пожалуйста, в чем может быть причина такого поведения и куда еще можно покопать?