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

фильтрация

 

1. Назначение

Плагин позволяет проводить спектральный анализ по двум каналам в реальном масштабе времени.
  • Одновременная работа по двум каналам.
  • Работа как в реальном масштабе времени, так и в режиме просмотра файла.
  • Выбор типа накладываемого на сигнал перед спектральным анализом окна.

2. Исходный текст плагина

/* Плагин, реализующий двухканальный спектроанализатор, работающий в реальном времени. Среда разработки LabWindows CVI 9.0. */ #include #include #include #include #include "..\\include\\plugin.h" #define SPEKTR_SIZE 32768 // число точек для БПФ static struct PluginDataInfoStr DataInfo; // структура с настройками АЦП static int device_index=0; // работаем с первым модулем АЦП // массивы для рассчета спектров static double SpektrY1[SPEKTR_SIZE/2]; static double SpektrY2[SPEKTR_SIZE/2]; static double SpektrX1[SPEKTR_SIZE/2]; static double SpektrX2[SPEKTR_SIZE/2]; static double Auto_Spectrum[SPEKTR_SIZE/2]; static double SpektrData[SPEKTR_SIZE]; // ********************************************************************************************************* // главная функция обмена данными с рассчетом спектров void __stdcall PluginDataExchange(struct PluginDataStr *data_str) { int i, j, chan, index, n; WindowConst WinConst; double df, *x; char Unit[256]; int chan1, chan2; Unit[0]=0; chan1=DataInfo.adc_channels[0]; // запомним номер первого канала (от 0 до 31) chan2=DataInfo.adc_channels[1]; // запомним номер второго канала (от 0 до 31) n=data_str->n; // сколько пришло кадров if(n & 1) n--; // сделаем n четным for(chan=0; chan < 2; chan++) // цикл по двум каналам { // переложим в SpektrData данные от обрабатываемого канала index=(chan) ? DataInfo.chan_kadr_offset[device_index][chan2] : DataInfo.chan_kadr_offset[device_index][chan1]; for(i=0; i < n; i++, index += DataInfo.nch[device_index]) SpektrData[i]=data_str->data_to_plugin[index]; // наложим на данные выбранное окно ScaledWindow (SpektrData, n, DataInfo.parameters_int[1], &WinConst); // рассчет спектра AutoPowerSpectrum (SpektrData, n, 1./DataInfo.rate[device_index], Auto_Spectrum, &df); // преобразуем спектр в дБ, Vrms (volts rms) SpectrumUnitConversion (Auto_Spectrum, n/2, 0, 1, DataInfo.parameters_int[0], df, WinConst, (chan) ? SpektrY2 : SpektrY1, Unit); // сохраним данные для передачи в ЛГраф data_str->n_from_graph[chan]=n/2; data_str->data_from_graph[chan]=(chan) ? SpektrY2 : SpektrY1; // сформируем ось X в герцах for(i=0, x=(chan) ? SpektrX2 : SpektrX1; i < n/2; i++) *x++=i*df; data_str->x_data[chan]=(chan) ? SpektrX2 : SpektrX1; data_str->control_index[chan]=chan; // номер графического элемента, в котором будет нарисован график data_str->color[chan]=VAL_RED; // цвет графика data_str->line_type[chan]=VAL_SOLID; // тип линии (сплошной, точки и т.п.) data_str->line_mode[chan]=VAL_VERTICAL_BAR; // тип графика sprintf(data_str->name[chan], "Канал %u", (chan) ? chan2+1 : chan1+1); // имя графика (для легенды) } } //********************************************************************************************************* // информационная функция void __stdcall PluginInfo(struct PluginInfoStr *p_info) { int i; char *rms_names[]={"Vrms (volts rms)", "Vpk (volts peak)", "Vrms2 (volts squared rms)", "Vpk2 (volts squared peak)", "Vrms/ (volts rms per root Hertz)", "Vpk/ (volts peak per root Hertz)", "Vrms2/ (volts squared rms per Hertz)", "Vpk2/ (volts squared peak per Hertz) "}; char *windows_names[]={"Rectangular", "Hanning", "Hamming", "Blackman-Harris", "Exact Blackman", "Blackman", "Flat Top", "4-Term Blackman-Harris", "7-Term Blackman-Harris", "Low Sidelobe"}; // установим общие переменные strcpy(p_info->name, "Spektr1"); // название плагина p_info->version=0x00010000; // версия 1.0 p_info->lgraph_version=0x221; // плагин разработан для версии 2.33 p_info->max_nch=2; // максимальное число каналов, которые может обработать плагин 2 p_info->min_nch=1; // минимальное число каналов 1 // установим параметры входных каналов плагина strcpy(p_info->channel_names[0], "Канал A для расчета спектра"); strcpy(p_info->channel_names[1], "Канал B для расчета спектра"); p_info->parameters=2; // плагин имеет 2 параметра strcpy(p_info->parameters_names[0], "Единицы измерения"); // название первого параметра strcpy(p_info->parameters_names[1], "Накладываемое окно"); // название второго параметра // оба параметра имеют тип текстового списка p_info->parameters_type[0]=L_TYPE_RING; p_info->parameters_type[1]=L_TYPE_RING; // заполним названия параметров for(i=0; i < 8; i++) strncpy(p_info->ring_names[0][i], rms_names[i], 63); for(i=0; i < 10; i++) strncpy(p_info->ring_names[1][i], windows_names[i], 63); } // ********************************************************************************************************* // обработка данных о параметрах модулей АЦП от LGraph void __stdcall PluginDataInfo(struct PluginDataInfoStr *d_info) { int chan1, chan2; if(!d_info->devices) { strcpy(d_info->error, "Нет модуля АЦП"); return; } if(!d_info->nch[device_index]) { strcpy(d_info->error, "Не выбраны каналы АЦП"); return; } DataInfo=*d_info; // запомним параметры АЦП chan1=d_info->adc_channels[0]; // запомним номер первого канала (от 0 до 31) chan2=d_info->adc_channels[1]; // запомним номер второго канала (от 0 до 31) // проверим включен ли первый канал if(!d_info->chan_on[device_index][chan1]) { sprintf(d_info->error, "Не выбран канал %u", chan1+1); return; } // проверим включен ли второй канал if(!d_info->chan_on[device_index][chan2]) { sprintf(d_info->error, "Не выбран канал %u", chan2+1); return; } // данные хотим получать строго по SPEKTR_SIZE кадров с отбрасыванием лишних данных d_info->input_kadrs_min=256; d_info->input_kadrs_max=SPEKTR_SIZE; } //********************************************************************************************************* // настройка графиков void __stdcall PluginVisualSetting(struct PluginVisualMainStr *main_visual_settings, struct PluginVisualStr p_visual[]) { main_visual_settings->n=2; // создаем два графика main_visual_settings->plugin_height=600; // для двух графиков хватит 600 пикселей по высоте p_visual[0].type=p_visual[1].type=L_VISUAL_GRAPH; // тип элементов - графики // настроим графические координаты p_visual[0].top=10; // координата по вертикали первого графика p_visual[0].height=p_visual[1].height=250; // высота каждого графика 250 пикселей p_visual[0].width=p_visual[1].width=main_visual_settings->width-20; // ширина графика p_visual[0].left=p_visual[1].left=10; // горизонтальная координата p_visual[1].top=p_visual[0].top+p_visual[0].height+10; // координата по вертикали второго графика // сконфигурируем ось X (частота) p_visual[0].x_axis_mode=p_visual[1].y_axis_mode=1; // по умолчанию включим автомасштаб по оси X strcpy(p_visual[0].axis_x_label, "Частота, Гц"); // название оси X первого графика strcpy(p_visual[1].axis_x_label, "Частота, Гц"); // название оси X второго графика // сконфигурируем ось Y (дБ) p_visual[0].axis_y_min=p_visual[1].axis_y_min=-120; // минимальное значение p_visual[0].axis_y_max=p_visual[1].axis_y_max=40; // максимальное значение strcpy(p_visual[0].axis_y_label, "Напряжение, дБ"); // название оси Y первого графика strcpy(p_visual[1].axis_y_label, "Напряжение, дБ"); // название оси Y второго графика p_visual[0].x_precision=p_visual[1].x_precision=1; // разметка по X с 1 цифрой после запятой p_visual[0].y_precision=p_visual[1].y_precision=1; // разметка по Y с 1 цифрой после запятой } // Функция сообщает плагину, что начался/закончился сбор данных (в данном плагине не используем) void __stdcall PluginStartInput(struct PluginDataStr *data_str) {} void __stdcall PluginStopInput(struct PluginDataStr *data_str) {} //********************************************************************************************************* // Функция вызываемая при загрузке - выгрузке DLL плагина int __stdcall DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: if (InitCVIRTE (hinstDLL, 0, 0) == 0) return 0; break; case DLL_PROCESS_DETACH: if (!CVIRTEHasBeenDetached ()) CloseCVIRTE (); break; } return 1; }

Контакты

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

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

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

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