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

E20-10 (B). При чтении АЦП в синхр. режиме ReadData возвращает false

Вы не вошли.

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

Ольга
12.05.2015 14:22:19
#1

Гость

E20-10 (B). При чтении АЦП в синхр. режиме ReadData возвращает false

Добрый день!

Какие могут причины того, что ReadData не может прочитать данные АЦП за time out?
(Функции для работы с цифровыми линиями работают)

- Модуль E20-10 (Rev.'B')
- Используется QT creator с компилятором MSVC 2013
- Настройки АЦП аналогичны примеру E20-10\Examples\MicroSoft Visual C++ 6.0 (за исключением того, что IoReq.Overlapped = 0)
- Сам проект  Examples\MicroSoft Visual C++\ReadData 6.0 работает

12.05.2015 14:50:13
#2

Сотрудник "Л Кард"
Здесь с 18.04.2014
Сообщений: 810

Re: E20-10 (B). При чтении АЦП в синхр. режиме ReadData возвращает false

Если выключили overlapped, то надо менять всю логику сбора (убрать двойную буферизацию, не делать два запроса в начале, исключить WaitFor... и GetOverlappedResult - короче говоря, просто ReadData в цикле). Однако использовать двойную буферизацию все-таки рекомендуется, тем более что у Вас самый быстрый модуль.
Советую еще вот эту статью.
P.S. На самом деле внутри lusbapi все равно overlapped i/o, просто в этом случае он делается внутри незаметно для вызывающей программы  (ReadFile - WaitForSingleObject - GetOverlappedResult) и не дает никакого выигрыша (если не использовать потоки).

Ольга
12.05.2015 14:59:17
#3

Гость

Re: E20-10 (B). При чтении АЦП в синхр. режиме ReadData возвращает false

Спасибо за быстрый ответ!
Да, двойную буферизацию убрала - пока просто хотелось бы один раз получить данные (поэтому, чтобы максимально упростить код, использую синхронный режим)

Примерный код (не срабатывает только m_pModule->ReadData(&IoReq))

m_dataStep = 256 * 1024
atdRate = 5000
kadrDelay = 0

    // получим текущие параметры работы АЦП
    if(!m_pModule->GET_ADC_PARS(&m_atdParams)){
        m_readError = SET_PARAMS_ERROR;
    }

    // разрешим автоматическую корректировку данных на уровне модуля
    m_atdParams.IsAdcCorrectionEnabled = FALSE;
    // при наличии перегрузки код отсчёта с АЦП ограничивается значениями -8192 или 8191
    m_atdParams.OverloadMode = CLIPPING_OVERLOAD_E2010;

    // внутренний старт сбора с АЦП
    m_atdParams.SynchroPars.StartSource = INT_ADC_START_E2010;
    // внутренние тактовые импульсы АЦП
    m_atdParams.SynchroPars.SynhroSource = INT_ADC_CLOCK_E2010;
    // задержка начала сбора данных в кадрах отсчётов
    m_atdParams.SynchroPars.StartDelay = 0x0;
    // останов сбора данных через заданное кол-во кадров отсчётов
    m_atdParams.SynchroPars.StopAfterNKadrs = 0x0;
    // тип аналоговой синхронизации
    m_atdParams.SynchroPars.SynchroAdMode = NO_ANALOG_SYNCHRO_E2010;
    // канал аналоговой синхронизации
    m_atdParams.SynchroPars.SynchroAdChannel = 0;
    // порог аналоговой синхронизации в кодах АЦП
    m_atdParams.SynchroPars.SynchroAdPorog = 0;
    // маркирование начала блока данных (удобно, например, при аналоговой синхронизации ввода по уровню)
    m_atdParams.SynchroPars.IsBlockDataMarkerEnabled = 0;

    // кол-во активных каналов
    m_atdParams.ChannelsQuantity = ADC_CHANNELS_QUANTITY_E2010;

    // формируем управляющую таблицу
    for(int i = 0; i < m_atdParams.ChannelsQuantity; i++)
    {
        m_atdParams.ControlTable[i] = (WORD)(i);
    }

    // частота работы АЦП в кГц
    m_atdParams.AdcRate = atdRate;
    // межкадровая задержка в мс
    m_atdParams.InterKadrDelay = kadrDelay;

    // сконфигурируем входные каналы
    for(int i = 0; i < ADC_CHANNELS_QUANTITY_E2010; i++)
    {
        // входной диапазоне 3В
        m_atdParams.InputRange[i] = ADC_INPUT_RANGE_3000mV_E2010;
        // источник входа - сигнал
        m_atdParams.InputSwitch[i] = ADC_INPUT_SIGNAL_E2010;
    }

    // выделим память под буфер
    m_atdBuffer = new SHORT[m_dataStep];

    if(!m_pModule->STOP_ADC())
    {
        m_readError = STOP_ATD_ERROR;
    }

    if (!m_pModule->SET_ADC_PARS(&m_atdParams))
    {
        m_readError = SET_PARAMS_ERROR;
    }

    // запустим АЦП
    if(!m_pModule->START_ADC())
    {
        m_readError = START_ATD_ERROR;
    }

    IO_REQUEST_LUSBAPI IoReq;

    IoReq.Buffer = m_atdBuffer;
    IoReq.NumberOfWordsToPass = m_dataStep;
    IoReq.NumberOfWordsPassed = 0;
    IoReq.Overlapped = 0;
    IoReq.TimeOut = (DWORD)(m_dataStep/m_atdParams.KadrRate + 1000);


    if(!m_pModule->ReadData(&IoReq))
    {
        m_readError = READ_DATA_ERROR;
        return;
    }
12.05.2015 15:54:06
#4

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

Re: E20-10 (B). При чтении АЦП в синхр. режиме ReadData возвращает false

Думаю было бы полезно для большей информации посмотреть, какой номер ошибки возвращает GetLastErrorInfo() после возникновения ошибки.

Также на всякий случай все же уточню, так как если исходить из этого куска кода, то при остальных ошибках нет выхода, а продолжает выполняться программа, всегда доходя до ReadData, не сохраняя коды предыдущих ошибок - точно ли нет ошибок до этого?

Ольга
12.05.2015 16:22:52
#5

Гость

Re: E20-10 (B). При чтении АЦП в синхр. режиме ReadData возвращает false

Спасибо!

- Да, ошибок до вызова ReadData не возникает (не выложила весь код, return только в одном месте, так как это отдельная функция)

- После вызова ReadData GetLastErrorInfo() возвращает код ошибки 422 (проверено, что перед вызовом возвращался код 100 (100 возвращается уже сразу после получения ILE2010)). В документации к GetLastErrorInfo() сказано, что "Данная интерфейсная функция не выполняет классификацию ошибок для интерфейсной функции ReadData(). Т.к. эта функция фактически является слепком со стандартной Windows API функций ReadFile(), то для выявления ошибок следует пользоваться классификацией ошибок, присущей системе Windows."

Тут (https://msdn.microsoft.com/en-us/librar … s.85).aspx) ошибки 422 нет, возможно я смотрю не в том списке?

12.05.2015 17:08:29
#6

Сотрудник "Л Кард"
Здесь с 18.04.2014
Сообщений: 810

Re: E20-10 (B). При чтении АЦП в синхр. режиме ReadData возвращает false

Ольга пишет:

После вызова ReadData GetLastErrorInfo() возвращает код ошибки 422

Ольга пишет:

Данная интерфейсная функция не выполняет классификацию ошибок для интерфейсной функции ReadData(). Т.к. эта функция фактически является слепком со стандартной Windows API функций ReadFile(), то для выявления ошибок следует пользоваться классификацией ошибок, присущей системе Windows."

Если так написано, то это для актуальной версии неправильно, см. исходные тексты lusbapi.
422 - это действительно таймаут:
#define    E2010_BASE_ERROR_ID (400)
#define    E2010_ERROR_ID_22 (E2010_BASE_ERROR_ID + 22)
E2010_ERROR_ID_22,    "Таймаут ожидания ввода данных."
Собственно, эту строку и должна была вернуть функция GetLastErrorInfo.

А вот почему, я пока не понял. Пуск АЦП, говорите, точно успешно выполнился? Внешний запуск вроде бы не включен.

Величина таймаута рассчитывается странно (по-моему, для получения времени сбора надо было разделить еще на число каналов), но это в большую сторону ошибка, а потом еще +1000 (секунда).
Вообще-то бывают фокусы с большим размером запроса в зависимости от USB хост-контроллера на компьютере. 512 кБайт (SHORT[256*1024]) - это не так уж мало, а что если попробовать уменьшить буфер в 2, 4, 8 раз?

12.05.2015 17:15:37
#7

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

Re: E20-10 (B). При чтении АЦП в синхр. режиме ReadData возвращает false

1. Какая версия используемой библиотеки Lusbapi?
2. Более свежее руководство можно скачать здесь:
www.lcard.ru/download/e2010_programmers_guide.pdf
3. Код ошибки 422 означает "Таймаут ожидания ввода данных".
4. Могу выслать рабочий пример работы модуля в указанном режиме. Или присылайте свой проект.

Ольга
12.05.2015 17:23:08
#8

Гость

Re: E20-10 (B). При чтении АЦП в синхр. режиме ReadData возвращает false

1. lusbapi34 (но использую не dll, а статическую lib из папки DLL\Lib\MicroSoft)
2. Спасибо, сейчас почитаю, может смогу найти ошибку самостоятельно (использовала ранее версию 2008 года)

12.05.2015 17:33:44
#9

Сотрудник "Л Кард"
Здесь с 18.04.2014
Сообщений: 810

Re: E20-10 (B). При чтении АЦП в синхр. режиме ReadData возвращает false

Ольга пишет:

1. lusbapi34 (но использую не dll, а статическую lib из папки DLL\Lib\MicroSoft)

Вообще это не статическая, а dll-import lib. Чтобы линкер смог собрать .exe с нужными импортами. Так что .dll при запуске программы нужна.

Ольга
13.05.2015 11:40:27
#10

Гость

Re: E20-10 (B). При чтении АЦП в синхр. режиме ReadData возвращает false

Спасибо за ответы!

Ошибка была в том, что в начале не была вызвана LOAD_MODULE().

Контакты

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

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

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

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