Форум:

Вы не вошли.

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

#1 Re: Техническая поддержка » e502: синхронный ввод/вывод » 31.10.2017 16:09:14

Если бы я не успевал обрабатывать кадры, то на приеме аналоговых данных у меня бы развалился спектр сигналов, поскольку с каждого кадра аналоговые данные пишутся в скользящий буфер и от него берется ДПФ. На практике такого не происходит, да и функции обмена с е502 ошибок не возвращают.  В варианте чтения/записи цифровых данных в асинхронном режиме и отдельном потоке все работало, но такой вариант нас не устраивало из-за больших и непрогнозируемых задержек.. по измерениям там было где-то порядка 30-60 мсек,но это и понятно- асинхронное чтение да еще в отдельном потоке с меньшим приоритетом...

#2 Re: Техническая поддержка » e502: синхронный ввод/вывод » 26.10.2017 12:56:51

на нулевой бит выводится то, что я прочитал с нулевого бита.. а задержка возникает между нулевым битом на входе и 7-м, куда прямо на разъеме АЦП запаян выход 0-го бита.. т.е. разъем выглядит так

входы     выходы
0 <---+   +----  0
1        |    |       1           
...       |    |      ...
7 <------- +       7
....      |           ...
15      + -------15

Обнаружил еще одну шнягу - задержка растет с течением времени...

#4 Re: Техническая поддержка » e502: синхронный ввод/вывод » 25.10.2017 17:04:03

ничего не меняется если закомментировать здесь любой из вызовов (кроме конечно сохранения входных данных) или просто вместо этой функции вставить только вывод на консоль входных данных... та же задержка если учесть что такт у нас 250 мксек

#5 Re: Техническая поддержка » e502: синхронный ввод/вывод » 25.10.2017 17:00:04

могу эту функцию привести.. но там много разных вызовов других функций. Здесь основная конва:

//цифровая обработка аналоговых данных
    double* adc_data = app->adc->ret_data;
    for(int n = 0; n < app->adc->m_channels; n++)
    {
        app->rza_data->m_prc[n]->update(adc_data[n]);
    }
    emit rzaUpdate();
// обработка цифровых данных
    app->logic->run();
// сохранение входных данных 
    appendSourceData(adc_data);

#6 Re: Техническая поддержка » e502: синхронный ввод/вывод » 25.10.2017 16:50:04

а-а, точно, этого я в приведенном тексте не указал. там после adc_size = 0 должен идти вызов внешней функции. Но в этой функции ничего особенного нет - используются массивы m_inputs, m_status, из них данные собираются в список и потом пишутся в файл с формате Comtrade (в отдельном потоке с низким приоритетом)

#7 Re: Техническая поддержка » e502: синхронный ввод/вывод » 25.10.2017 15:33:21

на счет компьютера и ОС - ArchLinux, Сore-I5 2.6 GHz... все шустрое, программа работает как сервис, т.е. с рутовым приоритетом.

#8 Re: Техническая поддержка » e502: синхронный ввод/вывод » 25.10.2017 15:30:02

На счет шага - у меня так и сделано:

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);

на счет бита с периодом 500 мсек - это вы правы, я просто ошибся - конечно 15-й.. по фронту этого бита внешнее устройство запускает внешний таймер... На логику не обращайте внимания, она тут чисто от реальной программы, а мне вот что не совсем ясно - я меняю состояние 0-го бита на выходе и тут же запускаю чтение входов. На разъеме АЦП выход 0-го бита соединен со входным 8-м битом, а 15-й (не 4-й конечно) с 0-м входным... так почему же сигнал на 0-м бите читается раньше чем на 8-м на вот эти пресловутые 7 мсек? Где засада - в моем коде или в стеке USB? я пробовал уменьшать размер входного буфера - а ни фига, данные начинают идти с перерывами.. но с той же начальной задержкой

вот вариант с размером буфера в 250 отсчетов: https://yadi.sk/i/41kg9Uod3P5oGu
а вот - с размером буфера 125 отсчетов: https://yadi.sk/i/3nQm4Njf3P5oRW

#9 Re: Техническая поддержка » e502: синхронный ввод/вывод » 25.10.2017 10:22:27

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

#10 Re: Техническая поддержка » e502: синхронный ввод/вывод » 24.10.2017 17:11:18

Я не уверен, что вы готовы продолжать это бесконечное разбирательство, но у меня просто идеи реализации того, что мне нужно иссякли..
Собственно как и раньше основная задача получить минимальную задержку в отправке/приеме цифровых данных одновременно с приемом данных с АЦП. Частота фрейма 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-м битом. Вопрос простой - откуда такая задержка берется...

#11 Re: Техническая поддержка » e502: синхронный ввод/вывод » 21.09.2017 16:57:31

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

#12 Re: Техническая поддержка » e502: синхронный ввод/вывод » 21.09.2017 13:05:10

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

#13 Re: Техническая поддержка » e502: синхронный ввод/вывод » 21.09.2017 11:00:45

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

#14 Re: Техническая поддержка » e502: синхронный ввод/вывод » 20.09.2017 21:41:14

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

#15 Re: Техническая поддержка » e502: синхронный ввод/вывод » 20.09.2017 17:01:22

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

#16 Re: Техническая поддержка » e502: синхронный ввод/вывод » 23.08.2017 14:34:05

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

#17 Re: Техническая поддержка » e502: синхронный ввод/вывод » 23.08.2017 14:32:44

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

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);

#18 Re: Техническая поддержка » e502: синхронный ввод/вывод » 23.08.2017 14:28:09

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

#19 Re: Техническая поддержка » e502: синхронный ввод/вывод » 23.08.2017 13:29:33

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

    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);

#20 Re: Техническая поддержка » e502: синхронный ввод/вывод » 23.08.2017 09:37:22

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

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

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

#21 Re: Техническая поддержка » e502: синхронный ввод/вывод » 23.08.2017 09:24:25

Добрый день! Хочу продолжить обсуждение проблемы. Отделение ввода/вывода в асинхронный поток в итоге дало слишком большие задержки - до 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 Re: Техническая поддержка » Сборка библиотек для e502 под Эльбрус » 28.04.2017 09:18:22

ну да, с ней: там аналоговый поток 16 * 32 * 4000 Гц, цифровой - 4 * 32 (асинхронно и пореже) + 16 ДПФ + несколько десятков специальных функций + сервер 61850.. в общем до фига. Но если сравнивать с интеловским процессором, то эта цифра где-то на уровне двухядерного Атома. аналогичный результат я имею на LBox с Arch Linux..

#24 Re: Техническая поддержка » Сборка библиотек для e502 под Эльбрус » 27.04.2017 17:31:37

все работает. На моих потоках загрузка процессора примерно 70%.. совсем неплохо!

Контакты

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

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

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

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