"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"); var fnc = gtl.import("user-functions.js"); // Цвета (для справки) // #ff0000 - красный // #00ff00 - зелёный // #0000ff - синий // #00ddff - голубой // #ff3dcc - фиолетовый // #ffff00 - жёлтый // ***** БАЛАНСИРОВОЧНЫЙ КАЛЬКУЛЯТОР. ОДНА ПЛОСКОСТЬ БЕЗ ФАЗЫ ***** // **************************************************************** // Получение входных сигналов // Определение частоты вращения по параметру freq.dc var freq = gtl.add_value_freq(gtl.analog_inputs[record.tachoOptions.tachoChannel]); freq.time = 1; // длина отрезка сигнала freq.avg_cnt = 3; // усреднение freq.dc = -0.05; // уровень, при переходе через который считаются периоды // Настройки для спектров и АФЧХ var frequency = 1000; // граничная частота var resolution = 0.5; // частотное разрешение var average = 3; // количество усреднений var overlap = 0; // наложение // ФИЛЬТР 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 = frequency; // граничная частота спектра AUSPv.lines = AUSPv.frequency * 1/resolution; // разрешение спектра (количество линий) AUSPv.average = average; // количество усреднений AUSPv.unit = gtl.spec.unit; // отображение амплитуды в мм/с AUSPv.smoothing_factor = 100; // усреднение средней линии AUSPv.smoothed_line_color = 0xff004dff; // цвет средней линии AUSPv.peak_level = 0.001; // порог обнаружения гармоник (необходим самый минимальный) 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; // СКЗa var RMSa = gtl.add_value_rms(gtl.analog_inputs[signals[0].portNumber]); RMSa.time = 1; RMSa.avg_cnt = 3; // var idx = 1; // индекс канала вибрации (канал 0 - опорный) // var cnt = record.signalsModel.length; // количество каналов вибрации // Спектр виброскорости (новый метод) var AUSPv_pl = gtl.create_ausp( { "src" : filter_2_1000v, "frequency" : frequency, "resolution" : resolution, "average" : average, "overlap" : overlap, "window" : gtl.spec.rectangular, "view" : gtl.spec.unit } ); // Объявление графических плоскостей для построения графиков let plot_ausp = gtl.plots.add("Спектр виброскорости"); // создание объекта для спектра let plot_balance = gtl.plots.add("Расположение балансировочного груза"); // создание объекта для расположения балансировочного груза на плоскости // Переменные основные // параметр вибрации (модуль вектора) - виброскорость (мм/с) // угол (фаза) вектора - градусы // масса груза (модуль вектора) - граммы // DCI - Dynamic Coefficient of Influence (динамический коэффициент влияния) // * - значение получаем из измерительного блока при нажатии кнопки // ** - значение вводится пользователем // *** - значение получаем в результате расчёта программы балансировки // значение переменной с нижним подчёркиванием (..._) берётся из "дополнительных опций"; если оно не задано, то рассчитывается в скрипте let m_test_ = gtl.options.customOptions.m_test; // модуль вектора пробного груза ** let m_test; // модуль вектора пробного груза ** (конечное значение) let m_test_calc; // масса пробного груза расчётная *** let n = gtl.options.customOptions.n; // скорость вращения, об/мин ** (для вычисления массы пробного груза) let FREQ_0 = n / 60; // частота вращения, об/мин *** (для определения амплитуды оборотной гармоники) let R = gtl.options.customOptions.R; // радиус установки грузов ** (для вычисления массы пробного груза) let P = gtl.options.customOptions.P; // масса ротора, грамм ** (для вычисления массы пробного груза) let Mb; // масса балансировочного груза *** let Mb_corner; // угол установки балансировочного груза *** let Mdisb; // масса дисбаланса *** let Mdisb_corner; // угол расположения дисбаланса *** let A0_ = gtl.options.customOptions.A0; // модуль вектора начальной вибрации */** let A0; // модуль вектора начальной вибрации */** (конечное значение) let A1_ = gtl.options.customOptions.A1; // модуль вектора вибрации пробного пуска №1 */** let A1; // модуль вектора вибрации пробного пуска №1 */** (конечное значение) let A2_ = gtl.options.customOptions.A2; // модуль вектора вибрации пробного пуска №2 */** let A2; // модуль вектора вибрации пробного пуска №2 */** (конечное значение) let A3_ = gtl.options.customOptions.A3; // модуль вектора вибрации пробного пуска №3 */** let A3; // модуль вектора вибрации пробного пуска №3 */** (конечное значение) let A1_corner = 0; // угол установки груза пробного пуска №1 (фиксированный параметр, НЕ ИЗМЕНЯТЬ) let A2_corner = 120; // угол установки груза пробного пуска №2 (фиксированный параметр, НЕ ИЗМЕНЯТЬ) let A3_corner = 240; // угол установки груза пробного пуска №3 (фиксированный параметр, НЕ ИЗМЕНЯТЬ) // Переменные вспомогательные необходимые для расчётов var x00 = 0; // координата центра окружности нулевого пуска по оси X var y00 = 0; // координата центра окружности нулевого пуска по оси Y var x_b_0 = 0; // координата центра окружности расположения балансировочного груза по оси X var y_b_0 = 0; // координата центра окружности расположения балансировочного груза по оси Y // переменные для обозначения пересечения окружностей A1 и A2 var d12; // расстояние между центрами окружностей пробных пусков №1 и 2 var b1; // расстояние от центра окружности A1 до точки пересечения P11 с окружностью A2 var c1; // расстояние от центра окружности A2 до точки пересечения P11 с окружностью A1 // d12 = b1 + c1 var P11; // центральная точка между P21 и P_21 (_ обозначает штрих) var P21; // точка пересечения окружностей A1 и A2 var P_21; // точка пересечения окружностей A1 и A2 var h1; // расстояние от точки P11 до точки P21 и P_21 var P11_X; // координата точки P11 по оси X var P11_Y; // координата точки P11 по оси Y var P21_X; // координата точки P21 по оси X var P21_Y; // координата точки P21 по оси Y var P_21_X; // координата точки P_21 по оси X var P_21_Y; // координата точки P_21 по оси Y // переменные для обозначения пересечения окружностей A2 и A3 var d23; // расстояние между центрами окружностей пробных пусков №2 и 3 var b2; // расстояние от центра окружности A2 до точки пересечения P12 с окружностью A3 var c2; // расстояние от центра окружности A3 до точки пересечения P12 с окружностью A2 // d23 = b2 + c2 var P12; // центральная точка между P22 и P_22 (_ обозначает штрих) var P22; // точка пересечения окружностей A2 и A3 var P_22; // точка пересечения окружностей A2 и A3 var h2; // расстояние от точки P12 до точки P22 и P_22 var P12_X; // координата точки P12 по оси X var P12_Y; // координата точки P12 по оси Y var P22_X; // координата точки P22 по оси X var P22_Y; // координата точки P22 по оси Y var P_22_X; // координата точки P_22 по оси X var P_22_Y; // координата точки P_22 по оси Y // переменные для обозначения пересечения окружностей A3 и A1 var d31; // расстояние между центрами окружностей пробных пусков №3 и 1 var b3; // расстояние от центра окружности A3 до точки пересечения P12 с окружностью A1 var c3; // расстояние от центра окружности A1 до точки пересечения P12 с окружностью A3 // d31 = b3 + c3 var P13; // центральная точка между P23 и P_23 (_ обозначает штрих) var P23; // точка пересечения окружностей A3 и A1 var P_23; // точка пересечения окружностей A3 и A1 var h3; // расстояние от точки P13 до точки P23 и P_23 var P13_X; // координата точки P13 по оси X var P13_Y; // координата точки P13 по оси Y var P23_X; // координата точки P23 по оси X var P23_Y; // координата точки P23 по оси Y var P_23_X; // координата точки P_23 по оси X var P_23_Y; // координата точки P_23 по оси Y // точка пересечения окружностей var K; // точка пересечения окружностей A1, A2, A3 var K_X; // координата точки K по оси X var K_Y; // координата точки K по оси Y var OK; // длина отрезка от центра окружности A0 до точки пересечения окружностей всех пробных пусков // ***** РАСЧЁТЫ ***** // gtl.diagnostic.interval = 15; gtl.diagnostic.interval = Math.max(AUSPv.acq_time, AUSPv_pl.acq_time) + 0.1; 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 = Math.max(AUSPv.acq_time, AUSPv_pl.acq_time) + 0.1;; state = 3; break; case 1: // Частота вращения фиксированная // Определение минимально необходимой длительности сигнала для проведения диагностики gtl.diagnostic.interval = Math.max(AUSPv.acq_time, AUSPv_pl.acq_time) + 0.1; state = 3; break; case 2: // Частота вращения из поля INFO (виброметр) // Определение минимально необходимой длительности сигнала для проведения диагностики gtl.diagnostic.interval = Math.max(AUSPv.acq_time, AUSPv_pl.acq_time) + 0.1; state = 3; break; case 3: // Выполняем анализ спектов // Очистка партретов спектров AUSPv.clear_harms_sets(); let __AUSPv_tools = gtl.create_spec_tools( { data: AUSPv_pl.data, df: AUSPv_pl.resolution, base: { factor: 100, visible: true, color: 0x00ff00 }, peaks: { color: 0xff0000, visible: true, level: 0.000001 }, harms: { tolerance: 1 } }); let __row_AUSPv = __AUSPv_tools.harms.add(freq.value, 3, 0x0000ff, 1); // добавление набора гармоник (частота, количество, цвет, вес) __row_AUSPv.name = "F1v (гарм. ряд част. вращ.)"; // название гармонического ряда // __row1.modulate(5, 2, 0x00ff00, 1); // добавление амплитудной модуляции для набора гармоник (частота, количество, цвет, вес) plot_ausp.add( { color: 0x0000ff, name: "Спектр виброскорости", x: AUSPv_pl.resolution, y: AUSPv_pl.data, spec_tools: __AUSPv_tools.to_json() }); let __result1 = __AUSPv_tools.to_json(); // Амплитуда гармонического ряда частоты вращения var F1_1_a = __result1.harms.rows[0].harms[0].ampl; var F1_2_a = __result1.harms.rows[0].harms[1].ampl; var F1_3_a = __result1.harms.rows[0].harms[2].ampl; // Частота гармонического ряда частоты вращения var F1_1_f = __result1.harms.rows[0].harms[0].freq; var F1_2_f = __result1.harms.rows[0].harms[1].freq; var F1_3_f = __result1.harms.rows[0].harms[2].freq; // Проверка наличия оборотной гармоники и необходимости проведения балансировки var test_balance = ""; // переменная для текста о необходимости проведения балансировки if (F1_1_a >= RMSv_2_1000 * 0.4) // вклад оборотной гармоники в СКЗv {test_balance = "необходимо провести балансировку";} else {test_balance = "проведение балансировки не требуется или нецелесообразно";} // __result.data; - массив значений амплитуд составляющих спектра; // __result.base.data; - массив значений средней линии; // __result.peaks.data; - массив обнаруженных гармоник; // __result.peaks.data[i]; - обращение к i - й обнаруженной гармонике и ее свойствам; // freq - частота обнаруженной гармоники; // ampl - амплитудное значение обнаруженной гармоники; // level - уровень обнаруженной гармоники над средней линией; // index - индекс обнаруженной гармоники; // __result.harms.rows; - массив построенных гармонических рядов; // __result.harms.rows[i]; - обращение к i - му гармоническому ряду; // __result.harms.rows[i].harms; - массив гармоник i - го гармонического ряда; // __result.harms.rows[i].harms[j]; - обращение к j - й гармонике и ее свойствам i - го гармонического ряда; // freq - частота гармоники указанного гармонического ряда; // ampl - амплитудное значение гармоники указанного гармонического ряда; // base - уровень средней линии под гармоникой указанного гармонического ряда; // level - уровень гармоники над средней линией указанного гармонического ряда; // is_present(true / false) - обнаружение гармоники указанного гармонического ряда; // РАСЧЁТЫ (балансировочный калькулятор) // Определение конечных значений переменных // A0 начальная вибрация if (A0_ != 0) {A0 = A0_} // принимает значение из опций else {A0 = F1_1_a} // принимает значение из спектра сигнала // A1 вибрация после установки пробного груза в 0 градусов if (A1_ != 0) {A1 = A1_} // принимает значение из опций else {A1 = F1_1_a} // принимает значение из спектра сигнала // A2 вибрация после установки пробного груза в 120 градусов if (A2_ != 0) {A2 = A2_} // принимает значение из опций else {A2 = F1_1_a} // принимает значение из спектра сигнала // A3 вибрация после установки пробного груза в 240 градусов if (A3_ != 0) {A3 = A3_} // принимает значение из опций else {A3 = F1_1_a} // принимает значение из спектра сигнала // вычисление массы пробного груза (если не введено своё значение и есть данные для формулы) m_test_calc = 804 * ((P * A0) / (R * n)); // m_test масса пробного груза if (m_test_ != 0) {m_test = m_test_} // принимает значение из опций else {m_test = m_test_calc} // принимает значение из расчёта // 1) производится "нулевой пуск", записывается значение вибрации A0 // ...выбирается точка с максимальным значением вибрации, далее работаем только с этой точкой // определение координат точек окружности A0 var x0_array = []; // массив координат точек окружности A0 по оси X var y0_array = []; // массив координат точек окружности A0 по оси Y for (let i=0; i<=359; i++ ) { x0_array.push(x00 + A0 * (Math.sin((i) * Math.PI / 180))); y0_array.push(y00 + A0 * (Math.cos((i) * Math.PI / 180)));} //gtl.log.info("centr x00",x00); //gtl.log.info("centr y00",y00); // 2) выбирается масса пробного груза (записывается в граммах) // 3) на плоскости коррекции ротора (место установки грузов) отмечаются углы 0(360), 120 и 240 // ...увеличение угла против направления вращения ротора // 4) пробный груз по очереди устанавливается в 0(360), 120 и 240 градусов; измеряется вибрация (амплитуда записывается) // определение координат точек окружности A1 var x1_array = []; // массив координат точек окружности A1 по оси X var y1_array = []; // массив координат точек окружности A1 по оси Y var x01 = x0_array[0]; var y01 = y0_array[0]; for (let i=0; i<=359; i++ ) { x1_array.push(x01 + A1 * (Math.sin((i) * Math.PI / 180))); y1_array.push(y01 + A1 * (Math.cos((i) * Math.PI / 180)));} // определение координат точек окружности A2 var x2_array = []; // массив координат точек окружности A2 по оси X var y2_array = []; // массив координат точек окружности A2 по оси Y var x02 = x0_array[120]; var y02 = y0_array[120]; for (let i=0; i<=359; i++ ) { x2_array.push(x02 + A2 * (Math.sin((i) * Math.PI / 180))); y2_array.push(y02 + A2 * (Math.cos((i) * Math.PI / 180)));} // определение координат точек окружности A3 var x3_array = []; // массив координат точек окружности A3 по оси X var y3_array = []; // массив координат точек окружности A3 по оси Y var x03 = x0_array[240]; var y03 = y0_array[240]; for (let i=0; i<=359; i++ ) { x3_array.push(x03 + A3 * (Math.sin((i) * Math.PI / 180))); y3_array.push(y02 + A3 * (Math.cos((i) * Math.PI / 180)));} // определение вспомогательных переменных d12 = Math.sqrt(Math.pow(x02 - x01, 2) + Math.pow(y02 - y01, 2)); d23 = d12; d31 = d12; c1 = (Math.pow(A1,2) - Math.pow(A2,2) + Math.pow(d12,2)) / (2 * d12); b1 = d12 - c1; c2 = (Math.pow(A2,2) - Math.pow(A3,2) + Math.pow(d12,2)) / (2 * d12); b2 = d12 - c2; c3 = (Math.pow(A3,2) - Math.pow(A1,2) + Math.pow(d12,2)) / (2 * d12); b3 = d12 - c3; h1 = Math.sqrt(Math.pow(A1,2) - Math.pow(c1,2)); h2 = Math.sqrt(Math.pow(A2,2) - Math.pow(c2,2)); h3 = Math.sqrt(Math.pow(A3,2) - Math.pow(c3,2)); P11_X = x01 + ((c1 * (x02 - x01)) / d12); P11_Y = y01 + ((c1 * (y02 - y01)) / d12); P21_X = P11_X - ((h1 * (y02 - y01)) / d12); P21_Y = P11_Y + ((h1 * (x02 - x01)) / d12); P_21_X = P11_X + ((h1 * (y02 - y01)) / d12); P_21_Y = P11_Y - ((h1 * (x02 - x01)) / d12); P12_X = x02 + ((c2 * (x03 - x02)) / d12); P12_Y = y02 + ((c2 * (y03 - y02)) / d12); P22_X = P12_X - ((h2 * (y03 - y02)) / d12); P22_Y = P12_Y + ((h2 * (x03 - x02)) / d12); P_22_X = P12_X + ((h2 * (y03 - y02)) / d12); P_22_Y = P12_Y - ((h2 * (x03 - x02)) / d12); P13_X = x03 + ((c3 * (x01 - x03)) / d12); P13_Y = y03 + ((c3 * (y01 - y03)) / d12); P23_X = P13_X - ((h3 * (y01 - y03)) / d12); P23_Y = P13_Y + ((h3 * (x01 - x03)) / d12); P_23_X = P13_X + ((h3 * (y01 - y03)) / d12); P_23_Y = P13_Y - ((h3 * (x01 - x03)) / d12); K_X = (P_21_X + P_22_X + P_23_X) / 3; K_Y = (P_21_Y + P_22_Y + P_23_Y) / 3; OK = Math.sqrt(Math.pow(K_X,2) + Math.pow(K_Y,2)); // определение массы балансировочного груза Mb = (m_test * A0) / OK; // определение угла установки балансировочного груза if ((K_X > 0) && (K_Y >= 0)) { Mb_corner = (Math.acos(Math.abs(K_Y) / OK) * 180 ) / Math.PI} if ((K_X <= 0) && (K_Y < 0)) { Mb_corner = 180 + (Math.acos(Math.abs(K_Y) / OK) * 180 ) / Math.PI} if ((K_X < 0) && (K_Y >= 0)) { Mb_corner = 360 - (Math.acos(Math.abs(K_Y) / OK) * 180 ) / Math.PI} if ((K_X >= 0) && (K_Y < 0)) { Mb_corner = 180 - (Math.acos(Math.abs(K_Y) / OK) * 180 ) / Math.PI} // определение массы дисбаланса Mdisb = Mb; // равен массе балансировочного груза // определение угла расположения дисбаланса if ((Mb_corner + 180) > 360) { Mdisb_corner = (Mb_corner + 180) - 360} else if ((Mb_corner + 180) < 0) { Mdisb_corner = (Mb_corner + 180) + 360} else {Mdisb_corner = (Mb_corner + 180)} // определение координат точек окружности расположения балансировочного груза // в качестве радиуса окружности используется радиус балансировочной плоскости R let x_b_array = []; // массив координат точек окружности расположения балансировочного груза по оси X let y_b_array = []; // массив координат точек окружности расположения балансировочного груза по оси Y // for (let i=0; i<=359; i++ ) { // x_b_array.push(R * (Math.sin(i * Math.PI / 180))); // y_b_array.push(R * (Math.cos(i * Math.PI / 180)));} // x_b_array.push(x_b_0 + R * (Math.sin((i) * Math.PI / 180))); // y_b_array.push(y_b_0 + R * (Math.cos((i) * Math.PI / 180)));} for(let i = 0; i <= 359; i++) { x_b_array.push(A0*Math.sin(2*Math.PI/180*i)); y_b_array.push(A0*Math.cos(2*Math.PI/180*i)); } plot_balance.add( { color: 0x0000ff, name: "Расположение балансировочного груза", x: x_b_array, y: y_b_array, }); plot_balance.add( { color: 0x00ffffff, name: "границы", x: [-(A0+A0*0.1), -(A0+A0*0.1), (A0+A0*0.1), (A0+A0*0.1)], y: [(A0+A0*0.1), -(A0+A0*0.1), -(A0+A0*0.1), (A0+A0*0.1)] } ) gtl.log.info("x_b_array",x_b_array[1]); gtl.log.info("y_b_array",y_b_array[1]); gtl.log.info("Mb (балансировочный груз)",Mb); gtl.log.info("Mb_corner (угол установки груза)",Mb_corner); gtl.log.info("Mdisb (дисбаланс)",Mdisb); gtl.log.info("Mdisb_corner (угол расположения дисбаланса)",Mdisb_corner); gtl.log.info("m_test (пробный груз введёный)",m_test); gtl.log.info("m_test_calc (пробный груз расчётный)",m_test_calc); gtl.log.info("RMSv_2_1000",RMSv_2_1000.value); gtl.log.info("RMSa",RMSa.value); gtl.log.info("Необходимость проведения балансировки",test_balance); gtl.log.info("F1_3_a (ампл)",F1_3_a); gtl.log.info("F1_3_f (част)",F1_3_f); gtl.log.info("F1_2_a (ампл)",F1_2_a); gtl.log.info("F1_2_f (част)",F1_2_f); gtl.log.info("F1_1_a (ампл)",F1_1_a); gtl.log.info("F1_1_f (част)",F1_1_f); gtl.log.info("gtl.diagnostic.interval",gtl.diagnostic.interval); gtl.log.info("Частота вращения freq.value", freq.value); gtl.log.info("Нестабильность частоты вращения, %", instability*100); // Выдача результата (results) let __result3 = { Частота_вращения_F1: freq.value, Тестирование: test_balance, Ампл_гарм_1F1: F1_1_a, Примен_пробный_груз: m_test, Расч_пробный_груз: m_test_calc, Масса_баланс_груза: Mb, Угол_баланс_груза: Mb_corner, СКЗ_виброскор: RMSv_2_1000.value, Нестаб_част_вращ: instability*100 }; gtl.results = {"result_ausp": __result1, "result_общий": __result3}; gtl.diagnostic.stop(); break; default: break; } }