Привет всем!
Ко мне часто обращаются молодые инженеры с вопросом: «А зачем вообще идти в аспирантуру?» Я обычно рассказываю, какие плюсы и минусы есть у такого шага — как учёба прокачивает навыки, помогает упорядочить знания и научиться грамотно ставить эксперименты. Но выбор каждому нужно делать самому, стоит ли прокачивать такие навыки или нет.
И вот во время одного такого разговора, погрузившись в воспоминания о собственных научных делах, я случайно наткнулся в интернете на хакатон. И угадайте, по какой теме? По диагностике асинхронных электродвигателей — прямо в точку! Своего рода - мой незакрытый гештальт во время собственного обучения.
Решили с товарищем поучаствовать. Правда, мы были вдвоём, а в команде могло быть до 9 человек. Спойлер: мы не взяли первое место и даже не попали в шорт‑лист из 9 команд — заняли 16‑е место из 35.
Да, это не история про успех, а про опыт — тот самый, который, как известно, «сын ошибок трудных». Главный урок прост: да, быть экспертом и действовать в одиночку — это неплохо. Но настоящая суперсила — в команде!
А теперь — обо всём по порядку…

Постановка задачи и разработка приложений
Проект предполагал создание прототипа системы для диагностики асинхронных двигателей, интегрирующей технологии искусственного интеллекта и машинного обучения. Есть некий набор данных о потребляемом токе исследуемого электродвигателя, записанных с частотой дискретизации в 25,6 кГц. При этом двигатель явно получает питание от преобразователя частоты и наблюдается большое количество высокочастотных шумов. Но задачу это особо не усложняет.
Работа велась совместно с коллегой(уговорил его в последний день подачи заявок): я сосредоточился на разработке десктопного приложения на JavaFX — автоматизированного рабочего места (АРМ) диагноста. С десктопным приложением мне было (и есть) гораздо проще разобраться. Собрать прототип для анализа данных и диагностировать «пациентов» по потребляемому току – на все ушло пара вечеров. Затем, используя эту основу, мы совместно создали веб‑приложение(про него мы поговорим в следующий раз), которое позволяет проводить диагностику и автоматически рассчитывать индекс технического состояния за счёт встроенной нейронной сети.
Функционал приложения, обработка сигналов, датасеты и его величество – преобразование Фурье

Представьте себе «умный микроскоп» для электродвигателей — такая ассоциация приходит мне на ум про разработанное приложение. Напоминает АРМ диагноста или врача, сидишь и исследуешь результаты анализов. Разберём, как оно работает — шаг за шагом.
Шаг 1. Подготовка сигнала: убираем лишнее
Прежде чем анализировать сигнал, его нужно «причесать» — очистить от всего ненужного. Для этого мы:
Фильтруем. Применяем цифровой фильтр нижних частот (ФНЧ) с частотой среза 1 кГц — а если нужно, можем снизить ещё. Почему именно так? Дело в том, что большинство проблем двигателя (эксцентриситет ротора, межвитковые замыкания, износ подшипников) «проявляются» на низких частотах. Фильтр убирает высокочастотные помехи и шумы — они только мешают диагностике. Плюс снижается риск алиасинга при дальнейшей обработке.

Собственно, в этом диапазоне и кроются самые частые проблемы с механической частью – эксцентриситеты ротора, дефект подшипников и даже обрывы стержней беличьей клетки. Взвешиваем. К очищенному сигналу применяем «окно Хемминга» — это такой математический приём, чтобы сделать спектр более плавным. Он помогает:
избежать «размазывания» спектра при анализе (так называемой спектральной утечки);
точнее определить амплитуды разных частот;
убрать лишние «всплески» в спектре — так легче заметить слабые гармоники, которые могут говорить о зарождающихся дефектах.
В коде это выглядит следующим образом.
public double[] applyHammingWindow(double[] signal) { int N = signal.length; int Fs = 25600; // Частота дискретизации исходных датасетов int order = 4; // Порядок фильтра int cutOff = 1000; // Частота среза Butterworth flt = new Butterworth(Fs); double[] result = flt.lowPassFilter(signal, order, cutOff); double[] windowedSignal = new double[N]; Hamming w1 = new Hamming(N); double[] out = w1.getWindow(); for (int i = 0; i < N; i++) { windowedSignal[i] = result[i] * out[i]; } return windowedSignal; }
Шаг 2. Смотрим, как меняется ток во времени
Система рисует осциллограммы тока, при этом пользовать может:
приближать и отдалять картинку, чтобы рассмотреть любой участок подробнее;
анализировать длительные записи — даже если они идут часами.
Шаг 3. Вектор Парка: превращаем 3 фазы в наглядную картинку
Я добавил реализацию преобразования Кларка‑Парка (αβ→dq). Давно читал вот эту статью http://news.elteh.ru/arh/2008/49/10.php?ysclid=mn0jmaeyyv442788543 и подумал, что помимо самого спектра тока, неплохо бы добавить какой то альтернативный метод анализа. Что же делает преобразование?
берёт трёхфазные токи (Ia, Ib, Ic) и превращает их в двухфазную вращающуюся систему координат (Id, Iq);
рисует траекторию вектора тока на плоскости d-q — получается красивая и понятная картинка;
Шаг 4. Спектральный анализ: раскладываем сигнал на частоты
Дальше в дело вступает быстрое преобразование Фурье (БПФ / FFT). На выходе мы получаем следующее:
амплитудный и фазовый спектр исходного сигнала;
гармонические и субгармонические составляющие;
автоматически выделенные самые сильные гармоники и их амплитуды;
Шаг 5. Пакетная обработка: анализируем не один файл, а сразу много
Испытаний может быть очень много. Даже в тестовом датасете их было 40 штук. Не нужно загружать и анализировать файлы по одному! Поэтому система должна уметь:
принимать сразу пачку файлов (в том числе в формате CSV) за одну операцию;
применять одинаковые настройки ко всем наборам данных — например, один и тот же фильтр или тип окна;
сравнивать результаты между разными файлами прямо в одной сессии — удобно для отслеживания изменений во времени.
Шаг 6. Всё на одном экране: сравниваем и делаем выводы
Все результаты — осциллограммы, векторные диаграммы, спектры — выводятся на едином интерфейсе. Мне показалось это удобным, а главное позволяет:
видеть, как меняется состояние двигателя с течением времени(в зависимости от датасетов);
вовремя замечать появление новых гармоник — они могут указывать на развитие дефектов;
сопоставлять изменения в спектре с динамикой вектора Парка и получать полную картину происходящего.
А насколько это быстро?
Сразу скажу что некоторые решения пришлось пересматривать и оптимизировать под реальную работу:
Обработка CSV‑файлов. Файл размером 70 МБ анализируется за ≤2 с на обычной рабочей станции (процессор не ниже Intel Core i5, 16 ГБ ОЗУ). Вот здесь пришлось поэкспериментировать. Но эффективнее всего получилось использовать BufferedReader.
Графики в реальном времени. Меняете параметры (например, двигаете слайдер для выбора временного окна) — и графики обновляются почти мгновенно, с задержкой менее 100 мс. Такой отклик возможен благодаря многопоточной архитектуре: вычисления и визуализация идут параллельно, не мешая друг другу.
А знаете, что самое приятное? Разрабатывать такое было не так уж сложно — спасибо экосистеме Java! Библиотека JDSP (Java Digital Signal Processing, — https://jdsp.dev/) взяла на себя всю тяжёлую работу по обработке сигналов. В Java вообще полно крутых библиотек — с ними прототипы собираются как конструктор, и можно быстрее переходить от идеи к работающему решению.
Более подробно про интерфейсы
Мы коснулись алгоритмической и математической части, но стоит поговорить и о внешнем виде приложения. Для чего нужны все эти графики, настройки и куда именно нужно смотреть.

Итак, основные графики:
а) Временная область (верхний левый угол)
Отображает форму тока в зависимости от времени (ток, А по вертикали; время, с — по горизонтали).
Используется для анализа периодичности, искажений, выбросов в сигнале.
Загружен датасет
current_1.csv.
б) Амплитуда вектора Парка тока (верхний правый угол)
Показывает модулированный сигнал (вероятно, после преобразования Парка).
Помогает анализировать векторные характеристики тока.
в) Частотная область (FFT, нижний левый угол)
Спектрограмма, полученная с помощью быстрого преобразования Фурье (FFT).
Ось X — частота (Гц), ось Y — амплитуда.
Видны пиковые значения, указывающие на доминирующие частоты в сигнале.
Одним из ключевых элементов пользовательского интерфейса приложения является система интерактивных подсказок на графиках. В LineChart из коробки этого не предусмотрено, благо реализовать это не сложно.
public static void setupTooltip(XYChart.Data<Number, Number> data, String seriesName) { Circle circle = new Circle(2); circle.setOpacity(0.5); circle.setOnMouseEntered(event -> { Tooltip tooltip = new Tooltip( "Y: " + data.getYValue() + "\n" + "X: " + data.getXValue() + "\n" + seriesName ); tooltip.setShowDelay(Duration.ONE); Tooltip.install(circle, tooltip); }); data.setNode(circle); }
Я уже упомянул что испытаний может быть много. Чтобы оценить динамику в заболевании пациента, нужно их наложить друг на друга. Для этого можно вызвать отдельно окно. Что в нем можно увидеть:
Одновременно отображаются спектры нескольких датасетов (
current_1.csv,current_3.csvи т. д.).Каждый датасет окрашен в свой цвет для дифференциации.
Позволяет сравнивать спектры разных сигналов на одном графике.

Окно для пакетной обработки датасетов
Набор настроек получился минималистичным, но функциональным. Что можно поменять:
Отн. ед./дБ — выбор единицы измерения амплитуды (относительные единицы или децибелы).
Частота — установка диапазона частот для анализа (здесь — 100 Гц).
Спектр сигнала — выбор типа анализируемого сигнала («Ток фазы» или «модуль вектора Парка тока»).
Ну и немного украшательств в виде я тоже добавил:
Подсказки на графиках — при наведении курсора отображаются значения точек (время, амплитуда, частота и т. д.).
Легенда — в всплывающем окне указана связь цветов с конкретными CSV-файлами.
Ползунки и шкалы — для детального масштабирования графиков.
Кнопки управления (файл, редактировать, помощь) — для работы с данными и справки.
И, конечно, интерфейс доступен в двух темах оформления – темной и светлой. Это, пожалуй, самое легкое во всей разработке.

Вывод и очередной урок
Знаете, что самое интересное? Когда я был в аспирантуре, постоянно мучился с зарубежным ПО для экспериментов. То документация на английском какая-то запутанная, то программа виснет в самый неподходящий момент, то функций нужных не хватает. А спросить не у кого — приходится самому разбираться методом проб и ошибок. И ввязавшись первый раз в жизни в участие в хакатоне убедился, что все эти инженерные испытания преодолевались не зря.
Даже если место в соревновании не самое высокое — это нормально. В очередной раз решить задачку, созидать и даже отдохнуть от основной деятельности (а программирую я теперь очень редко) - куда важнее любого призового места.
Так что, если кто-то сейчас бьётся головой о какой-нибудь сложный софт — не отчаивайтесь. Это часть пути. Каждый такой опыт — это кирпичик в фундаменте вашего будущего профессионализма. И я уверен, именно эти трудности помогут вам создать что-то действительно крутое!
