Как измерить фазовый угол между напряжением и током с помощью Arduino

Когда ты работаешь с цепями переменного тока — например, подключаешь трансформатор, двигатель или хочешь посчитать реактивную мощность — возникает необходимость узнать, насколько ток «отстаёт» от напряжения. Разница между ними и есть фазовый угол. Измерить его осциллографом — полдела, но если у тебя под рукой Arduino, можно собрать компактный измеритель, который будет выдавать результат в реальном времени прямо в монитор порта.

Разберёмся, как это сделать без лишней теории, с конкретной схемой, кодом и пониманием, что может пойти не так.

Что на самом деле мы измеряем

В идеальном резистивном чайнике напряжение и ток совпадают по фазе — угол равен нулю. Но если в цепи есть катушка индуктивности или конденсатор, ток начинает «сдвигаться» относительно напряжения. Этот сдвиг выражается в градусах (или радианах) и напрямую влияет на коэффициент мощности — cos φ.

Arduino не умеет напрямую работать с переменным напряжением сети. Поэтому наша задача — безопасно и точно привести оба сигнала (напряжение и ток) к уровню, который может оцифровать аналоговый вход Arduino (0–5 В или 0–3.3 В), а затем программно определить разницу во времени между переходами сигналов через ноль.

Что понадобится

Вот минимальный набор компонентов для сборки измерителя фазового угла на Arduino:

  • Arduino (Uno, Nano, Mega — подойдёт любая с аналоговым входом)
  • Трансформатор напряжения (220 В → 6–12 В, любой маломощный)
  • Трансформатор тока (например, SCT-013-005 или аналогичный)
  • Два резистора для делителя напряжения (100 кОм и 10 кОм)
  • Два резистора для смещения сигнала (10 кОм)
  • Два стабилитона на 4.7 В (защита входа Arduino)
  • Конденсатор электролитический 10 мкФ
  • Конденсатор керамический 100 нФ
  • Соединительные провода, макетная плата

Подготовка сигналов: напряжение

Трансформатор напряжения понижает сетевое напряжение до безопасного уровня — скажем, до 12 В переменного. Но Arduino не может считывать отрицательные значения, поэтому сигнал нужно сместить в положительную область.

Схема простая: выход трансформатора подключается через делитель напряжения (100 кОм + 10 кОм), который снижает амплитуду примерно в 11 раз. Затем через разделительный конденсатор (100 нФ) сигнал поступает на среднюю точку между двумя резисторами по 10 кОм, подключёнными к земле и к опорному напряжению 2.5 В (получаем делением 5 В пополам через два одинаковых резистора). Получаем сигнал, который колеблется вокруг 2.5 В — идеально для аналогового входа.

Параллельно входу ставим стабилитрон на 4.7 В, чтобы случайный выброс не сжёг пин Arduino.

Подготовка сигналов: ток

Трансформатор тока (ТТ) выдаёт напряжение пропорциональное току в цепи. Если у тебя ТТ с встроенным нагрузочным резистором (burden resistor), то сигнал уже готов. Если нет — нужно подключить внешний резистор (обычно 33–100 Ом в зависимости от модели).

Дальше — та же схема смещения: резистивный делитель, конденсатор для подавления постоянной составляющей, стабилитрон для защиты. Важно, чтобы оба канала (напряжение и ток) были согласованы по амплитуде и фазе — иначе измерения будут врать.

Программная часть: определяем переход через ноль

Самый надёжный способ измерить фазовый угол с Arduino — засечь моменты, когда оба сигнала пересекают средний уровень (2.5 В при 5 В питании), и посчитать разницу во времени между этими событиями.

Вот упрощённый алгоритм работы:

  1. Настраиваем два аналоговых входа (A0 — напряжение, A1 — ток).
  2. В цикле опрашиваем оба входа с частотой не менее 10 кГц (для 50 Гц сети это даёт около 200 точек на период — достаточно).
  3. Фиксируем момент, когда сигнал на A0 переходит через порог 2.5 В снизу вверх (это «восходящий фронт»).
  4. Запоминаем время по миллисекундам или микросекундам.
  5. Аналогично фиксируем восходящий фронт на A1.
  6. Считаем разницу во времени между двумя фронтами.
  7. Переводим разницу в градусы: если сеть 50 Гц, период 20 мс = 360°, значит 1 мс = 18°.

Примерный код для Arduino:

const int voltagePin = A0;
const int currentPin = A1;
const float periodMs = 20.0; // для 50 Гц
const float degreesPerMs = 360.0 / periodMs;

unsigned long voltageZeroTime = 0;
unsigned long currentZeroTime = 0;
bool voltageCrossed = false;
bool currentCrossed = false;
int prevVoltage = 0;
int prevCurrent = 0;

void setup() {
  Serial.begin(115200);
}

void loop() {
  int vRaw = analogRead(voltagePin);
  int cRaw = analogRead(currentPin);
  
  float vVoltage = vRaw * (5.0 / 1023.0);
  float cVoltage = cRaw * (5.0 / 1023.0);
  
  // Определяем переход через 2.5 В снизу вверх
  if (prevVoltage < 2.5 && vVoltage >= 2.5 && !voltageCrossed) {
    voltageZeroTime = micros();
    voltageCrossed = true;
  }
  
  if (prevCurrent < 2.5 && cVoltage >= 2.5 && !currentCrossed) {
    currentZeroTime = micros();
    currentCrossed = true;
  }
  
  if (voltageCrossed && currentCrossed) {
    long delta = currentZeroTime - voltageZeroTime;
    float phaseAngle = (delta / 1000.0) * degreesPerMs;
    
    if (phaseAngle < 0) phaseAngle += 360.0;
    if (phaseAngle > 180.0) phaseAngle = 360.0 - phaseAngle;
    
    Serial.print("Фазовый угол: ");
    Serial.print(phaseAngle, 1);
    Serial.println("°");
    
    voltageCrossed = false;
    currentCrossed = false;
  }
  
  prevVoltage = vVoltage;
  prevCurrent = cVoltage;
  
  delayMicroseconds(100); // ~10 кГц опрос
}

Этот код — отправная точка. В реальности стоит добавить фильтрацию помех (скользящее среднее или медианный фильтр), а также проверку на то, что переходы произошли в одном и том же периоде.

Альтернативный метод: оцифровка и корреляция

Если нужна большая точность и ты готов повозиться с математикой, можно оцифровать оба сигнала за один период и вычислить фазовый сдвиг через дискретную взаимную корреляцию или быстрое преобразование Фурье (FFT).

Для этого потребуется:

  • Библиотека arduinoFFT — есть в менеджере библиотек
  • Массивы выборок по 128 или 256 точек на период сети
  • Синхронизация начала выборки с переходом напряжения через ноль

Метод даёт точность до 1–2°, но требует больше вычислительных ресурсов. Для Arduino Uno это заметная нагрузка, для ESP32 — вполне реально.

Сравнение подходов

Метод Точность Сложность Подходит для
Переход через ноль ±3–5° Низкая Arduino Uno, Nano
Взаимная корреляция ±1–2° Средняя Arduino Mega, ESP32
FFT (быстрое преобразование Фурье) ±0.5–1° Высокая ESP32, STM32

Что выбрать под свою задачу

Нужно быстро собрать и получить приблизительный результат — метод перехода через ноль с Arduino Uno. Хватит для расчёта cos φ с точностью до 0.05, что в большинстве практических задач приемлемо.

Нужна точность для лабораторных измерений или калибровки — FFT на ESP32 с 256 выборками. Но тут уже придётся разбираться с оконными функциями, утечкой спектра и прочими тонкостями.

Работаешь с нестандартной частотой сети (например, 400 Гц в авиации или 60 Гц в США) — не забудь поправить значение периода в коде. Для 60 Гц период 16.67 мс, для 400 Гц — 2.5 мс.

Частые ошибки и как их избежать

Нет гальванической развязки. Если ты подключаешь Arduino к сети без трансформаторов — это смертельно опасно. Всегда используй трансформаторы напряжения и тока, они обеспечивают развязку.

  • Забыл про смещение сигнала. Arduino не читает отрицательные напряжения. Без смещения на 2.5 В ты получишь только половину периода и полный хаос в измерениях.
  • Не учёл фазовый сдвиг самого трансформатора. Трансформаторы тока, особенно с ферромагнитным сердечником, сами вносят сдвиг 1–3°. Если нужна высокая точность — калибруй систему на чисто активной нагрузке (чайник, утюг).
  • Шум на аналоговом входе. Длинные провода к трансформаторам собирают помехи. Короткие дорожки, экранированный кабель, конденсатор 100 нФ параллельно входу — обязательно.
  • Слишком низкая частота опроса. Если опрашиваешь входы реже 5 кГц, погрешность измерения угла будет больше 10°. Для 50 Гц минимум — 10 кГц, лучше 20–50 кГц.
  • Неправильный выбор порога. Если сеть загружена и форма искажена, переход через ноль может быть не один за период. Используй гистерезис: фиксируй переход только после того, как сигнал ушёл от порога на 0.2–0.3 В.

Калибровка и проверка

Собрал схему — не верь первому показанию. Вот как проверить, что всё работает правильно:

  1. Подключи чисто активную нагрузку (лампочка накаливания, чайник). Фазовый угол должен быть близок к 0°.
  2. Подключи вентилятор или трансформатор без нагрузки — угол должен быть 20–40° (зависит от модели).
  3. Подключи конденсатор большой ёмкости — угол должен быть около 90°.
  4. Если показания не соответствуют — проверь фазировку: не перепутаны ли входы A0 и A1. Если ток «опережает» напряжение, а должен отставать — поменяй выводы ТТ местами.

Практические рекомендации

  • Питание Arduino — от отдельного блока питания или USB-адаптера, не от той же сети, которую измеряешь. Это снижает наводки.
  • Если измеряешь в розетке с заземлением — убедись, что земля трансформатора напряжения подключена правильно. Перепутанная фаза и ноль не влияют на измерение угла, но влияют на безопасность.
  • Для долговременного мониторинга записывай данные в SD-карту или отправляй по Wi-Fi (ESP8266/ESP32). Монитор порта хорош для отладки, но не для постоянной работы.
  • Если в сети есть мощные импульсные потребители (сварка, частотные преобразователи) — форма напряжения будет искажена, и метод перехода через ноль начнёт сбоить. В этом случае только FFT с анализом основной гармоники.

Итог

Измерить фазовый угол между напряжением и током с Arduino — задача вполне реальная для домашней лаборатории. Минимальный набор деталей, пара трансформаторов, простой код — и ты получаешь рабочий измеритель cos φ. Для большинства задач достаточно метода перехода через ноль с точностью 3–5°. Если нужна бо́льшая точность — переходи на FFT с ESP32.

Главное — не забывай про безопасность: гальваническая развязка через трансформаторы обязательна, стабилитроны на входах — тоже. Калибруй систему на известной нагрузке, и тогда показаниям можно верить.

radio-blog.ru — электроника и технологии