В предыдущей статье мы рассмотрели применение платы Arduino Due для измерения сигналов вибрации при балансировке роторов.
Поскольку процесс измерения в этом случае должен быть синхронизирован с частотой вращения ротора, мы использовали "адаптивную" частоту дискретизации, то есть частота дискретизации рассчитывается таким образом, чтобы на периоде выборки укладывалось заданное число оборотов ротора. Исходя из объема памяти данных платы Arduino Due объем выборки составил 8192 отсчета 2 байта*4 (исторически сложилось) канала.
При этом период дискретизации (требуемое время между отсчетами АЦП) может быть гораздо больше, чем время преобразования АЦП, то есть АЦП может брать отсчеты гораздо чаще, чем нам требуется, исходя из нашей задачи. Поэтому становится возможным применить  oversampling (оверсэмплинг) для повышения разрешения и улучшения соотношения сигнал/шум

Типичный вид сигнала вибрации обусловленной дисбалансом. Синие импульсы - оборотные метки, красный, зеленый - сигнал с датчиков вибрации
Типичный вид сигнала вибрации обусловленной дисбалансом. Синие импульсы - оборотные метки, красный, зеленый - сигнал с датчиков вибрации

В чем смысл оверсэмплинга?

Поскольку АЦП может брать отсчеты гораздо чаще, чем требуется, можно в промежутках между основными отсчетами брать еще несколько дополнительных и суммировать их.
Что это дает? 
Пусть например  шаг квантования (одна ступенька ) АЦП соответствует  0.1 вольта (после пересчета ступенек АЦП в напряжение). 

Пусть например  шаг квантования (одна ступенька ) АЦП соответствует  0.1 вольта (после пересчета ступенек АЦП в напряжение). 
То есть сигнал может измеряться с дискретностью 0.1 вольта ( 0.1 или 0.2 и так далее)  
На рисунке выше видно, что после каждого основного отсчета мы берем 6 дополнительных, и часть этих отсчетов может быть выше 2-ой ступеньки АЦП (0.2 В), а часть ниже (0.1 В).
Если допустим в заданный момент времени  t0  АЦП делает 1 основной + 6 дополнительных отсчетов, из которых 3 (синие) пересекают уровень квантования (допустим 0.2 - 2 ступенька) , а 4 (оранжевые) - нет (0,1 В), то при последующем усреднении в величину с плавающей точкой мы получим величину (4*0.1 + 3*0.2)/7=0.14 В
То есть для отсчета привязанного к  моменту времени t0 мы получили величину 0.14 В  вместо 0.1 В.  Таким образом разрешение по амплитуде улучшилось. Насколько улучшается разрешение в данном случае зависит от характера измеряемого сигнала. Если измеряется постоянное напряжение, то простое увеличение числа отсчетов ничего не даст, поскольку дополнительные отсчеты не будут отличаться друг от друга и последующее усреднение даст туже величину, что и одиночный отсчет.

Для того, чтобы увеличить разрешение при измерении постоянного сигнала, необходимо, чтобы этот сигнал содержал шум, некоррелированный с основным сигналом.

Шум заставляет сигнал колебаться относительно среднего уровня. При этом сигнал может пересечь уровень срабатывания (квантования) АЦП или нет. Если в заданный момент времени АЦП делает 10 замеров, из которых 7 пересекают уровень квантования (допустим 4) , а 3 - нет, то при последующем усреднении в величину с плавающей точкой мы получим величину (3*3 + 4*7)\10=3.7

На рисунке представлен сигнал (красная линия) с шумовой составляющей (две синие линии, ограничивающие величину шума). Красные точки - основные отсчеты АЦП. Мы берем несколько дополнительных отсчетов, которые вследствие шума случайным образом могут оказаться в области А1 или А2 (желтые и голубые точки). Вероятность того, в какую область попадет отсчет пропорциональна площади области (оранжевой или фиолетовой на рисунке)
Области А1 и А2 на вид примерно равны по площади, поэтому допустим 3 отсчета попадут в область А1 (выше  порога 0.2) и 4 отсчета (включая основной) попадут в область А2 (выше  порога 0.1). Тогда после усреднения получим величину 3*0.2+4*0.1=0.6+0.4=1.0/7=0.14 В
Таким образом мы измерили наш сигнал с более высоким разрешением.
При этом также улучшается отношение сигнал\шум, поскольку фактически мы усреднили наш сигнал. Суммирование N отсчетов некоррелированного шума  увеличивает его амплитуду в √(N) раз, а суммирование когерентного сигнала увеличивает его величину в N раз, что улучшает соотношение сигнал/шум в √(N).

Особенности реализации оверсемплинга при измерении сигнала с помощью платы Arduino Due.

Диапазон измеряемого напряжения  АЦП платы Arduino Due  — от 0 до 3,3 В. Нулевой уровень таким образом поднят на 1.65 вольта и соответствует 2048 ступенек АЦП (для 12 разрядов).
Мы сохраняем 12 разрядный отсчет АЦП в массив беззнаковых переменных типа  uint16_t - максимальная величина которого 65535. Таким образом мы можем просуммировать максимум 65535\2048= 32 раза для сигнала нулевой величины. Если конечно не начать исхитряться )

Наш сигнал может выглядеть так.

Или так

Пусть наш сигнал меняется в диапазоне от min до max. Тогда максимальное количество дополнительных отсчетов oversN, которые мы можем взять не должно превышать  65536/max, иначе мы вылезем за разрядную сетку.
Однако мы можем вычесть из каждого отсчета величину min, так чтобы минимум сигнала стал равен нулю, то есть "сдвинуть" наш сигнал вниз на величину min.
Максимум сигнала при этом станет max-min.
Тогда максимальное число доп. отсчетов для оверсемплинга  станет равным oversN=65536/(max-min)

Нам придется проводить измерения два раза - сначала для определения максимального и минимального значения сигнала а затем "рабочее" измерение.

// предварительно находим максимальное и минимальное значение сигнала
		maxSignal1=0; minSignal1=65535;
		maxSignal2=0; minSignal2=65535;
	
		for ( MNpt = 0; MNpt <1024  ; MNpt++) //  для экономии времени берем только 1024 отсчета, а не 8192
			Usr1=analogRead(A0); if (Usr1>maxSignal1)  maxSignal1=Usr1; if (Usr1<minSignal1)  minSignal1=Usr1;
			Usr2=analogRead(A1); if (Usr2>maxSignal2)  maxSignal2=Usr2; if (Usr2<minSignal2)  minSignal2=Usr2;
		}

Это все конечно работает для  стационарного сигнала, амплитуда которого постоянна в течение измерения. Если же в сигнале будут присутствовать какие-нибудь "выбросы", которые мы пропустим при предварительном измерении минимума и максимума сигнала, то возможно переполнение 16-разрядной величины и искажение сигнала. С другой стороны, применять оверсемплинг целесообразно только для малых сигналов, когда его величина не превышает несколько десятков ступенек АЦП. В этом случае вероятность переполнения будет минимальной. Хотя все зависит от характера сигнала.

Второй ограничивающий момент - это конечный период дискретизации Тдискр. - период времени между соседними отсчетами. 

На рисунке выше это время например между t1 и t0,  Тдискр = t1- t0.
Хотя дополнительные отсчеты мы берем с максимальной частотой АЦП,  все равно за время между t1 и t0 мы сможем получить только ограниченное количество отсчетов.
В нашем случае это время  (период дискретизации Тдискр= t1- t0) привязано к частоте вращения ротора (см.https://habr.com/ru/articles/1028062 ) и может меняться в широких пределах.  В некоторых режимах время минимально  Тдискр=15 мкс (АЦП берет отсчеты с максимальной частотой), и в этом случае взять дополнительные отсчеты и  применить оверсемплинг мы не сможем. 
Время преобразования АЦП Arduino Due составляет 5 мкс. У нас три канала поэтому суммарное время на получение одного "кадра" составляет 5 мкс*3=15 мкс.
Реальное время между "кадрами" (частота дискретизации) у нас привязано к параметрам сигнала и  обычно оно больше 15 мкс, так что мы можем "вставить" в этот промежуток сколько-то дополнительных отсчетов. 
Как уже было сказано в предыдущей статье объем собираемых данных у нас всегда 8192 отсчета 4 канала* 2 байта=65536 байт
Пользователь задает количество отсчетов приходящееся на 1 период сигнала (оборот вала) Npob. Период сигнала мы предварительно измеряем как время между оборотными метками (импульсами с тахометра) которые подаем на цифровой пин, к которому привязано прерывание, например, по спаду импульса.

Tob = timeM2 - timeM1; //время между метками оборотов
Время измерения расчитывается как 
Tizm = Tob * (NPnt/ NPOb)   ; // время измерения, мкс, где
Tob - период одного оборота
NPnt - число отсчетов, всегда 8192
NPOb - число отсчетов на одном обороте, задается пользователем, как степень 2.
Исходя из этих данных рассчитываем период дискретизации 
Nzad = Tizm / NPnt; //время задержки между отсчетами, мкс
Если Nzad > 15 мкс, то мы можем добавить дополнительные отсчеты

Находим максимальное количество доп. отсчетов, исходя из периода дискретизации Nzad
overs1=(Nzad-15)/10; //  доп. отсчеты 2 кан х 5мкс=10 мкс
где
Nzad-15 - "свободное" время между основными отсчетами в которое, мы можем вставить дополнительные отсчеты.
15 мкс - это время за которое АЦП берет 2 основных отсчета + 1 отсчет с тахометра (3*5 мкс)
10 мкс - время за которое АЦП берет дополнительные отсчеты по двум каналам вибросигнала.
Дальше мы выбираем меньше число
if (overs1> Usr1) overs1= Usr1;

Используя полученные параметры проводим цикл измерений

// рабочее измерение (в цикле 8192 раз)

SummP[j + 0] = ( analogRead(A0)); //Основной отсчет  1 канал в массив SummP[j]
// дополнительные отсчеты
for (int g = 0; g < overs1 ; g++) // накапливаем отсчеты для оверсемплинга, вычитая при этом минимальное значение сигнала
{
SummP[j + 0] =SummP[j + 0]+ ( analogRead(A0)-minSignal); 
}

где SummP = new uint16_t[8192 * 4]; /..беззнаковый массив 16-разрядных значений
minSignal - заранее определенное минимальное значение сигнала
Далее передаем данные в ПК
SerialUSB.write((uint8_t )SummP, NPnt 8); //NPnt отсчетов по 4 измерения по 2 байта - один отсчет пустой по историческим причинам.

Далее в ПК принимаем данные в массив Word 
Z2000: array of Word;   //  0 ... 65535
Разбираем данные по каналам, вычисляем величину вибрации и делим на число отсчетов Overs1
 VXo := VX/Overs1;

Пример измерения малого сигнала с оверсемплингом и без.

Измерение сигнала без оверсемплинга
Измерение сигнала без оверсемплинга
Измерение того же сигнала с оверсемплингом.
Измерение того же сигнала с оверсемплингом.

Фактически применение оверсемплинга эквивалентно апраратному усилению сигнала. Причем это не потребовало внесения изменений в аппаратную часть, мы просто бесплатно программным образом задействовали имеющиеся резервы, что позволило в 3-5 раз улучшить качество балансировки.

Комментарии (4)


  1. ValeriyS
    21.07.2026 14:28

    Хорошая статья — объяснение оверсэмплинга ясное, а таблица результатов уже показывает, что метод работает: остаточный дисбаланс после триммирующего пуска (0,013 и 0,05 мм/с) — отличный результат. Ниже — как выжать из этого больше средствами цифровой обработки, оставаясь в рамках возможностей платы Due (96 КБ SRAM, Cortex‑M3 без аппаратного FPU) и вашего ПК‑приложения.

    Смена ракурса

    Для балансировки вам, по сути, не нужно высокое разрешение формы сигнала по всей записи — вам нужно одно комплексное число на плоскость: амплитуда и фаза вибрации точно на 1‑й оборотной гармонике (1×), плюс, возможно, 2×, 3× для диагностики. Это задача узкополосной оценки, а у узкополосной оценки рычаги мощнее, чем у пословного повышения разрешения.

    1. Когерентное выделение — ваш главный рычаг (вероятно, сильнее самого оверсэмплинга)

    Поскольку вы ведёте порядковый анализ (в каждую запись из 8192 отсчётов укладывается целое число оборотов), составляющая 1× попадает точно на бин ДПФ (спектральный отсчёт) без растекания спектра. Если вычислить только этот бин алгоритмом Гёрцеля — или, что эквивалентно, программным синхронным детектором (умножение на cos/sin от привязанной к тахометру фазы и накопление, чтобы получить квадратуры I/Q) — вы сразу получаете амплитуду и фазу. При этом когерентный выигрыш растёт как √N относительно случайного шума (√8192 ≈ 90×). Заодно подавляется всё, что не лежит на целом порядке (асинхронная вибрация, шум подшипников и т. п.).

    Полезно знать: такое суммирование одного бина по всей записи математически тождественно синхронному усреднению во временно́й области. Если сгруппировать запись по «номеру отсчёта внутри оборота», то бин порядка k равен R × (ДПФ от усреднённого оборота). То есть «усреднить все обороты в угловой области» и «прочитать точный бин порядка» — это одна и та же операция. Скорее всего, вы уже получаете большую часть этого выигрыша из пика вашего БПФ; уточнение сводится к тому, чтобы:

    • (а) запись охватывала целое число оборотов;

    • (б) использовать прямоугольное окно, когда вы действительно привязаны к порядку (окно Ханна размыло бы энергию и съело часть когерентного выигрыша — добавляйте его только как страховку от ухода частоты вращения);

    • (в) читать именно бин нужного порядка, а не локальный максимум.

    Оверсэмплинг тогда ложится поверх этого как меньший, вторичный выигрыш.

    2. Убедитесь, что выигрыш оверсэмплинга реален — проверьте наличие дизера

    Оверсэмплинг повышает разрешение только при наличии некоррелированного шума величиной ≥ ~1 ступеньки АЦП (LSB) на дополнительных отсчётах (вы сами отмечаете это для постоянного сигнала). Вибрация поверх шума датчика/усилителя обычно это условие выполняет, но очень «тихий» канал (малый сигнал, низкий шум) выдаст идентичные доп. отсчёты и не даст ничего — туда стоит подмешать ~1–2 ступеньки дизера (шум с треугольным распределением, TPDF).

    Заявленное вами улучшение в 3–5 раз согласуется с ~+2,5 битами разрешения (32× ≈ 4^2.5 ≈ 5,6×), так что цифры сходятся. А ваш приём с вычитанием minSignal, чтобы остаться в пределах uint16_t, — правильное решение с учётом лимита ОЗУ: 32‑битный аккумулятор удвоил бы 64 КБ → 128 КБ и не влез бы в 96 КБ.

    3. Следите за фазовой задержкой от окна усреднения

    Суммирование overs1 отсчётов сразу после основного — это фильтр «скользящее прямоугольное окно» (boxcar), который вносит групповую задержку τ ≈ overs1 × 5 мкс. Для обоих виброканалов она одинакова, поэтому относительная фаза между плоскостями сохраняется. Но overs1 зависит от Nzad, а Nzad — от частоты вращения, и ваши пуски идут на разных оборотах (2007 / 1801 / 1687 / 2159 об/мин). Значит, фазовый сдвиг относительно тахометра отличается от пуска к пуску, и это вносит небольшую систематическую погрешность в коэффициенты влияния.

    При 2000 об/мин и overs1 ≈ 10 это ~0,6°, меняясь от нескольких десятых до ~1° между пусками — мало, но вы работаете на точности, где это уже способно сказаться. Дешёвое исправление на стороне ПК: повернуть 1×‑вектор каждого пуска на e^{+j2πfτ}, используя собственное τ этого пуска.

    4. Форма фильтра (второстепенно)

    Прямоугольное окно — слабый антиалиасинговый / децимирующий фильтр. Для низких порядков (1×–3×) этого достаточно; переходить на короткий CIC/КИХ‑дециматор имеет смысл, только если начнёте интересоваться высшими гармониками или подавлением наложения спектров.

    5. Порядковый трекинг внутри записи

    Ваша адаптивная дискретизация это уже обеспечивает. Если частота вращения «плывёт» внутри одной записи, передискретизация по углу на ПК перед ДПФ удержит порядок точно на бине и подтянет и амплитуду, и фазу.


    1. diakin Автор
      21.07.2026 14:28

      Спасибо за развернутый комментарий!
      Да, основную роль играет синхронное накопление по оборотам, оверсэмплинг здесь как бесплатное дополнение :-). Оверсэмплинг помогает, когда сигнал слабый и составляет несколько ступенек АЦП, в какой-то степени он заменяет аппаратное усиление сигнала.
      Чтобы не было растекания спектра, когда частота вращения гуляет, применена передискретизация, чтобы на каждый оборот приходилось заданное число отсчетов (в степени 2). При этом даже если частота вращения гуляет, но АЧХ системы практически горизонтальна в диапазоне гуляния ( мы далеко от резонанса), то амплитуда и фаза будут меняться незначительно. При этом составляющая 1× попадает точно на бин. Приятно глазу! )

      • (а) запись охватывала целое число оборотов;

      • (б) использовать прямоугольное окно, когда вы действительно привязаны к порядку (окно Ханна размыло бы энергию и съело часть когерентного выигрыша — добавляйте его только как страховку от ухода частоты вращения);

      Да, так это и реализовано. Запись охватывает целое число оборотов - потом при обработке обрезается по оборотным меткам и передискретизируется в степени 2. И по факту используется прямоугольное окно.

      туда стоит подмешать ~1–2 ступеньки дизера (шум с треугольным распределением, TPDF).

      Это аппаратно подмешивать? Это надо влезать в плату?

      При 2000 об/мин и overs1 ≈ 10 это ~0,6°, меняясь от нескольких десятых до ~1° между пусками

      В конечном-то итоге это выливается в погрешность угла установки корректирующих грузов, а там погрешность в 1 градус нивелируется невозможностью так точно установить груз. Я так понимаю.


  1. VT100
    21.07.2026 14:28

    Предлагается сузить динамический диапазон на входе (естественно - ухудшив С/Ш), чтобы потом нагнать разрядность математикой. Я правильно понял? Почему бы просто не ограничить oversN до 16?
    Будет ли статья о том, как съэкономить на входном фильтре (anti-aliasing) с помощью передискретизации?


    1. diakin Автор
      21.07.2026 14:28

      В смысле "сузить динамический диапазон на входе" ? Нет, речь идет о том, что при маленьких сигналах (несколько ступенек АЦП) делать не один отсчет, а несколько (сколько сможем из-за ограничений) и потом их просуммировать (усреднить). Чем больше таких отсчетов мы сможем взять, тем лучше получится разрешение. Поэтому наоборот, oversN желательно брать по максимуму.
      Ну и да, это будет способом сэкономить на антиалиасинговом фильтре, поскольку ВЧ сигнал (помеха) как-то усреднится и не пролезет в НЧ область спектра.