Форум: Техническая поддержка

Тема: При синхронном ввода теряется связь с E502

Вы не вошли.

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

01.12.2017 10:56:04
#1

Участник
Откуда: МО
Здесь с 01.12.2017
Сообщений: 24

При синхронном ввода теряется связь с E502

Возникла проблема с получением данных с устройства E502.

Схема очень простая, на 1 канал подключён источник постоянного тока, подаётся напряжение от 0 до 8 вольт (можно менять), второй канал заземлён, остальные не используются (могу выложить чертёж схемы). Оба канала (1 и 2) запущены в режиме с общей землёй, запущен синхронный ввод, частота 2000000 (=2x10^6, 2 МГц).

Чтение происходит в бесконечном цикле, после каждого чтения выводим первый и последний отсчёт. Данные выдаются правильные, при изменении напряжения реакция мгновенная. Но есть одна проблема - периодически теряется связь. Функция X502_Recv возвращает ошибку -9, после чего дальнейшие попытки чтения оказываются бесполезными (постоянно летит ошибка -9), помогает только закрыть соединение и открыть его по новой. Тогда опять некоторое время будет успешное чтение, но потом ошибка появляется снова. В среднем время до потери связи составляет 20 секунд (даже 15).

Как бороться с этой проблемой?

Ниже код, так как скорее всего его всё равно нужно показать (может там явный мой косяк). Для укорочения кода убраны проверки кодов ошибок, а также описания временных массивов-буферов, также убраны описания классов, отвечающих за хранение данных. Если нужно ещё что-то - выложу.

Код чтения данных:

    uint32_t next_channel = ~uint32_t(0);
    int32_t err0 = X502_GetNextExpectedLchNum(hnd, &next_channel);
    memset(buffer, 0, buffer_size*sizeof(buffer[0]));
    int32_t err = X502_Recv(hnd, buffer, buffer_size, 1000);
    if (err >= 0)
    {
        adc_data_size = adc_data_size_basic;
        din_data_size = din_data_size_basic;
        int32_t err2 = X502_ProcessData(hnd, buffer, buffer_size, X502_PROC_FLAGS_VOLT, adc_data, &adc_data_size, din_data, &din_data_size);
    }
    else
    {
        static int counter = 0;
        ++counter;
        qDebug() << "error X502_Recv : " << err << " " << X502_GetErrorString(err) << counter;
        return -1;
    }

Код установления соединения:

    int err_code = E502_OpenUsb(hnd, serial_);
    if (err_code == X502_ERR_OK)
    {
        // Сконфигурировать устройство
        int conf_error;
        conf_error = X502_SetLChannelCount(hnd, n_channels);
        for (int i = 0; i < n_channels; ++i)
        {
            conf_error = X502_SetLChannel(hnd, i, channels[i], X502_LCH_MODE_COMM, X502_ADC_RANGE_10, 0);
        }
        double freq = 2000000.;
        conf_error = X502_SetAdcFreq(hnd, &freq, 0);
        conf_error = X502_Configure(hnd, 0);
    }
01.12.2017 11:18:37
#2

Инженер-электронщик
Откуда: "Л Кард"
Здесь с 21.04.2014
Сообщений: 4,597

Re: При синхронном ввода теряется связь с E502

Здравствуйте.
При испытании под lqmeasstudio  связь устойчива (при том же подключении, тех же настройках и физических условиях)?

01.12.2017 11:21:42
#3

Участник
Откуда: МО
Здесь с 01.12.2017
Сообщений: 24

Re: При синхронном ввода теряется связь с E502

Гарманов Александр пишет:

Здравствуйте.
При испытании под lqmeasstudio  связь устойчива (при том же подключении, тех же настройках и физических условиях)?

Да, lqmeasstudio ошибок не выдаёт, данные в ней верные, за месяц активной работы только 1 раз в lqm была ошибка чтения, думаю это была случайность (может что-то с питанием).

01.12.2017 12:26:01
#4

Сотрудник "Л Кард"
Здесь с 17.04.2014
Сообщений: 1,259

Re: При синхронном ввода теряется связь с E502

Описание как устанавливаются размеры всех буферов и их выделение/объявление хотелось бы посмотреть. И еще вопрос, как именно вызывается эта функция чтения данных во время работы (постоянно в каком-то потоке или как-то иначе).
Если в программе оставить только прием (убрать сохранение и прочие вспомогательные вещи), то ошибка все равно возникает?

01.12.2017 13:54:46
#5

Участник
Откуда: МО
Здесь с 01.12.2017
Сообщений: 24

Re: При синхронном ввода теряется связь с E502

Оставил только чтение, убрал вывод прочитанных данных и сохранение данных. Ошибка всё равно возникла.

Чтение происходит в отдельном потоке в бесконечном цикле вида:

lcardE502 dev("serial_number");
for(;;)
{
    dev.getBlock();
}

Код, в котором производится выделение буфферов, установка их размеров и прочие вспомогательные действия:

#include <QVector>

#include "e502api.h"
#include "l502api.h"

class lcardE502
{
private:
    t_x502_hnd     hnd       ;
    bool           hnd_opened;
    int            n_channels;
    QVector<int>   channels  ;

    const char* serial_;

public:
    uint32_t* buffer       ;
    uint32_t  buffer_size  ;
    double*   adc_data     ;
    uint32_t  adc_data_size;
    static const uint32_t  adc_data_size_basic = 2097152;  // 2*1024*1024
    uint32_t* din_data     ;
    uint32_t  din_data_size;
    static const uint32_t  din_data_size_basic = 2097152;  // 2*1024*1024

    void make_channels_array();

    int getBlock   (            );
    int openDevice (            );
    int closeDevice(            );

public:
    explicit lcardE502(const char* serial);

    virtual ~lcardE502();
};

lcardE502::lcardE502(const char* serial) : serial_(serial)
{
    // Готовим описатель модуля
    hnd_opened = false;
    hnd = X502_Create();

    // Выделяем память под буффера
    buffer_size = 2097152;
    buffer = new uint32_t[buffer_size];
    adc_data_size = adc_data_size_basic;
    adc_data = new double[adc_data_size];
    din_data_size = din_data_size_basic;
    din_data = new uint32_t[din_data_size];

    // Сгенерируем массив используемых каналов
    make_channels_array();
}

lcardE502::~lcardE502()
{
    closeDevice();
    X502_Free(hnd);

    delete[] buffer;
    delete[] adc_data;
    delete[] din_data;
}

int lcardE502::openDevice()
{
    // Открыть устройство
    int err_code = E502_OpenUsb(hnd, serial_);
    if (err_code == X502_ERR_OK)
    {
        // Сконфигурировать устройство
        int conf_error = X502_SetLChannelCount(hnd, n_channels);
        if (conf_error != X502_ERR_OK)
        {
            qDebug() << "error X502_SetLChannelCount : " << X502_GetErrorString(conf_error);
        }
        for (int i = 0; i < n_channels; ++i)
        {
            // Все каналы работают только в режиме с общей землёй
            conf_error = X502_SetLChannel(hnd, i, channels[i], X502_LCH_MODE_COMM, X502_ADC_RANGE_10, 0);
            if (conf_error != X502_ERR_OK)
            {
                qDebug() << "error X502_SetLChannel : " << X502_GetErrorString(conf_error);
                break;
            }
        }
        double freq = 2000000.;
        conf_error = X502_SetAdcFreq(hnd, &freq, 0);
        if (conf_error != X502_ERR_OK)
        {
            qDebug() << "error X502_SetAdcFreq : " << X502_GetErrorString(conf_error);
        }
        conf_error = X502_Configure(hnd, 0);
        if (conf_error != X502_ERR_OK)
        {
            qDebug() << "error X502_Configure : " << X502_GetErrorString(conf_error);
        }

        hnd_opened = true;
        qDebug() << "error X502_StreamsEnable : " << X502_GetErrorString(X502_StreamsEnable(hnd, X502_STREAM_ADC));
        qDebug() << "error X502_StreamsStart : " << X502_GetErrorString(X502_StreamsStart(hnd));
    }
    else
    {
        qDebug() << "Opening error : " << err_code << " " << X502_GetErrorString(err_code);
    }
    return err_code;
}

int lcardE502::closeDevice()
{
    int err_code = X502_Close(hnd);
    if (err_code == X502_ERR_OK)
    {
        hnd_opened = false;
    }
    else
    {
        qDebug() << "Closing error : " << err_code << " " << X502_GetErrorString(err_code);
    }
    return err_code;
}

void lcardE502::make_channels_array()
{
    channels.append(0);
    channels.append(1);
}

int lcardE502::getBlock()
{
    // Если не открыто соединение - открыть его
    if (!hnd_opened)
    {
        openDevice();
        usleep(1000000);
    }
    uint32_t next_channel = ~uint32_t(0);
    int32_t err0 = X502_GetNextExpectedLchNum(hnd, &next_channel);
    if (err0 != X502_ERR_OK)
    {
        qDebug() << X502_GetErrorString(err0);
        return -1;
    }
    memset(buffer, 0, buffer_size*sizeof(buffer[0]));
    int32_t err = X502_Recv(hnd, buffer, buffer_size, 1000);
    if (err >= 0)
    {
        adc_data_size = adc_data_size_basic;
        din_data_size = din_data_size_basic;
        int32_t err2 = X502_ProcessData(hnd, buffer, err, X502_PROC_FLAGS_VOLT, adc_data, &adc_data_size, din_data, &din_data_size);
        if (err2 != X502_ERR_OK)
        {
            qDebug() << "error X502_ProcessData : " << err2 << " " << X502_GetErrorString(err2);
            return -1;
        }
    }
    else
    {
        static int counter = 0;
        ++counter;
        qDebug() << "error X502_Recv : " << err << " " << X502_GetErrorString(err) << counter;
        closeDevice();
        hnd_opened = false;
        return -1;
    }

    return 0;
}
01.12.2017 18:36:03
#6

Сотрудник "Л Кард"
Здесь с 17.04.2014
Сообщений: 1,259

Re: При синхронном ввода теряется связь с E502

А штатный консольный пример у Вас при этом работает без ошибок?
Что-то пока не удалось воспроизвести Вашу ситуацию.
А какая у Вас ОС?
можете в принципе прислать урезанный полный проект, на котором могу проверить, будет ли у меня проявляться.

01.12.2017 18:56:00
#7

Сотрудник "Л Кард"
Здесь с 17.04.2014
Сообщений: 1,259

Re: При синхронном ввода теряется связь с E502

несколько непонятна необходимость usleep(1000000);, хотя влиять на данную ошибку не должно

04.12.2017 10:48:40
#8

Участник
Откуда: МО
Здесь с 01.12.2017
Сообщений: 24

Re: При синхронном ввода теряется связь с E502

Сделал отдельный проект, в котором в цикле выполняется чтение с модуля. Ссылка на архив: http://rgho.st/7cXhFvy5L (проект под Qt4). Но пока есть проблемка - стабильно идёт -140 ошибка (неверный номер канала в буффере), это скорее всего какой-то явный ляп в коде у меня (наверняка memset сделал неправильно), сейчас разбираюсь, думаю с ней справлюсь (код взят ровно тот, что я выкладывал сообщением выше).

Штатный консольный пример это какой? Я кажется несколько запутался в материалах, и проглядел его. Код lqmeasstudio пытался разобрать, но он довольно большой, поэтому его пока не осилил.

usleep(1000000) в принципе не нужен, но если его убрать, то мы задёргаем модуль, так как цикл будет лететь с дикой скоростью. Однако скорее всего беды не будет - задержку сделает модуль, так как он физически не сможет выдавать столько отсчётов в секунду, и задержку сделает X502_Recv, в итоге мы будет также получать 2 миллиона отсчётов в секунду. Так что эта команда тут скорее как стиль программирования, чтобы отдельные процессы не сожрали все ресурсы.

04.12.2017 10:56:56
#9

Участник
Откуда: МО
Здесь с 01.12.2017
Сообщений: 24

Re: При синхронном ввода теряется связь с E502

Исправленная ссылка на архив проекта: http://rgho.st/7rr8kchGP (ссылка в предыдущем сообщении потёрлась, что-то не то нажал на файлообменнике).

04.12.2017 11:33:56
#10

Участник
Откуда: МО
Здесь с 01.12.2017
Сообщений: 24

Re: При синхронном ввода теряется связь с E502

Причину -140 нашёл - неиницилизированная переменная (n_channels). Добавил n_channels - channels.size();, теперь -140 нету.

Исправленный проект: http://rgho.st/6YlJjlFH9 .

Запустил приложение, пока разрыва связи нету. Значит проблема всё-таки в нашей архитектуре (скорее всего).

Итог на текущий момент - в чистом приложении ошибки не возникает. Буду пробовать получить ошибку в многопоточном приложении, если удастся - напишу снова (с приложением проекта). Тему можно пока закрыть (или оставить, на случай если удастся это ошибку повторить в чистом многопоточном приложении, но могу и другую тему создать).

Спасибо.

PS. Ранее не ответил на вопрос про ОС, ОС linux debian .

04.12.2017 11:43:10
#11

Участник
Откуда: МО
Здесь с 01.12.2017
Сообщений: 24

Re: При синхронном ввода теряется связь с E502

Общий вопрос - от чего вообще может произойти ошибка -9 ? (ошибка чтения данных синхронного ввода)

04.12.2017 11:59:37
#12

Участник
Откуда: МО
Здесь с 01.12.2017
Сообщений: 24

Re: При синхронном ввода теряется связь с E502

Опять накосячил со ссылками, вот верная ссылка на последнюю версию проекта : http://rgho.st/8CmqXpyzj .

04.12.2017 13:29:34
#13

Сотрудник "Л Кард"
Здесь с 17.04.2014
Сообщений: 1,259

Re: При синхронном ввода теряется связь с E502

Под штатным примером имелся ввиду этот http://www.lcard.ru/download/examples/l … m_read.zip, может собираться и gcc.
Хотя если Вы получили сбор без ошибки, то может он уже не так актуален.
Recv() действительно задержит работу цикла до получения данных, так что в принципе usleep не должен быть обязательным.

Само возникновение ошибки несколько странно. Вообще эта ошибка при работе по USB возникает, если какой-то запрос по USB завершился с ошибкой. При этом, если бы были проблемы с подключением по USB, то по идее проблемы должны были возникнуть и в lqmeasstudio и в простом примере.
Честно говоря, пока не совсем понимаю, каким образом можно привести к этой ошибке из приложения (если не рассматривать вариант порчи памяти или какой-то хитрый вариант некорректного использования функций библиотеки...).
По видимому только добавляя части того проекта и смотря, что именно приведет к этой ошибке, можно понять, с чем она связана

05.12.2017 13:23:41
#14

Участник
Откуда: МО
Здесь с 01.12.2017
Сообщений: 24

Re: При синхронном ввода теряется связь с E502

Открылись новые обстоятельства.

Ошибка возникает лишь в случае, если проект собран с флагом -pg, исправленный проект : http://rgho.st/8z7GSRdGN , собрать необходимо в debug-режиме, после этого запускать (можно как под отладчиком, так и без, ошибка воспроизводится).

Если убрать флаг -pg, ошибок не будет (по крайней мере я не дождался). Чтобы убрать этот флаг, нужно в pro-файле убрать две строки, которые его подключают (для компилятора и для линковщика, там их сразу видно).

Проект по ссылке это ранее выложенный проект (то есть чистый, без посторонних действий), но собранный с флагом -pg. Судя по всему, ошибка как-то связана именно с ним.

05.12.2017 19:02:47
#15

Сотрудник "Л Кард"
Здесь с 17.04.2014
Сообщений: 1,259

Re: При синхронном ввода теряется связь с E502

Вроде нашел проблему. При сборке с -pg функция ожидания событий от USB возвращает иногда LIBUSB_ERROR_INTERRUPTED (видимо для профилирования при включении этого флага приложению посылаются какие-то сигналы, прерывающие ожидание в функции). Обработал этот код функции корректно и закинул на сборку (версия 1.1.12), так что можете попробовать как собирется обновление

06.12.2017 09:52:31
#16

Участник
Откуда: МО
Здесь с 01.12.2017
Сообщений: 24

Re: При синхронном ввода теряется связь с E502

Сейчас проверяю исправление, уже возникла проблема - символические ссылки libe502api.so и аналогичные указывают на старую версию библиотеки. Либо make install их не обновил, либо в сборке они неверно устанавливаются.

06.12.2017 10:05:43
#17

Участник
Откуда: МО
Здесь с 01.12.2017
Сообщений: 24

Re: При синхронном ввода теряется связь с E502

Вопрос с символическими ссылками закрыл (просто сам их пересоздал). Тестирую изменения.

06.12.2017 10:09:16
#18

Участник
Откуда: МО
Здесь с 01.12.2017
Сообщений: 24

Re: При синхронном ввода теряется связь с E502

За 5 минут работы ни одного разрыва не было. Данные принимаются корректно (факт получения и их равенство реальному сигналу, измеренному вольтметром). Думаю, ошибка исправлена. Спасибо за помощь.  smile

06.12.2017 12:40:18
#19

Сотрудник "Л Кард"
Здесь с 17.04.2014
Сообщений: 1,259

Re: При синхронном ввода теряется связь с E502

Отлично! Если что обращайтесь. Удачи!

Контакты

Адрес: 117105, Москва, Варшавское шоссе, д. 5, корп. 4, стр. 2

Многоканальный телефон:
+7 (495) 785-95-25
Факс: +7 (495) 785-95-14

Отдел продаж: sale@lcard.ru
Техническая поддержка: support@lcard.ru

Время работы: с 9-00 до 19-00 мск