"use strict"; var signals = gtl.options.record.signalsModel; var options = gtl.options; var record = gtl.options.record; var point = gtl.options.point; // Файл импорта функций var imp = gtl.import("functions_for_balance.js"); // ***** БАЛАНСИРОВОЧНЫЙ КАЛЬКУЛЯТОР. ОДНА ПЛОСКОСТЬ с фазой ***** // *************************************************************** // Получение входных сигналов // ФИЛЬТР 2...1000 Гц, полосовой фильтр для СКЗ виброскорости и спектра var filter_2_1000 = gtl.add_filter_iir(gtl.analog_inputs[signals[0].portNumber]); filter_2_1000.kind = gtl.filter_iir.butterworth; filter_2_1000.type = gtl.filter_iir.bandpass; filter_2_1000.order = 6; filter_2_1000.frequency = 502; // центральная частота полосового фильтра filter_2_1000.width = 1000; // ширина полосы фильтра var filter_2_1000v = gtl.add_intg(filter_2_1000); // интегрирование filter_2_1000v.taps = 1; // степень интегрирования (скорость из ускорения - 1-нарное) // Спектр виброскорости для получения 1-й гармоники частоты вращения var AUSPv = gtl.add_ausp(filter_2_1000v); // объявление переменной спектра AUSPv.color = 0x00ff0000; // цвет спектра AUSPv.name = "AUSPv"; // имя спектра AUSPv.frequency = 1000; // граничная частота спектра AUSPv.lines = AUSPv.frequency * 4; // разрешение спектра (количество линий) AUSPv.average = 4; // количество усреднений AUSPv.unit = gtl.spec.unit; // отображение амплитуды в мм/с AUSPv.smoothing_factor = 100; // усреднение средней линии AUSPv.smoothed_line_color = 0xff004dff; // цвет средней линии AUSPv.peak_level = 0.000001; // порог обнаружения гармоник (необходим самый минимальный) AUSPv.tolerance = AUSPv.resolution; // диапазон поиска гармоник +/- // СКЗv var RMSv_2_1000 = gtl.add_value_rms(filter_2_1000v); RMSv_2_1000.time = 1; RMSv_2_1000.avg_cnt = 3; // Определение частоты вращения по параметру freq.dc var freq = gtl.add_value_freq(gtl.analog_inputs[signals[2].portNumber]); freq.time = 1; // длина отрезка сигнала freq.avg_cnt = 3; // усреднение freq.dc = -0.05; // уровень, при переходе через который считаются периоды // Фаза 1-й гармоники частоты вращения (виброскорости) // var delta_phase_F1v = gtl.add_delta_phase_spec(filter_2_1000v, filter_freq); // var delta_phase_F1v = gtl.add_delta_phase_spec(gtl.analog_inputs[0], filter_freq); // var delta_phase_F1v = gtl.add_delta_phase_spec(gtl.analog_inputs[0], gtl.analog_inputs[record.tachoOptions.tachoChannel]); var delta_phase_F1v = gtl.add_delta_phase_spec(filter_2_1000v, gtl.analog_inputs[signals[1].portNumber]); var freq_begin = 54.25; // предположительное значение частоты вращения var freq_round; // округлённая частота вращения для которой вычисляем фазу вибрации var frq_arr = [freq_begin, freq_round]; // массив частот для которых определяем фазу var i = 0; var res_delta_phase_F1v = {}; // объект результатов вычислений разности фаз delta_phase_F1v.max_frequency = AUSPv.frequency; delta_phase_F1v.resolution = AUSPv.resolution; delta_phase_F1v.frequency = frq_arr[0]; // частота, для которой вычисляется разница фаз, Гц // Объявление переменных массивов var level_AUSPv = []; // массив амплитуд гармоник канала 0 var delta_phase_AUSPv = []; // массив разностей фаз гармоник канала 0 относительно тахо var index_AUSPv = []; // массив индексов гармоник канала 0 var frequency_AUSPv = []; // массив частот (перевод индексов) гармоник канала 0 // Переменные основные // параметр вибрации (модуль вектора) - виброскорость (мм/с) // угол (фаза) вектора - градусы // масса груза (модуль ветора) - граммы // * - значение получаем из измерительного блока при нажатии кнопки // ** - значение вводится пользователем // *** - значение получаем в результате расчёта программы балансировки var A0=100; // модуль вектора начальной вибрации */** var A0_phase=30; // фаза вектора начальной вибрации */** var m_test=50; // модуль вектора пробного груза * var m_test_corner=100; // угол вектора пробного груза * var A1=75; // модуль вектора вибрации после установки пробного груза */** var A1_phase=120; // фаза вектора вибрации после установки пробного груза */** var dA; // модуль вектора дельты вибрации после установки пробного груза *** var dA_phase; // фаза вектора дельты вибрации после установки пробного груза *** var DCI; // модуль (мм/с/граммы) динамического коэффициента влияния (dinamic coefficient of influence) **/*** var DCI_phase; // фаза динамического коэффициента влияния **/*** var Mb; // модуль вектора балансировочного груза *** var Mb_corner; // угол вектора балансировочного груза *** var A2=1; // модуль вектора вибрации после установки балансировочного груза *** var A2_phase=21; // фаза вектора вибрации после установки балансировочного груза *** // Переменные вспомогательные var A0_phase_X; // угол наклона вектора A0 к оси X var A0_phase_Y; // угол наклона вектора A0 к оси Y var A0_1_X; // начальная координата вектора A0 по оси X var A0_2_X; // конечная координата вектора A0 по оси X var A0_1_Y; // начальная координата вектора A0 по оси Y var A0_2_Y; // конечная координата вектора A0 по оси Y var A1_phase_X; // угол наклона вектора A1 к оси X var A1_phase_Y; // угол наклона вектора A1 к оси Y var A1_1_X; // начальная координата вектора A1 по оси X var A1_2_X; // конечная координата вектора A1 по оси X var A1_1_Y; // начальная координата вектора A1 по оси Y var A1_2_Y; // конечная координата вектора A1 по оси Y var dA_1_X; // начальная координата вектора dA по оси X var dA_2_X; // конечная координата вектора dA по оси X var dA_1_Y; // начальная координата вектора dA по оси Y var dA_2_Y; // конечная координата вектора dA по оси Y var m_test_corner_X;// угол наклона вектора m_test к оси X var m_test_corner_Y;// угол наклона вектора m_test к оси Y var m_test_1_X; // начальная координата вектора m_test по оси X var m_test_2_X; // конечная координата вектора m_test по оси X var m_test_1_Y; // начальная координата вектора m_test по оси Y var m_test_2_Y; // конечная координата вектора m_test по оси Y // ***** РАСЧЁТЫ ***** // gtl.diagnostic.interval = 10; gtl.diagnostic.interval = Math.max(AUSPv.acq_time, delta_phase_F1v.acq_time); // gtl.diagnostic.interval = delta_phase_F1v.acq_time; //интервал запуска функции диагностики let state = record.tachoOptions.tachoState; // начальное состояние после выбора источника тахо сигнала function diagnose() { // Нестабильность частоты вращения var freq_max = Math.max(...freq.values); var freq_min = Math.min(...freq.values); var instability = ((freq_max - freq_min) / freq.value) * 100; // * 100% switch (state) { case 0: // считаем частоту вращения и настраиваем спектры var freq_max = Math.max(...freq.values); var freq_min = Math.min(...freq.values); var instability = (freq_max - freq_min) / freq.value; // if (instability > imp.tolerance()) { if (instability > 0.3) { gtl.log.info("Критическая нестабильность частоты вращения, %", instability * 100); gtl.log.info("Результат:", "Диагностика прервана"); //gtl.diagnostic.stop(); //принудительная остановка диагностики let __result = { Result: false }; gtl.results = __result; }; // Определение минимально необходимой длительности сигнала для проведения диагностики gtl.diagnostic.interval = AUSPv.acq_time; state = 3; break; case 1: // Частота вращения фиксированная // Определение минимально необходимой длительности сигнала для проведения диагностики gtl.diagnostic.interval = AUSPv.acq_time; state = 3; break; case 2: // Частота вращения из поля INFO (виброметр) // Определение минимально необходимой длительности сигнала для проведения диагностики gtl.diagnostic.interval = AUSPv.acq_time; state = 3; break; case 3: // Выполняем анализ спектов // Очистка партретов спектров AUSPv.clear_harms_sets(); // ТЕСТИРОВАНИЕ (получение фазы и амплитуды оборотной гармоники из массивов) // Запись в массив значений уровня спектра for (let i = 0; i < AUSPv.data.length; i++) { index_AUSPv.push(i); // индексы гармоник frequency_AUSPv.push(i * (AUSPv.frequency / AUSPv.lines)); // частоты гармоник level_AUSPv.push(AUSPv.data[i]); // уровень гармоник, если отображение амплитуд в спектре unit // level_AUSPv.push(AUSPv.data[i] - AUSPv.base[i]); // уровень гармоник, если отображение амплитуд в спектре db } var F_find = freq.value; // искомая частота var F_find_round_min = Math.round(F_find); // округление значения искомой частоты до ближайшего var F_find_round_max = Math.round(F_find) + AUSPv.resolution; // округление значения искомой частоты в большую сторону if (level_AUSPv[frequency_AUSPv.indexOf(F_find_round_min)] >= level_AUSPv[frequency_AUSPv.indexOf(F_find_round_max)]) {freq_round = F_find_round_min;} else {freq_round = F_find_round_max;} var ind_F_find = frequency_AUSPv.indexOf(freq_round); // индекс искомой частоты в общем спектре res_delta_phase_F1v[frq_arr[i]] = delta_phase_F1v.value; // записываем данные в объект if (i < frq_arr.length - 1) { i = i + 1; delta_phase_F1v.frequency = frq_arr[i]; } else { gtl.results = res_delta_phase_F1v; // записываем объект в резалт }; // Спектр виброскорости (для визуализации) // Набор гармоник частоты вращения F1v (виброскорость) var F1v_harms = AUSPv.add_harms_set(freq_round, 1, 0x000000ff, 1); // синий цвет for (let i=0; i <= 0; i++) {F1v_harms.harms[i].tolerance = (1+i) * freq_round * 0.1}; // коридор обнаружения гармоник F1v_harms.name = "F1v (гарм. ряд част. вращ.)"; // 1-я гармоника F1v var F1v = F1v_harms.harms[0].amplitude; // параметр amplitude при спектре в абсолютной величине амплитуды // var F1v = F1v_harms.harms[0].level; // параметр level при спектре в относительной величине амплитуды // Проверка наличия оборотной гармоники необходимости проведения балансировки if (F1v_harms.harms[0].is_present == true) // обнаружения оборотной гармоники {var F1v_test_ampl = "амплитуда частоты вращения определена";} else {var F1v_test_ampl = "амплитуда частоты вращения НЕ определена или имеет низкий уровень";} if (F1v >= RMSv_2_1000.value * 0.4) // вклад оборотной гармоники в СКЗv {var F1v_test_balance = "необходимо провести балансировку";} else {var F1v_test_balance = "проведение балансировки не требуется или нецелесообразно";} // РАСЧЁТЫ (балансировочный калькулятор) // определение угла наклона вектора A0 к осям X и Y if (A0_phase <= 90) { A0_phase_X = 90 - A0_phase} if (A0_phase <= 180) { A0_phase_X = A0_phase - 90} if (A0_phase <= 270) { A0_phase_X = 270 - A0_phase} if (A0_phase <= 360) { A0_phase_X = A0_phase - 270} if (A0_phase <= 90) { A0_phase_Y = A0_phase} if (A0_phase <= 180) { A0_phase_Y = 180 - A0_phase} if (A0_phase <= 270) { A0_phase_Y = A0_phase - 180} if (A0_phase <= 360) { A0_phase_Y = 360 - A0_phase} // определение координат вектора A0 A0_1_X = 0; if (A0_phase <= 180) {A0_2_X = Math.abs(Math.cos(A0_phase_X * 3.1415/180)) * A0 } else {A0_2_X = Math.abs(Math.cos(A0_phase_X * 3.1415/180)) * A0 * (-1)} A0_1_Y = 0; if (A0_phase <= 90 || A0_phase >= 270) {A0_2_Y = Math.abs(Math.cos(A0_phase_Y * 3.1415/180)) * A0 } else {A0_2_Y = Math.abs(Math.cos(A0_phase_Y * 3.1415/180)) * A0 * (-1)} // определение угла наклона вектора m_test к осям X и Y if (m_test_corner <= 90) { m_test_corner_X = 90 - m_test_corner} if (m_test_corner <= 180) { m_test_corner_X = m_test_corner - 90} if (m_test_corner <= 270) { m_test_corner_X = 270 - m_test_corner} if (m_test_corner <= 360) { m_test_corner_X = m_test_corner - 270} if (m_test_corner <= 90) { m_test_corner_Y = m_test_corner} if (m_test_corner <= 180) { m_test_corner_Y = 180 - m_test_corner} if (m_test_corner <= 270) { m_test_corner_Y = m_test_corner - 180} if (m_test_corner <= 360) { m_test_corner_Y = 360 - m_test_corner} // определение координат вектора m_test m_test_1_X = 0; if (m_test_corner <= 180) {m_test_2_X = Math.abs(Math.cos(m_test_corner_X * 3.1415/180)) * m_test * (-1) } else {m_test_2_X = Math.abs(Math.cos(m_test_corner_X * 3.1415/180)) * m_test} m_test_1_Y = 0; if (m_test_corner <= 90 || m_test_corner >= 270) {m_test_2_Y = Math.abs(Math.cos(m_test_corner_Y * 3.1415/180)) * m_test } else {m_test_2_Y = Math.abs(Math.cos(m_test_corner_Y * 3.1415/180)) * m_test * (-1)} // определение угла наклона вектора A1 к осям X и Y if (A1_phase <= 90) { A1_phase_X = 90 - A1_phase} if (A1_phase <= 180) { A1_phase_X = A1_phase - 90} if (A1_phase <= 270) { A1_phase_X = 270 - A1_phase} if (A1_phase <= 360) { A1_phase_X = A1_phase - 270} if (A1_phase <= 90) { A1_phase_Y = A1_phase} if (A1_phase <= 180) { A1_phase_Y = 180 - A1_phase} if (A1_phase <= 270) { A1_phase_Y = A1_phase - 180} if (A1_phase <= 360) { A1_phase_Y = 360 - A1_phase} // определение координат вектора A1 A1_1_X = 0; if (A1_phase <= 180) {A1_2_X = Math.abs(Math.cos(A1_phase_X * 3.1415/180)) * A1 } else {A1_2_X = Math.abs(Math.cos(A1_phase_X * 3.1415/180)) * A1 * (-1)} A1_1_Y = 0; if (A1_phase <= 90 || A1_phase >= 270) {A1_2_Y = Math.abs(Math.cos(A1_phase_Y * 3.1415/180)) * A1 } else {A1_2_Y = Math.abs(Math.cos(A1_phase_Y * 3.1415/180)) * A1 * (-1)} // определение модуля вектора dA dA_1_X = A0_2_X; dA_2_X = A1_2_X; dA_1_Y = A0_2_Y; dA_2_Y = A1_2_Y; dA = Math.sqrt(Math.pow(dA_2_X - dA_1_X, 2) + Math.pow(dA_2_Y - dA_1_Y, 2)) // определение фазы вектора dA if ((dA_2_Y < dA_1_Y) && (dA_2_X < dA_1_X)) { dA_phase = 180 + (((Math.acos((Math.abs(dA_2_Y - dA_1_Y)) / dA)) * 180 ) / 3.1415)} if ((dA_2_Y > dA_1_Y) && (dA_2_X > dA_1_X)) { dA_phase = (((Math.acos((Math.abs(dA_2_Y - dA_1_Y)) / dA)) * 180 ) / 3.1415)} if ((dA_2_Y > dA_1_Y) && (dA_2_X < dA_1_X)) { dA_phase = 360 - (((Math.acos((Math.abs(dA_2_Y - dA_1_Y)) / dA)) * 180 ) / 3.1415)} if ((dA_2_Y < dA_1_Y) && (dA_2_X > dA_1_X)) { dA_phase = 180 - (((Math.acos((Math.abs(dA_2_Y - dA_1_Y)) / dA)) * 180 ) / 3.1415)} if (dA_phase > 360) {dA_phase = dA_phase - 360} // определение модуля вектора DCI DCI = dA / m_test; // опредение фаза вектора DCI DCI_phase = dA_phase - m_test_corner; // определение модуля вектора Mb Mb = (m_test * A0) / dA; // определение модуля вектора Mb по известному ДКВ (DCI) ** //Mb = A0 / DCI; // определение угла вектора Mb if ((m_test_corner + A0_phase - dA_phase + 180) < 360) { Mb_corner = (m_test_corner + A0_phase - dA_phase + 180) } else {Mb_corner = (m_test_corner + A0_phase - dA_phase + 180) - 360} // определение угла вектора Mb по известному ДКВ (DCI) //if ((A0_phase - DCI_phase + 180) < 360) { // Mb_corner = (A0_phase - DCI_phase + 180) // } else {Mb_corner = (A0_phase - DCI_phase + 180) - 360} gtl.log.info("Индекс", i); gtl.log.info("Частота", frq_arr[i]); gtl.log.info("Разница фаз на частоте", delta_phase_F1v.value); gtl.log.info("искомая частота, Гц", F_find); gtl.log.info("искомая частота округлённая до ближ, Гц", freq_round); // gtl.log.info("верхняя граница поиска частоты, Гц", F_find_round_max); // gtl.log.info("нижняя граница поиска частоты, Гц", F_find_round_min); gtl.log.info("индекс искомой частоты в общем спектре", ind_F_find); gtl.log.info("уровень искомой частоты (data)", level_AUSPv[ind_F_find]); // gtl.log.info("Mb",Mb); // gtl.log.info("Mb_corner",Mb_corner); // gtl.log.info("freq.value (по dc)",freq.value); gtl.log.info("F1v.level (гарм.ряд)",F1v); gtl.log.info("RMSv_2_1000",RMSv_2_1000.value); // gtl.log.info("F1v_test_ampl",F1v_test_ampl); // gtl.log.info("F1v_test_balance",F1v_test_balance); // gtl.log.info("F1v_harms.harms[0].tolerance",F1v_harms.harms[0].tolerance); // gtl.log.info("delta_phase_F1v",delta_phase_F1v.value); gtl.log.info("gtl.diagnostic.interval",gtl.diagnostic.interval); // gtl.log.info("delta_phase_F1v.acq_time",delta_phase_F1v.acq_time); // gtl.log.info("AUSPv.acq_time",AUSPv.acq_time); // Выдача результата (results) let __result = { Частота_вращения_F1_округл: freq_round, Канал_вибрации_датчика1: "канал [0]", Амплитуда_гармоники_F1: level_AUSPv[ind_F_find], амплитуда_F1v_поСпектру: F1v, дельта_фаза: delta_phase_F1v.value, phase_res: res_delta_phase_F1v, }; gtl.results = __result; gtl.diagnostic.stop(); } }