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


Скорость Считывания данных АЦП

Вы не вошли.

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

Denis
21.04.2006 14:12:14
#1

Гость

Скорость Считывания данных АЦП

В общем в плате L-780 замечено такое непонятное свойство. При циклическом сборе если мы количество отсчетов для сбора ставим 65536 - то отслеживая переменной syncVarPointer положение записи текущей порции (я устанавливал по 2048 порции) и сразу же пытаясь считать якобы только что записанную порцию там получались не совсем те данные что должны быть... реальные данные можно было считать только если дождаться полного заполнения всех отсчетов т.е. 65536  конечно проблема решается достаточно несложно - я просто ставлю количество отсчетов 2048 - ожидаю пока syncVarPointer не достигнет этой отметки и таким образом получаю реальные данные.. но все таки возможно я что то недопонимаю и хотелось бы услышать комментарии специалистов...

параметры задаются следующие:

   public unsafe string SetWorkParameters()
        {           
            csDriverLibrary.WADC_PAR_0 InitParameters = new csDriverLibrary.WADC_PAR_0();
       
            InitParameters.s_Type = csDriverLibrary.L_ADC_PARAM; // тип структуры (должен быть L_ADC_PARAM);
            InitParameters.AutoInit = 1; // флаг указывающий на тип сбора данных 0 - однократный 1 - циклический;
            InitParameters.dRate = SamplingFrequency;     // частота опроса каналов в кадре (кГц);
            InitParameters.dKadr = 0;       // интервал между кадрами (мс);             
            InitParameters.dScale = 0;     // масштаб работы (таймера для 1250 или делителя для 1221)
            InitParameters.SynchroType = 3; // тип синхронизации;  (если больше 2 - то нет синхронизации)           
            InitParameters.SynchroSensitivity = 0; // вид синхронизации           
            InitParameters.SynchroMode = 0;         // режим синхронизации           
            InitParameters.AdChannel = 0;           // канал по которому выполняется синхронизация                       
            InitParameters.AdPorog = 0;             // уровень синхронизации
            InitParameters.NCh = NumberOfChannels;         // количество опрашиваемых каналов ;
            InitParameters.Chn[0] = 0x0;    // массив с номерами каналов и усилением на них; описывает порядок опроса каналов;
            //InitParameters.Chn[1] = 0x1; // усиления 0x00 - нет усиления 0х40 - усиление в 4 раза 0x80 - усиление в 16 раз, 0xc0 - усиление в 64 раза
           // InitParameters.Chn[2] = 0x2;
           // InitParameters.Chn[3] = 0x3;
            InitParameters.FIFO = 2048;     // размер половины аппаратного буфера FIFO на плате;
            InitParameters.IrqStep = InteraptGenerationStep;  //  шаг генерации прерываний
            InitParameters.Pages = 1;       // размер кольцевого буфера в шагах прерываний
            // произведение этих двух параметров IrqStep*Pages задает количество отсчетов,
            // которое соберет плата при однократном сборе, но не больше чем 128К отсчетов.
            // При циклическом сборе они игнорируются – буфер всегда 128К.
            InitParameters.IrqEna = 1;      // разрешение генерации прерывания от платы (1/0),
            // при этом mask - это младшие 16 бит в слове разрешающем прерывания от платы (блок АЦП);
            InitParameters.AdcEna = 1;      // разрешение работы АЦП (1/0);

            csDriverLibrary.FillDAQparameters(ref hIfc, ref InitParameters, (uint)2); //sp_type (t1=0, t2=1, t3 = 2, t4 =3)           
         
           // DAQparameters.t3 = InitParameters;

            string ParameterSettingLog = "";

            uint tm = 2048; // количество отсчтов (так как мы решили считывать порциями по 2048 то столько и ставим)
            Err = csDriverLibrary.RequestBufferStream(ref hIfc, ref tm, csDriverLibrary.L_STREAM_ADC); // функция служит для выделения памяти под большой кольцевой буфер
            ParameterSettingLog += "/nCalled RequestBufferStream. Allocated memory size(word): " + tm.ToString() + ". Error result = " + Err.ToString() + '/n';
           
            // фунция настраивает плату ацп/цап под заданные параметры ввода выода
            Err = csDriverLibrary.SetParametersStream(ref hIfc, ref InitParameters, /*csDriverLibrary.L_STREAM_ADC*/ (uint)2, ref tm, ref dataStartPointer, ref syncVarPointer, csDriverLibrary.L_STREAM_ADC);
            ParameterSettingLog += "Настрайка АЦП/ЦАП заданными параметры ввода выода... /n" + ErrorMessenger(Err) + "/n";
            ParameterSettingLog += "Установленные параметры  : " + "/n";
            ParameterSettingLog += "Размер буфера (word) : " + tm.ToString() + "/n";
            ParameterSettingLog += "Страницы отсчетов : " + InitParameters.Pages.ToString() + "/n";
            ParameterSettingLog += "Шаг генерации прерываний : " + InitParameters.IrqStep.ToString() + "/n";
            ParameterSettingLog += "Размер половины аппаратного буфера FIFO на плате : " + InitParameters.FIFO.ToString() + "/n";
            ParameterSettingLog += "частота опроса каналов : " + InitParameters.dRate.ToString() + "/n";

            DAQparameters.t3 = InitParameters; // записываем параметры инициализации в поле структуры необходимой непонятно кому???

            Err = csDriverLibrary.EnableCorrection(ref hIfc,1); // Функция включает/выключает режим коррекции. Сама загружает коэффициенты в плату
            ParameterSettingLog += "Вклучение режима коррекции...  /n" + ErrorMessenger(Err) + "/n";
            Err = csDriverLibrary.InitStartLDevice(ref hIfc); // Функция инициализирует внутренние переменные драйвера перед началом сбора
            ParameterSettingLog += "Инициализация внутренних переменных драйвера... /n" + ErrorMessenger(Err) + "/n";

            return ParameterSettingLog;
        }

функция сбора такая:

        public static Int16[] dataPortion = new Int16[2048]; // выделяем память под массив               

        private unsafe void DataCapture(ushort SizeOfDataPortion)
        {
            for (int cycl = 0; cycl < NumberOfPortion; cycl++) // считываем нужное количество порций
            {
                while (ReadingPosPointer != 2048) // ожидаем пока не достигнем окончания порции
                    csDriverLibrary.GetSyncData(ref hIfc, (uint)syncVarPointer.ToInt32(), ref ReadingPosPointer);

                Marshal.Copy(dataStartPointer, dataPortion, 0, 2048);// считываем порцию                           
                OnDataPortionReady(this, dataPortion); // активируем событие и передаем порцию                         
            }
        }

21.04.2006 15:03:57
#2

Сотрудник "Л Кард"
Откуда: Москва
Здесь с 23.04.2014
Сообщений: 3,727

Re: Скорость Считывания данных АЦП

я бы рекомендовал вдумчиво посмотретьна сишный пример L780.TST... и повторитьего на С# через враппер...

Denis
27.04.2006 12:24:48
#3

Гость

Re: Скорость Считывания данных АЦП

В общем пока несовсем получается..... смотрел пример правда для  L783.TST - но думаю это непринципиально.... непонятен один момент почему мы вроде как хотим снять только сто тысяч отсчетов
"DWORD tm = 100000;  // мы захотели 100000 отсчетов"

но в тоже время задаем АЦП принять миллион с копейками:

"
USHORT IrqStep = 1024;//777-777%7; // половинка буфера кратная числу каналов
USHORT FIFO = 1024;         //
USHORT pages = 32;
USHORT multi = 64; // - количество половинок кольцевого буфера, которое мы хотим собрать
"

в общем случае полбуфера это

ULONG halfbuffer = IrqStep*pages/2;             // Собираем половинками кольцевого буфера

что есть 1024*32/2= 16384

и соответственно

16384 * multi  = 16384 * 64 =  1048576 что есть в 10 раз больше чем нам надо????


ну и соответственно мой вариант

проблема уже как то мной поднималась правда не в этом топике --- почему если я считываю данные от 0 до 2048 сразу после достижения указателя значения 2048 реально там записаны только первые 1024 отсчета из всех 2048??? хотя делал также как у вас только все меньше по размеру (если делать так же как у вас достаточно долго ждать окончания записи всего буфера)

   InitParameters.FIFO = 2048;     // размер половины аппаратного буфера FIFO на плате;
            InitParameters.IrqStep = 2048;  //  шаг генерации прерываний
            InitParameters.Pages = 2;       // размер кольцевого буфера в шагах прерываний

uint tm = 4096; // количество отсчтов (так как мы решили считывать порциями по 2048 то столько и ставим)
         

и непосредственно считывание

  public static Int16[] dataPortion = new Int16[2048]; // выделяем память под массив в котором будем сохранять данные                                   
        public static Int16[] devidedDataPortion = new Int16[4096];
        private unsafe void DataCapture()
        {


            Int16[] Initdata = new Int16[2048]; // создаем массив
            // инициализируем его 5-ами
            for (int i = 0; i < Initdata.Length; i++) // вывод массива на экран                 
                Initdata[i] = 5;

            Int16[] channelDataPortion = new Int16[numberOfChannels * 4096]; // необходимо собрать порцию размером 4096 для каждого канала
            uint readingPosPointer = 0;
           
            uint dataShiftStep = 4096;
            for (int cycl = 0; cycl < NumberOfPortion; cycl++) // считываем нужное количество порций
            {
                uint dataShiftCounter = 0;
                for (ushort channel = 0; channel < numberOfChannels; channel++) // задали число каналов
                {
                    while (readingPosPointer != 2048) // ожидаем пока не достигнем середины порции
                        csDriverLibrary.GetSyncData(ref hIfc, (uint)syncVarPointer.ToInt32(), ref readingPosPointer);

                    Marshal.Copy(dataStartPointer, dataPortion, 0, 2048); // считываем порцию  размером 2048
                    dataPortion.CopyTo(channelDataPortion, dataShiftStep * dataShiftCounter); // копируем только что считанную порцию в наш массив для сбора всех каналов

                    // проверка записывает ли Ацп вообще что нить в память.... т.е. перед съемом заполняем память 1
                    Marshal.Copy(Initdata, 0, dataStartPointer, Initdata.Length);
                    //затерли то что только что считали

                    while (readingPosPointer != 4096) // ожидаем пока не достигнем окончания порции
                        csDriverLibrary.GetSyncData(ref hIfc, (uint)syncVarPointer.ToInt32(), ref readingPosPointer);

                    Marshal.Copy((IntPtr)(dataStartPointer.ToInt32() + 2048), dataPortion, 0, 2048); // считываем порцию                                                                                               
                    dataPortion.CopyTo(channelDataPortion, dataShiftStep * dataShiftCounter + 2048); // копируем только что считанную порцию в наш массив для сбора всех каналов

                    Marshal.Copy(Initdata, 0, (IntPtr)(dataStartPointer.ToInt32() + 2048), Initdata.Length);
                    //затерли то что только что считали


                    dataShiftCounter++;

}

28.04.2006 08:28:50
#4

Сотрудник "Л Кард"
Откуда: Москва
Здесь с 23.04.2014
Сообщений: 3,727

Re: Скорость Считывания данных АЦП

а с каким процом 780? если с 84 то там половина фифо максимум 1024... и функция его обрезала внутри. ...

Denis
28.04.2006 10:53:03
#5

Гость

Re: Скорость Считывания данных АЦП

в общем я вроде как понял в чем была ошибка....

в считывании второй половины буфера я ytghfdbmkyj сдвигал указатель откуда считывать


было вот так
Marshal.Copy((IntPtr)(dataStartPointer.ToInt32() + 2048), dataPortion, 0, 2048); // считываем порцию

первая половина вопроса про ваш пример остаеться в силе

а нужно было

Marshal.Copy((IntPtr)(dataStartPointer.ToInt32() + 4096), dataPortion, 0, 2048); // считываем порцию

28.04.2006 11:28:51
#6

Сотрудник "Л Кард"
Откуда: Москва
Здесь с 23.04.2014
Сообщений: 3,727

Re: Скорость Считывания данных АЦП

ну буфер выделяем на 100000...используем в нем 32 тыщи и прокручиваем его несколько раз...