Точное измерение переменного тока датчиком ACS712 на Arduino: метод истинного RMS (TRMS)
Необходимые компоненты
- Arduino UNO — 1 шт.
- Датчик тока ACS712 (версия 30A) — 1 шт. Совет: для бытовых нагрузок лучше 5A или 10A — меньше шумов.
- Дисплей: LCD 16×2 I²C или OLED 128×32 I²C — 1 шт.
- Перемычки, нагрузка для тестов (лампа накаливания + диммер)
О проекте
Автор (SurtrTech) показывает, как правильно измерять переменный ток с ACS712. Датчик основан на эффекте Холла: выходное напряжение пропорционально току в проводнике, гальванически разделённом с измеряемой цепью. Главная сложность — вычисление истинного корня из среднего квадрата (True RMS) для несинусоидальных сигналов (например, при управлении диммером/триаком).
Почему простой метод «пик-пик» не работает
Для чистой синусоиды RMS = (Vpp / 2) × 0,707. Но если форма сигнала искажена (обрезанная синусоида от фазового регулятора), пик-пик даёт завышенные значения. Пример: мультиметр показывает 0,21 А, простой код — 0,36 А.
Решение: библиотека Filters (статистический подход)
Библиотека Filters.h реализует скользящее окно накопления выборок и вычисляет сигму (стандартное отклонение) сигнала, что эквивалентно TRMS для нулевого среднего. Настройка выполняется двумя коэффициентами:
intercept— смещение нуля (ошибка при нулевом токе).slope— коэффициент пропорциональности (калибровка по известной нагрузке).
Калибровка
- С током 0 А измеряйте
inputStats.sigma(). Если не 0 — задайтеintercept = -measured_sigma. - Подайте известный ток (например, лампа 75 Вт при 230 В → ~0,326 А). Измерьте
sigma. Вычислитеslope = I_real / sigma. - Пропишите оба коэффициента в скетче.
Примеры кода (основные версии)
1. Тест формы сигнала (Serial Plotter)
#define CURRENT_PIN A0
void setup() {
Serial.begin(9600);
pinMode(CURRENT_PIN, INPUT);
}
void loop() {
float val = analogRead(CURRENT_PIN);
Serial.println(val);
delay(100); // подберите задержку для видного синуса
}
2. Метод пик-пик (только для синусоиды)
#define SAMPLES 300
#define ACS_PIN A0
float highPeak, lowPeak, ampsPP, ampsRMS;
void setup() { Serial.begin(9600); pinMode(ACS_PIN, INPUT); }
void loop() {
readAmps();
ampsRMS = ampsPP * 0.3536 * 0.06; // 0.06 — эмпирический калибровочный коэф.
Serial.print(ampsRMS); Serial.print("\t"); Serial.println(ampsPP);
delay(200);
}
void readAmps() {
highPeak = 0; lowPeak = 1024;
for (int i=0; i highPeak) highPeak = v;
if (v < lowPeak) lowPeak = v;
}
ampsPP = highPeak - lowPeak;
}
3. TRMS через библиотеку Filters (Serial)
#include
#define ACS_PIN A0
float testFreq = 50.0;
float window = 40.0 / testFreq; // 800 мс окно
float intercept = 0;
float slope = 0.0752; // ПОДСТАВЬТЕ СВОИ ПОСЛЕ КАЛИБРОВКИ
unsigned long period = 1000, prev = 0;
void setup() {
Serial.begin(9600);
pinMode(ACS_PIN, INPUT);
}
void loop() {
RunningStatistics stats;
stats.setWindowSecs(window);
while (true) {
float v = analogRead(ACS_PIN);
stats.input(v);
if (millis() - prev >= period) {
prev = millis();
float amps = intercept + slope * stats.sigma();
Serial.print("\t Amps: "); Serial.println(amps);
}
}
}
4. TRMS + LCD I²C
#include
#include
#define ACS_PIN A0
#define I2C_ADDR 0x27
LiquidCrystal_I2C lcd(I2C_ADDR, 2, 1, 0, 4, 5, 6, 7); // En, Rw, Rs, D4-D7
// ... те же параметры окна, intercept, slope ...
void setup() {
lcd.begin(16,2);
lcd.setBacklightPin(3, POSITIVE);
lcd.setBacklight(HIGH);
}
void loop() {
RunningStatistics stats;
stats.setWindowSecs(window);
while (true) {
stats.input(analogRead(ACS_PIN));
if (millis() - prev >= period) {
prev = millis();
float amps = intercept + slope * stats.sigma();
lcd.clear();
lcd.setCursor(2,0);
lcd.print(amps); lcd.print(" A");
}
}
}
5. TRMS + OLED 128×32 (Adafruit SSD1306)
#include
#include
#include
#define ACS_PIN A0
#define SCREEN_W 128
#define SCREEN_H 32
Adafruit_SSD1306 display(SCREEN_W, SCREEN_H, &Wire, -1);
// ... те же параметры ...
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay(); display.display();
}
void loop() {
RunningStatistics stats;
stats.setWindowSecs(window);
while (true) {
stats.input(analogRead(ACS_PIN));
if (millis() - prev >= period) {
prev = millis();
float amps = intercept + slope * stats.sigma();
display.clearDisplay();
display.setTextSize(3);
display.setTextColor(WHITE);
display.setCursor(15,10);
display.print(amps); display.println(" A");
display.display();
}
}
}
Схемы подключения
- ACS712: VCC → 5V, GND → GND, OUT → A0. Измеряемый провод проходит через клеммы модуля.
- LCD I²C: SDA → A4, SCL → A5, VCC/GND → 5V/GND.
- OLED I²C: те же пины I²C.
Важные замечания
- Безопасность! Работа с сетью 220 В опасна. Используйте изолированные провода, не касайтесь открытых частей под напряжением.
- Версия ACS712 30A имеет низкую чувствительность (66 мВ/А) — для малых токов шум большой. Лучше 5А (185 мВ/А) или 20А (100 мВ/А).
- Библиотека
Filters.hне входит в стандартный набор — скачайте с GitHub автора (ссылка в исходнике) или найдите в Library Manager. - Частота сети (50/60 Гц) задаётся в
testFrequency.
Производственный процесс
- Измерение качества воздуха с OpenSensors: руководство по Arduino и Python
- Датчик CO2 K30: мониторинг качества воздуха в реальном времени на Arduino
- Устройство для общения глухосліпых людей с помощью 1Sheeld и Arduino
- Умная копилка: управление монетоприёмником на Arduino Nano
- Управление светодиодом по Bluetooth с Arduino: простой DIY-гид
- Интеграция ёмкостного сканера отпечатков DFRobot с Arduino или ESP8266
- Интерактивный HMI-проект на Nextion с Arduino Mega и датчиками
- Роботизированная рука 6 степеней свободы на Arduino Mega с управлением через Nunchuk
- Оживление рыбы Billy Bass с любым аудиоисточником — пошаговое руководство
- Измерение солнечной радиации на Arduino UNO с Ethernet Shield