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

Тема: e502: синхронный ввод/вывод

Вы не вошли.

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

18.10.2016 16:36:53
#26

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

Re: e502: синхронный ввод/вывод

а ведь точно -поставил частоту строго равной частоте фрейма и цифры стали правильными.. спасибо, буду пытать дальше

18.10.2016 16:44:43
#27

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

Re: e502: синхронный ввод/вывод

Не обязательно. Но надо либо учитывать это соотношение на приеме, либо делать прием с учетом того, что соотношение могут быть разными.
Суть в том, что Вы принимаете все общим потоком и в этом потоке перемешены данные от АЦП и от цифровых входов.

Если у Вас частота цифровых линий равна или в M раз больше частоты кадров, то Вы можете применить простой метод приема (как Вы делаете) - принять (N + M) отсчетов (где N - кол-во каналов в кадре), тогда вы знаете что в них N отсчетов АЦП и M цифровых линий и соответственно в ProcessData передать нужное в качестве adc_size -- N, а в качестве din_size -- M и соответственно обработать.


Если делать прием для общего случая, то при приема K слов, Вы не знаете сколько тут данных от АЦП, а сколько от DIN.  Если Вы вызываете ProcessData() с размерами 11 и 1, а в принятом массиве допустим 7 данных АЦП и 4 DIN, то соответственно он и вернет 7 в АЦП и 1 в DIN, а 3 DIN отбросит, т.к. нет место в выходном массиве для их сохранения.
Для общей обработки можно передать adc_size и din_size равными K (чтобы всегда было место для всех данных), а дальше уже по полученным на выходе adc_size и din_size судить, сколько было данных АЦП, а сколько данных цифровых линий. При этом разбивку данных АЦП на кадры нужно делать вторым этапам (т.е. сохранять некую очередь отсчетов АЦП, которая действительна между ProcessData(), на один кадр (или больше), добавлять в конец данные из ProcessData и когда этот кадр заполнился уже вызвать функцию обработки)

Отредактировано Алексей L Card (18.10.2016 16:48:33)

18.10.2016 17:04:25
#28

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

Re: e502: синхронный ввод/вывод

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

23.08.2017 09:24:25
#29

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

Re: e502: синхронный ввод/вывод

Добрый день! Хочу продолжить обсуждение проблемы. Отделение ввода/вывода в асинхронный поток в итоге дало слишком большие задержки - до 100 мс. Мне надо хотя-бы 10-20 мс на цифровые входы/выходы. Я переписал код основного потока приема данных с АЦП и цифровых входов, но получил немного странный результат. Вот так выглядит код основного цикла приема/передачи

    //! запись адреса входных данных
    out_buff = address_inp;
    m_invert = 1 - m_invert;
    if(m_invert != 0) out_buff |= 0x4000;

     err = X502_PrepareData(m_dev, 0, 0, (uint32_t*) &out_buff, 1, 0, (uint32_t*)&tmp_data);
    err = X502_Send(m_dev, (uint32_t*)&tmp_data, 1, 2000);
    qint32 rcv_size = X502_Recv(m_dev, (uint32_t*)&tmp_buffer, m_channels + 1, 2000);

   //! такие размеры должны приходить
    quint32 adc_size = m_channels;
    quint32 inp_size = 1;
    qint32 err = X502_ProcessData(m_dev, (uint32_t*)&tmp_buffer, rcv_size, X502_PROC_FLAGS_VOLT,
                                  adc_data, (uint32_t*)&adc_size, (uint32_t*)&inp_buff, (uint32_t*)&inp_size);
    printf("%d %d %d %d\n", err, rcv_size, adc_size, inp_size);
    
   //! копирование входных данных
    m_inputs[address_inp++] = inp_buff;
    memcpy(ret_data, adc_data, sizeof(double) * m_channels);
    }

здесь
m_channels - число каналов АЦП
address_inp - внешний адрес источника  цифровых данных

Ну так вот, когда я запускаю этот поток, то на консоли получаю следующее:

0 12 0 1
0 12 0 1
0 12 0 1
0 12 0 1
0 12 0 1
0 12 4 1
0 12 6 1
0 12 1 1
0 12 0 1
0 12 0 1
0 12 0 1
0 12 0 1
0 12 0 1
т..е
код ошибки 0,
принято всего данных 12, из них - от АЦП то 0, то не ноль (но так что за два - три раза набирается данных с 11 каналов АЦП)
и 1 слово цифровых данных
Вопрос простой - это нормально и надо вызывать функция .X502_ProcessData необходимое число раз чтобы забрать данные с 11 каналов АЦП или что-то не так?

23.08.2017 09:37:22
#30

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

Re: e502: синхронный ввод/вывод

и еще вопрос - если для цифровых входов/выходов я укажу делитель частоты

   X502_SetDinFreqDivider(m_dev, 4);
    X502_SetOutFreqDivider(m_dev, 4);

как это скажется на принимаемых значениях? Т.е. inp_size всегда будет 1, но данные в буфере будут одни и те же?

23.08.2017 12:27:09
#31

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

Re: e502: синхронный ввод/вывод

А какое соотношение частот АЦП и DIN в примере, где вы приводите цифры.
Судя по всему частота DIN сильно больше АЦП, в этом случае у Вас в первых 12 словах все DIN, соответственно так как Вы передали размер на прием DIN 1 он сохранил только 1 отсчет из 12, т.к. на остальные нет места в указанном вами выходном буфере.
Соответственно у Вас сперва идет 60 отсчетов DIN, потом в следующих 12 4 АЦП и 8 DIN и т.п. в результате все значения с АЦП Вы примете корректно (т.к. на них всегда есть место), а DIN часть пропустите. Чтобы принимать всегда все DIN при разных частотах АЦП/DIN нужно на вход ProcessData подать массив для din тоже на 12 и уже анализировать din_size.
Увеличение делителя на DIN приводит к тому, что отсчеты с DIN будут идти реже и соответственно изменится соотношение кол-ва DIN на отсчеты АЦП в потоке.
На вывод делитель будет означать, что выведенное значение DOUT будет удерживаться большее время перед тем как будет выведено следующее значение массива.

23.08.2017 13:29:33
#32

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

Re: e502: синхронный ввод/вывод

Вот код инициализации:

    X502_SetDinFreqDivider(m_dev, 4);
    X502_SetOutFreqDivider(m_dev, 4);
    err = X502_StreamsEnable(m_dev, X502_STREAM_ADC | X502_STREAM_DIN | X502_STREAM_DOUT);
    err = X502_PreloadStart(m_dev);
    err = X502_StreamsStart(m_dev);
23.08.2017 13:46:04
#33

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

Re: e502: синхронный ввод/вывод

Ну во первых первые две функции должны идти до Configure, а во вторых Вы не привели код установки частоты АЦП (через X502_SetAdcFreq или через явную установку делителей)

23.08.2017 14:28:09
#34

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

Re: e502: синхронный ввод/вывод

Полный код инициализации АЦП конечно есть, все же работает без цифровых входов/выходов... а вот замечание на счет X502_SetDinFreqDivider - спасибо, сейчас попробую

23.08.2017 14:32:44
#35

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

Re: e502: синхронный ввод/вывод

не, ничего не поменялось...

0 12 0 1
0 12 0 1
0 12 0 1
0 12 5 1
0 12 6 1
0 12 0 1
0 12 0 1
0 12 0 1

хотя код переставил:

   X502_SetSyncMode(m_dev, X502_SYNC_INTERNAL);
    X502_SetSyncStartMode(m_dev, X502_SYNC_INTERNAL);

    double fAcq = 2000000.0, fAdcFrame = 50.0 * global->m_dval[LINEPPP];
    err = X502_SetAdcFreq(m_dev, &fAcq, &fAdcFrame);
    X502_SetDinFreqDivider(m_dev, 1);
    X502_SetOutFreqDivider(m_dev, 1);
    err = X502_Configure(m_dev, 0);
23.08.2017 14:34:05
#36

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

Re: e502: синхронный ввод/вывод

ну и там перед этим еще все каналы АЦП определяются..

23.08.2017 17:05:30
#37

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

Re: e502: синхронный ввод/вывод

При X502_SetDinFreqDivider(m_dev, 1) у Вас частота ввода 2 МГц, а частота кадров АЦП - 50*global->m_dval[LINEPPP] Гц (не знаю чему у Вас это значение равно). Соответственно в таких пропорциях и будут приходить данные

20.09.2017 17:01:22
#38

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

Re: e502: синхронный ввод/вывод

Вот такой вопрос, который мешает корректно принимать данные по цифровым входам в синхронном режиме одновременно с приемом данных с АЦП: как бы получить на внешнем разъеме строб, соответствующий моменту чтения цифровых входов? Или по другому - можете подсказать в какой момент времени относительно строба CONV_OUT (или START_OUT) происходит чтение данных с цифрового входа?

20.09.2017 20:11:51
#39

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

Re: e502: синхронный ввод/вывод

@ Valery,  интересующие Вас времена задержек при производстве E-502 не контролируются, но могут быть вычислены теоретически, исходя из допусков на минимальное и максимальное  время распространения сигналов логических элементов (согласно документации на элементы и временной модели ПЛИСов ). Данные вычисления проведу в ближайшее время, о результатах сообщу.

20.09.2017 21:41:14
#40

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

Re: e502: синхронный ввод/вывод

Очень хорошо.. а можно указать сигнал от которого надо отсчитывать задержку? START_OUT или CONV_OUT?

20.09.2017 22:30:06
#41

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

Re: e502: синхронный ввод/вывод

CONV_OUT транслирует внутренний сигнал синхронизации преобразования АЦП, ЦАП, стробирования данных  входов DI и выдачи на выход DO. Все эти четыре потока данных ввода-вывода синхронны по отношению к CONV_OUT.  А по фронту START_OUT  можно только синхронизировать начало сбора данных.

21.09.2017 11:00:45
#42

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

Re: e502: синхронный ввод/вывод

В документации приведена временная диаграмма работы АЦП, а вот бы хорошо иметь то же самое для цифровых входов/выходов.. у меня должен быть синхронный цикл такого вида: запись адреса -> чтение данных и параллельно чтение аналоговых данных с АЦП.
И вот тут-то вся проблема. После записи адреса во внешний ящик и готовностью данных для чтения  проходит 16 мксек, а е502 похоже читает данные быстрее.. и начинаются "пляски с бубнами"

21.09.2017 12:12:06
#43

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

Re: e502: синхронный ввод/вывод

@ Valery,  все процессы  сбора-выдачи данных в  E-502 синхронны по отношению к опорной частоте 2 МГц (которая транслируется на CONV_OUT во время сбора данных). И я уже  собрался для Вас вычислять наносекундные задержки в пределах периода 500 нс этой опорной частоты.
Но если же Вас интересуют аппаратные задержки  ввода первого отсчёта относительно вывода первого отсчёта  с точностью до периода опорной частоты, то они могут измеряться только  несколькими  периодами опорной частоты, но никак не  16 мкс (32 периода). Но для АЦП следует учесть, что дополнительную задержку создаёт внутренний механизм усреднения/прореживания  отсчётов данных, если усреднение было применено (тогда задержка отсчётов АЦП может быть и больше 16 мкс).
Прошу уточнить: Вас интересуют задержки ввода-вывода относительно синхросигнала  CONV_OUT (в пределах периода) или задержки  между отсчётами ввода-выдачи данных (с точностью до периода опорной частоты)?
Если и то, и другое. и для всех режимов усреднения/прореживания АЦП, и для всех режимов синхронизации E-502, то описания этих диаграмм и задержек нужно проводить в рамках дополнения документации на E-502, но в ближайшее время у нас на это время не выделено.

21.09.2017 13:05:10
#44

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

Re: e502: синхронный ввод/вывод

Ну да, вы правы, меня как раз и интересуют задержка момента ввода цифровых сигналов относительно этого синхросигнала.
Ситуация такая: опорная частота АЦП 2 МГц, частота кадров 4 кГц, усреднения нет.. т.е. мне нужны мгновенные значения аналоговых сигналов с дискретностью 250 мксек. И одновременно идет вывод/чтение цифровых данных..
Вот похоже на чтении я и лажаю, поскольку нет уверенности что читаются валидные данные.

21.09.2017 15:52:53
#45

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

Re: e502: синхронный ввод/вывод

@ Valery, расчётные результаты таковы. Если за 0 нс принять момент фронта (0->1)  сигнала CONV_OUT, то:
-  Расчётное время установления данных (setup) на цифровых входах DI будет  минус 4,5 нс, а время удержания данных (hold) на цифровых входах DI - минус 1,5 нс. 
-  Время выборки данных АЦП относительно аналоговых входов  оценивается в диапазоне  от минус 10  до минус 70 нс  (это связано с  задержкой аналогового тракта, которая может быть разной на разных поддиапазонах измерения). По-хорошему, эту групповую задержку нужно измерить, но данная метрология у нас не проводилась (поэтому эти данные носят оценочных характер).

Если усреднение АЦП не используется, то каждый фронт CONV_OUT будет соответствовать отсчёту АЦП и цифрового входа DI c одним и тем же порядковым номером (т.е. по тактам преобразования между АЦП и DI - нулевая задержка). Но в буфер данные DI кладутся по порядку раньше, чем отчёты АЦП (кажется, на 2 отсчёта - это можно уточнить), но эта задержка буферизации уже не имеет отношения к рассматриваемой аппаратной задержке преобразования АЦП и ввода DI по отношению к CONV_OUT.

21.09.2017 16:57:31
#46

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

Re: e502: синхронный ввод/вывод

Во!! Даже и не могу сказать как вы мне помогли, теперь я вполне могу решить проблему.. Большое спасибо!

24.10.2017 17:11:18
#47

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

Re: e502: синхронный ввод/вывод

Я не уверен, что вы готовы продолжать это бесконечное разбирательство, но у меня просто идеи реализации того, что мне нужно иссякли..
Собственно как и раньше основная задача получить минимальную задержку в отправке/приеме цифровых данных одновременно с приемом данных с АЦП. Частота фрейма 4 кГц, а частота АЦП 2 МГц. Я сделал примитивную схему прямо на разъеме е502:

выходной 4-й бит замкнул на входной  0-й бит
выходной 0-й бит замкнул на входной  8-й бит

и написал вот такую программу

double fAcq = 2000000.0, fAdcFrame = 4000.0;
X502_SetAdcFreq(m_dev, &fAcq, &fAdcFrame);

m_bin_size = 250;
int divInp, divOut;

double freqInp  = fAdcFrame * m_bin_size;
X502_SetDinFreq(m_dev, &freqInp);

double freqOut  = fAdcFrame;
X502_SetOutFreq(m_dev, &freqOut);

X502_Configure(m_dev, 0);

X502_StreamsEnable(m_dev, X502_STREAM_ADC | X502_STREAM_DIN | X502_STREAM_DOUT);

X502_SetStreamBufSize(m_dev, X502_STREAM_CH_OUT, 1);
X502_SetStreamStep(m_dev, X502_STREAM_CH_OUT, 1);
X502_PreloadStart(m_dev);

sendRelayData();

X502_SetStreamBufSize(m_dev, X502_STREAM_CH_IN, (m_channels + m_bin_size) * 80);
X502_SetStreamStep(m_dev, X502_STREAM_CH_IN, m_channels + m_bin_size);

X502_StreamsStart(m_dev);
X502_Send(m_dev, (uint32_t*)tmp_buffer, 1, 2000);

while(1)
{
    qint32 rcv_size = X502_Recv(m_dev, (uint32_t*)inp_buffer, m_channels + m_bin_size, 2000);
    if(rcv_size > 0)
    {
        int fch = 0;
        X502_GetNextExpectedLchNum(m_dev, (uint32_t*)&fch);
        qint32 amp_size = m_channels;
        qint32 inp_size = m_bin_size;
        X502_ProcessData(m_dev, (uint32_t*)inp_buffer, rcv_size, X502_PROC_FLAGS_VOLT,
                      adc_data, (uint32_t*)&amp_size, (uint32_t*)bin_buffer, (uint32_t*)&inp_size);

        testReadData(inp_size);

        if(amp_size > 0)
        {
            for(int n = 0; n < m_channels; ++n)
            {
                int pos = (n >= fch)? n - fch : m_channels - fch + n;
                if(pos < m_channels) ret_data[n] = adc_data[pos];
            }
            adc_size += amp_size;
            if(adc_size == m_channels)
            {
                adc_size = 0;
                
				m_meandr++;
				if(m_meandr > 2000)
				{
					m_meandr = 0;
					m_invert = 1 - m_invert;
				}
                
			    if(m_relay_mode != 0) sendInputAddress(); else sendRelayData();
                X502_Send(m_dev, (uint32_t*)tmp_buffer, 1, 2000);
            }
        }
    }
}


void sendInputAddress()
{
    m_address = address_inp;
    if(m_invert != 0) m_address |= 0x4000;
    out_buffer = m_address;
    X502_PrepareData(m_dev, NULL, NULL, (uint32_t*)&out_buffer, 1, 0, (uint32_t*)tmp_buffer);
    m_relay_mode = 0;
}

void sendRelayData()
{
    m_address = m_relays[address_inp] | 0x8 | address_inp;
    if(m_invert != 0) m_address |= 0x4000;
    out_buffer = m_address;
    X502_PrepareData(m_dev, NULL, NULL, (uint32_t*)&out_buffer, 1, 0, (uint32_t*)tmp_buffer);
    m_relay_mode = 1;
}

void testReadData(int size)
{
    data_inp = 0;
    for(int i = 0; i < size; i++)
    {
        quint32 src = bin_buffer[i];
        data_inp |= src & 0x7ff;
    }
    if(m_relay_mode != 0)
    {
        m_status[address_inp] = data_inp;
    }
    else
    {
        m_inputs[address_inp++] = data_inp;
        if(address_inp == input_count) address_inp  = 0;
    }
}

Если смотреть осциллографом, то получится следующее: на выходе 4-го бита будет меандр с периодом 500 мсек,
я его читаю по 0-му биту входу и программно передаю на 0-й выходной бит. Соответственно тот же сигнал должен читаться с 8-го входного бита.
Однако я имею задержку аж в 7 мсек между 0-м и  8-м битом. Вопрос простой - откуда такая задержка берется...

24.10.2017 22:36:17
#48

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

Re: e502: синхронный ввод/вывод

@ Valery, простите, я - не программист, но уж сильно похоже на ситуацию, описанную в этой статье FAQ:
http://www.lcard.ru/support/faq/problem … me_release

25.10.2017 10:22:27
#49

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

Re: e502: синхронный ввод/вывод

Да,я это конечно читал и понимаю в чем тут могут быть проблемы... единственное хочу заметить, что если данные с АЦП совершенно адекватные и частота фрейма низкая..  думаете что USB так сильно задерживает только данные с цифровых входов? Но насколько я понимаю все пишется-читается в одном буфере. На осциллографе картинка стоит без дрожаний, т.е. времени хватает на все...

25.10.2017 14:07:16
#50

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

Re: e502: синхронный ввод/вывод

Честно говоря по приведенному коду программы сложно понять, что Вы выводите и насколько это соответствует тому, что описывали, так как у Вас там накручена какая-то своя логика формирования данных (вроде m_meandr и m_invert влияют на 15-ый бит (0x4000), а не 4-ый?).

Данные АЦП и цифровых входов передаются одним потоком и в ходе передачи задерживаются на одинаковое время (единственное, начальный момент измерения может быть со сдвигом, но это совсем другие порядки времен). Другой вопрос, что из того, что данные адекватные и картинка без дрожаний (хотя небольшое дрожание наверное в любом случае должно быть, все же временные задержки программы все равно будут немного отличаться, хотя это дрожание может быть не заметно для сигнала 500 мс и видимо им можно пренебречь).
Здесь вопрос идет скорее о латентности канала передачи данных, т.е. за сколько времени данные передаются от выхода АЦП через модуль, шину USB, драйвер ОС и системные вызовы в программу. Вы будете получать кадры с той же частотой, что они были сняты модулем, но они будут задержаны все на одинаковое время относительно реальных моментов времени, т.е. сама получаемая на ПК диаграмма у Вас полностью совпадает, но сдвинута на это время задержки канала относительно реального сигнала. Такая же сдвижка будет и для вывода на время, соответствующее латентности этого канала передачи. Т.е. опять же диаграмма будет та же, но сдвинута на эту задержку.

Время это сильно зависит от ОС, конкретного ПК и т.п. и явно оно не измерялось, но суммарное время задержки обоих каналов в 7 мс не выглядит большим и вполне может соответствовать реальному.

Вообще проверить это время можно простым тестом - сперва выставить на цифровые выходы 0, затем разрешить поток на вывод, сделать Preload и загрузить код, соответствующий 1 на выходе, после этого запустить поток, принять первый кадр АЦП и сразу передать на вывод 0. В результате у Вас будет переход от 0 в 1 в момент начала запуска потоков и переход из 1 в 0 в момент когда вы обработаете первый кадр и выведите значение, т.е. длина импульса будет соответствовать суммарному времени задержки ввода и вывода + время сбора одного кадра АЦП.

Контакты

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

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

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

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