"use strict"; let signals = gtl.options.record.signalsModel; let options = gtl.options; let record = gtl.options.record; let point = gtl.options.point; // let fnc = gtl.import("user-functions.js"); // используемые функции let plot_0 = gtl.plots.add("Спектр ускорения (канал 0)"); // спектр ускорения канала 0 let plot_1 = gtl.plots.add("Спектр ускорения (канал 1)"); // спектр ускорения канала 1 let plot_2 = gtl.plots.add("Спектр ускорения (канал 2)"); // спектр ускорения канала 2 let plot_3 = gtl.plots.add("Спектр силы (канал 3)"); // спектр ускорения канала 3 let plot_FreqResp_0_3 = gtl.plots.add("Частотный отклик (каналы 0 и 3)"); // частотный отклик между каналами 0 и 3 let plot_FreqResp_1_3 = gtl.plots.add("Частотный отклик (каналы 1 и 3)"); // частотный отклик между каналами 1 и 3 let plot_FreqResp_2_3 = gtl.plots.add("Частотный отклик (каналы 2 и 3)"); // частотный отклик между каналами 2 и 3 // *************************************************************** // ********** ВЫЧИСЛЕНИЕ ЧАСТОТНОГО ОТКЛИКА (ВНИИЖТ) *********** // *************************************************************** // Алгоритм // 1. Получить спектры ускорения и силы в комплексном виде (вибропреобразователь и молоток). // 2. Преобразовать спектр силы (молотка) в комплексно-сопряжённый вид. // 3. Получить кросс-спектр (перекрёстный) между ускорением и силой. // 4. Вычислить деление кросс-спектра на спектр силы. // ОБРАБОТКА СИГНАЛОВ // ФИЛЬТРЫ // Входной сигнал - виброускорение // Файл импорта функций // var imp = gtl.import("..."); // ПАРАМЕТРЫ и их ПОРОГОВЫЕ ЗНАЧЕНИЯ (уставки) // Настройки спектров // Цвета // #ff0000 - красный // #00ff00 - зелёный // #0000ff - синий // #00ddff - голубой // #ff3dcc - фиолетовый // #ffff00 - жёлтый // *** Формирование спектров сигналов *** // Настройки для спектров и АФЧХ let frequency = gtl.options.customOptions.frequency; // граничная частота let resolution = gtl.options.customOptions.resolution; // частотное разрешение let lines = 1 / resolution; // количество линий let average = gtl.options.customOptions.average; // количество усреднений let overlap = gtl.options.customOptions.overlap; // наложение // Задание диапазона сигнала для анализа let ranges = gtl.player.stored_ranges; // Спектры каналов ускорения (каналы датчиков вибрации) // Канал_0 let ausp_acсel_0 = gtl.create_ausp( { "src": gtl.analog_inputs[signals[0].portNumber], // сигнал вибрации сырой "frequency": frequency, "resolution": resolution, "average": average, "overlap": overlap, "window": gtl.spec.rectangular, "view": gtl.spec.unit } ); // Канал_1 let ausp_acсel_1 = gtl.create_ausp( { "src": gtl.analog_inputs[signals[1].portNumber], // сигнал вибрации сырой "frequency": frequency, "resolution": resolution, "average": average, "overlap": overlap, "window": gtl.spec.rectangular, "view": gtl.spec.unit } ); // Канал_2 let ausp_acсel_2 = gtl.create_ausp( { "src": gtl.analog_inputs[signals[2].portNumber], // сигнал вибрации сырой "frequency": frequency, "resolution": resolution, "average": average, "overlap": overlap, "window": gtl.spec.rectangular, "view": gtl.spec.unit } ); // Спектр силы (канал сигнала молотка) // Канал_3 let ausp_force_3 = gtl.create_ausp( { "src": gtl.analog_inputs[signals[3].portNumber], // сигнал вибрации сырой "frequency": frequency, "resolution": resolution, "average": average, "overlap": overlap, "window": gtl.spec.rectangular, "view": gtl.spec.unit } ); //*******************ДИАГНОСТИКА********************* //*************************************************** // Задаем период проведения диагностики в секундах var acq_time = Math.max(ausp_acсel_0.acq_time, ausp_acсel_1.acq_time, ausp_acсel_2.acq_time, ausp_force_3.acq_time) + 0.3; gtl.diagnostic.interval = acq_time; // gtl.diagnostic.interval = 10; // время в секундах (константа) // примечание: наблюдается зависимость результатов АФЧХ от времени диагностики function diagnose() { let n = ausp_force_3.data.length; // переменная для цикла gtl.log.info("n (ausp_data.length)", ausp_force_3.data.length); gtl.log.info("Минимально необходимая длительность сигнала", gtl.diagnostic.interval); // Получение массивов для формулы определения частотного отклика // Канал_3 (ausp_force_3) - комплексно-сопряжённый вид // меняется знак мнимой части на противоположный // действительная часть без изменений let ausp_force_3_imag_anti = []; // мнимая часть с противоположным знаком for (let i = 0; i < n; i += 1) { ausp_force_3_imag_anti.push(ausp_force_3.imag[i] * (-1)); } // Кросс-спектры // Канал_0 & Канал_3 let ausp_cross_0_3_real = []; // действительная часть кросс-спектра 0 & 3 let ausp_cross_0_3_imag = []; // мнимая часть кросс-спектра 0 & 3 for (let i = 0; i < n; i += 1) { ausp_cross_0_3_real.push(ausp_acсel_0.real[i] * ausp_force_3.real[i] - (ausp_acсel_0.imag[i] * ausp_force_3_imag_anti[i])); ausp_cross_0_3_imag.push(ausp_acсel_0.real[i] * ausp_force_3_imag_anti[i] + ausp_acсel_0.imag[i] * ausp_force_3.real[i]); } // Канал_1 & Канал_3 var ausp_cross_1_3_real = []; // действительная часть кросс-спектра 1 & 3 var ausp_cross_1_3_imag = []; // мнимая часть кросс-спектра 1 & 3 for (let i = 0; i < n; i += 1) { ausp_cross_1_3_real.push(ausp_acсel_1.real[i] * ausp_force_3.real[i] - (ausp_acсel_1.imag[i] * ausp_force_3_imag_anti[i])); ausp_cross_1_3_imag.push(ausp_acсel_1.real[i] * ausp_force_3_imag_anti[i] + ausp_acсel_1.imag[i] * ausp_force_3.real[i]); } // Канал_2 & Канал_3 var ausp_cross_2_3_real = []; // действительная часть кросс-спектра 2 & 3 var ausp_cross_2_3_imag = []; // мнимая часть кросс-спектра 2 & 3 for (let i = 0; i < n; i += 1) { ausp_cross_2_3_real.push(ausp_acсel_2.real[i] * ausp_force_3.real[i] - (ausp_acсel_2.imag[i] * ausp_force_3_imag_anti[i])); ausp_cross_2_3_imag.push(ausp_acсel_2.real[i] * ausp_force_3_imag_anti[i] + ausp_acсel_2.imag[i] * ausp_force_3.real[i]); } // Частотный отклик (деление кросс-спектра на спектр силы) // (Канал_0 & Канал_3) / Канал_3 let freq_resp_0_3_real = []; // действительная часть частотного отклика между 0 и 3 let freq_resp_0_3_imag = []; // мнимая часть частотного отклика между 0 и 3 let freq_resp_0_3_ampl = []; // амплитуда частотного отклика между 0 и 3 let freq_resp_0_3_phase = []; // фаза частотного отклика между 0 и 3 (корректировка) for (let i = 0; i < n; i += 1) { freq_resp_0_3_real.push((ausp_cross_0_3_real[i] * ausp_force_3.real[i] + ausp_cross_0_3_imag[i] * ausp_force_3.imag[i]) / (Math.pow(ausp_force_3.real[i], 2) + Math.pow(ausp_force_3.imag[i], 2))); freq_resp_0_3_imag.push((ausp_force_3.real[i] * ausp_cross_0_3_imag[i] - ausp_cross_0_3_real[i] * ausp_force_3.imag[i]) / (Math.pow(ausp_force_3.real[i], 2) + Math.pow(ausp_force_3.imag[i], 2))); } // запись массива амплитуды и фазы for (let i = 0; i < n; i += 1) { freq_resp_0_3_ampl.push(Math.sqrt(Math.pow(freq_resp_0_3_real[i],2) + Math.pow(freq_resp_0_3_imag[i],2))); if (freq_resp_0_3_real[i] > 0 & freq_resp_0_3_imag[i] > 0) {freq_resp_0_3_phase.push(Math.atan(freq_resp_0_3_imag[i] / freq_resp_0_3_real[i]) * 180 / Math.PI)} else if (freq_resp_0_3_real[i] < 0 & freq_resp_0_3_imag[i] > 0) {freq_resp_0_3_phase.push(180 - Math.atan(freq_resp_0_3_imag[i] / freq_resp_0_3_real[i]) * 180 / Math.PI)} else if (freq_resp_0_3_real[i] < 0 & freq_resp_0_3_imag[i] < 0) {freq_resp_0_3_phase.push(180 + Math.atan(freq_resp_0_3_imag[i] / freq_resp_0_3_real[i]) * 180 / Math.PI)} else if (freq_resp_0_3_real[i] > 0 & freq_resp_0_3_imag[i] < 0) {freq_resp_0_3_phase.push(360 - Math.atan(freq_resp_0_3_imag[i] / freq_resp_0_3_real[i]) * 180 / Math.PI)} } // корректировка угла для предотвращения превышения 360 град for (let i = 0; i < freq_resp_0_3_phase.length; i += 1) { if (freq_resp_0_3_phase[i] >= 360) {freq_resp_0_3_phase[i] = freq_resp_0_3_phase[i] - 360} else {freq_resp_0_3_phase[i] = freq_resp_0_3_phase[i]} } // (Канал_1 & Канал_3) / Канал_3 let freq_resp_1_3_real = []; // действительная часть частотного отклика между 0 и 3 let freq_resp_1_3_imag = []; // мнимая часть частотного отклика между 0 и 3 let freq_resp_1_3_ampl = []; // амплитуда частотного отклика между 0 и 3 let freq_resp_1_3_phase = []; // фаза частотного отклика между 0 и 3 for (let i = 0; i < n; i += 1) { freq_resp_1_3_real.push((ausp_cross_1_3_real[i] * ausp_force_3.real[i] + ausp_cross_1_3_imag[i] * ausp_force_3.imag[i]) / (Math.pow(ausp_force_3.real[i], 2) + Math.pow(ausp_force_3.imag[i], 2))); freq_resp_1_3_imag.push((ausp_force_3.real[i] * ausp_cross_1_3_imag[i] - ausp_cross_1_3_real[i] * ausp_force_3.imag[i]) / (Math.pow(ausp_force_3.real[i], 2) + Math.pow(ausp_force_3.imag[i], 2))); } // запись массива амплитуды и фазы for (let i = 0; i < n; i += 1) { freq_resp_1_3_ampl.push(Math.sqrt(Math.pow(freq_resp_1_3_real[i],2) + Math.pow(freq_resp_1_3_imag[i],2))); if (freq_resp_1_3_real[i] > 0 & freq_resp_1_3_imag[i] > 0) {freq_resp_1_3_phase.push(Math.atan(freq_resp_1_3_imag[i] / freq_resp_1_3_real[i]) * 180 / Math.PI)} else if (freq_resp_1_3_real[i] < 0 & freq_resp_1_3_imag[i] > 0) {freq_resp_1_3_phase.push(180 - Math.atan(freq_resp_1_3_imag[i] / freq_resp_1_3_real[i]) * 180 / Math.PI)} else if (freq_resp_1_3_real[i] < 0 & freq_resp_1_3_imag[i] < 0) {freq_resp_1_3_phase.push(180 + Math.atan(freq_resp_1_3_imag[i] / freq_resp_1_3_real[i]) * 180 / Math.PI)} else if (freq_resp_1_3_real[i] > 0 & freq_resp_1_3_imag[i] < 0) {freq_resp_1_3_phase.push(360 - Math.atan(freq_resp_1_3_imag[i] / freq_resp_1_3_real[i]) * 180 / Math.PI)} } // корректировка угла для предотвращения превышения 360 град for (let i = 0; i < freq_resp_1_3_phase.length; i += 1) { if (freq_resp_1_3_phase[i] >= 360) {freq_resp_1_3_phase[i] = freq_resp_1_3_phase[i] - 360} else {freq_resp_1_3_phase[i] = freq_resp_1_3_phase[i]} } // (Канал_2 & Канал_3) / Канал_3 let freq_resp_2_3_real = []; // действительная часть частотного отклика между 2 и 3 let freq_resp_2_3_imag = []; // мнимая часть частотного отклика между 2 и 3 let freq_resp_2_3_ampl = []; // амплитуда частотного отклика между 2 и 3 let freq_resp_2_3_phase = []; // фаза частотного отклика между 2 и 3 for (let i = 0; i < n; i += 1) { freq_resp_2_3_real.push((ausp_cross_2_3_real[i] * ausp_force_3.real[i] + ausp_cross_2_3_imag[i] * ausp_force_3.imag[i]) / (Math.pow(ausp_force_3.real[i], 2) + Math.pow(ausp_force_3.imag[i], 2))); freq_resp_2_3_imag.push((ausp_force_3.real[i] * ausp_cross_2_3_imag[i] - ausp_cross_2_3_real[i] * ausp_force_3.imag[i]) / (Math.pow(ausp_force_3.real[i], 2) + Math.pow(ausp_force_3.imag[i], 2))); } // запись массива амплитуды и фазы for (let i = 0; i < n; i += 1) { freq_resp_2_3_ampl.push(Math.sqrt(Math.pow(freq_resp_2_3_real[i],2) + Math.pow(freq_resp_2_3_imag[i],2))); if (freq_resp_2_3_real[i] > 0 & freq_resp_2_3_imag[i] > 0) {freq_resp_2_3_phase.push(Math.atan(freq_resp_2_3_imag[i] / freq_resp_2_3_real[i]) * 180 / Math.PI)} else if (freq_resp_2_3_real[i] < 0 & freq_resp_2_3_imag[i] > 0) {freq_resp_2_3_phase.push(180 - Math.atan(freq_resp_2_3_imag[i] / freq_resp_2_3_real[i]) * 180 / Math.PI)} else if (freq_resp_2_3_real[i] < 0 & freq_resp_2_3_imag[i] < 0) {freq_resp_2_3_phase.push(180 + Math.atan(freq_resp_2_3_imag[i] / freq_resp_2_3_real[i]) * 180 / Math.PI)} else if (freq_resp_2_3_real[i] > 0 & freq_resp_2_3_imag[i] < 0) {freq_resp_2_3_phase.push(360 - Math.atan(freq_resp_2_3_imag[i] / freq_resp_2_3_real[i]) * 180 / Math.PI)} } // корректировка угла для предотвращения превышения 360 град for (let i = 0; i < freq_resp_2_3_phase.length; i += 1) { if (freq_resp_2_3_phase[i] >= 360) {freq_resp_2_3_phase[i] = freq_resp_2_3_phase[i] - 360} else {freq_resp_2_3_phase[i] = freq_resp_2_3_phase[i]} } // Построение пользовательских графиков plot_0.add( { color: 0x04ff00, name: "Спектр ускорения (канал 0)", x: 1/lines, y: ausp_acсel_0.data }); plot_1.add( { color: 0xcad714, name: "Спектр ускорения (канал 1)", x: 1/lines, y: ausp_acсel_1.data }); plot_2.add( { color: 0xff8800, name: "Спектр ускорения (канал 2)", x: 1/lines, y: ausp_acсel_2.data }); plot_3.add( { color: 0xff00f7, name: "Спектр силы (канал 3)", x: 1/lines, y: ausp_force_3.data }); plot_FreqResp_0_3.add( { color: 0xedc887, name: "Амплитуда частотный отклик (каналы 0 и 3)", x: 1/lines, y: freq_resp_0_3_ampl }); plot_FreqResp_0_3.add( { color: 0xedc887, name: "Фаза частотного отклика (каналы 0 и 3)", x: 1/lines, y: freq_resp_0_3_phase }); plot_FreqResp_1_3.add( { color: 0xedc887, name: "Амплитуда частотный отклик (каналы 1 и 3)", x: 1/lines, y: freq_resp_1_3_ampl }); plot_FreqResp_1_3.add( { color: 0xedc887, name: "Фаза частотного отклика (каналы 1 и 3)", x: 1/lines, y: freq_resp_1_3_phase }); plot_FreqResp_2_3.add( { color: 0xedc887, name: "Амплитуда частотный отклик (каналы 2 и 3)", x: 1/lines, y: freq_resp_2_3_ampl }); plot_FreqResp_2_3.add( { color: 0xedc887, name: "Фаза частотного отклика (каналы 2 и 3)", x: 1/lines, y: freq_resp_2_3_phase }); gtl.diagnostic.stop(); }