Официальный сайт компании Arduino по адресу arduino.cc
GY-712 30A. "Удаленный" контроль переменного тока
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Мониторю температуру и влажность на даче через народный мониторинг. Ардуино подключена к роутеру с OpenWRT.
Зимой дом обогревается конвекторами на режиме незамерзание +5-7 град С.
Хочу мониторить потребляемую мощность конвекторов и в последующем управлять ими.
Как промежуточная задача необходимо реализовать сенсор тока, но столкнулся со странными проблемами, а именно, датчик тока показывает значения сильно отличающиеся от номиналов нощьностей приборов.
Например: фен для волос номинал 1200Вт, а ток течет 1,82А т.е. 400Вт. Электрочайник 2.2кВт ожидаемый действующий ток 10А, а на практике 3,42 А т.е. 750Вт.
Собрал тест: Компьютер - USB - Arduino - +5,GND,A0 - GY-712(30A) - в разрыв проводника к розетке 220.
Вот прграмма:
long now; // Время сейчас long LastMeasure=0; // Время последнего измерения long DeltaMeasure=1000; // Интервал измерений long DeltaMeasureSinPeriod=20; // Период синусоиды для измерения значений 50 Герц long LastMeasureSinPeriod=0; // long LastSerialPrint=0; // Время последнего вывода в серийный порт long DeltaSerialPrint=5000; // Интервал вывода в серийный порт long EndOfPeriod=0; // Конец периода измерения double Resolution=0.0293; // Ампер в 1 делении АЦП для 30А датчика 30/1024 int Input[6]; // Массив для хранения результатов измерения всех АЦП //int CurrentArray[175]; int analogChannel=0; // Пока измерения произвожу на 1 входе int Input_currentLast=0; // Предидущее измерение моментального значения тока в единицах АЦП int Input_current=0; // Текущее значение моментального значения тока в единицах АЦП double Input_current_rms=0; // Действующее значение тока за период long i=0; // Счетчик измерений внутри периода //long ii=0; long lasti; // Предидущее значение счетчика измерений void setup() { Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } } void loop() { now = millis(); // Время от начала в милисекундах if (now >= EndOfPeriod) { // Проверка, что не находимся внутри периода измерений синусоиды тока (можно снова мерить) if (now >= LastMeasure + DeltaMeasure) { // Проверяем, что не находимся в интервале между измерениями (можно снова мерить) // сбросить результат и выставляем условия для начала измерений в следующем цикле Input_currentLast=Input[analogChannel]; Input_current=0; Input[analogChannel] = 511; //Input[analogChannel] = 0; EndOfPeriod = now + DeltaMeasureSinPeriod; lasti=i; i=0; } } else { i++; measure(); // Идем мерить один отсчет } // Если пора печатать, то печатаем if (now >= LastSerialPrint + DeltaSerialPrint) { Input_current_rms = ((Input_currentLast - 511) * Resolution) / 1.4142; // Вычисляем действующее значение тока на периоде: отнимаем постоянные показания датчика (511) и умножаем на амперы в единице АЦП и делим на корень из 2 (для гармонических колебаний) // * Resolution) / 1.4142); Serial.print (" Pin A="); Serial.print (analogChannel); Serial.print (" value="); Serial.print (Input_currentLast); Serial.print (" Urms="); Serial.print (Input_current_rms); Serial.print (" i="); // просто интересно сколько раз МК успевает померить сигнал на АЦП Serial.println (lasti); //for (ii=1;ii<=lasti;ii++) { // Serial.println (CurrentArray[ii]); //} //ii=0; LastSerialPrint=now; } } void measure () { Input_current = analogRead(analogChannel); // получаем значение на АЦП //CurrentArray[i] = Input_current; if (Input_current >= Input[analogChannel]) // сравниваем его с предидущим и оставляем большее (ищем максимальное значение измерения в периоде синусоиды, чтобы найти амплитуду тока) { Input[analogChannel] = Input_current; //Serial.println (Input_current); } }
Суть такая:
Специально не использую delay, поскольку не хочу прерывать выполнение программы.
Один раз в пять секунд печатаю результат (просто так удобнее на период отладки)
Один раз в секунду на протяжении одного периода синусоиды (20 милисекунд) переменного тока измеряю все значения напряжения с датчика, так часто, как только может контроллер.
Определяю амплитуду синуса, пересчитываю в амперы и делю на корень квадратный из 2. (1.4142). В результате получаю дейтвующее значение переменного тока и могу получить значение мощности. I действ * U действ = P
Датчик менял. Порт Ардуины тоже. Период измерения синусоиды увеличивал. Результаты измерений отсчетов синусоиды накапливал и выводил. Напряжение на датчик подается 5.12Вольт Амперметра для переменного тока таких величин у меня нет.
Методика верна. В комментариях программы есть строчки для наполнения массива результатов и вывод его значений. Значения собрал в экселе построил график. Получается произвольный четкий период синусоиды из 170 отсчетов на период.
Чему верить то?
Может это нормально, что на приборах написано 2200 Вт, а он 750 Вт, 1200 Вт, а он 400 Вт? Значения меньше в разы!
Ну все правильно. Куда копать? Может кто сталкивался? Или придется таки купить мультиметр с большим переменным током?
1. А что это за величина Resolution=0.0293? Насколько я помню, у 30-амперного датчика чувствительность 66мВ/А.
2. Идея выделять в сигнале амплитуду, чтобы затем пересчитать ее в действующее значение для синусоиды мне кажется порочной. Коль скоро мы можем измерить профиль, логичнее всего было бы его интегрировать. Так мы будем получать верное значение при любой форме сигнала.
вся проблема в том, что вы опрос делаете в основном цикле и получаете не равномерную выборку
равномерной я называю выборку в которой замеры тока делаются через равные промежутки времени
практически единственый вариант это сделать - это делать замеры по прерываниям ADC, а инициирование измерений делать или по таймеру или в режиме FreeRunning
чтобы более менее точно замерить ток, надо на одном полупериоде сделать как минимум сотню замеров, так как полупериоды в сети следуют с частотой 100 гц, получается, что минимальная частота выборки замеров должна быть 10кгц. Дальше в этой выборке нужно или считать среднеквадратичное если мы хотим получить RMS или находить максимум и пересчитывать его в действующее значение тока полелива на корень из 2 (примерно поделить на 1.41). Если у вас сиключительно конвекторы т.е только активная нагрузка то достаточно простого второго способа (поиск максимума)
можете примеры мои посмотреть http://radiokot.ru/articles/54/ и http://radiokot.ru/lab/controller/66/
там не ардуино, но код с небольшими изменениями (под мега328) можно скопировать или просто использовать для понимания
Обычно переменное напряжение (измерение тока делается через измерение напряжения) измеряется двумя способами (не считая экзотических типа термо)
1. Мост, выпрямление, сглаживание и измерение постоянного напряжения (дешевые мультиметры)
2. True RMS обычно написано в документации это оцифровка сигнала и его интегрирование. Есть специальный проект http://openenergymonitor.org, там есть решения и для ардуино с библиотекой https://github.com/openenergymonitor/EmonLib. Я использую эту библиотеку с небольшими доработками, Все достаточно корректно рабоатет.
Смотрите в сторону готовых уже опробованных решений.
Народный мониторинг это передача данных раз 3-5 минут. У вас много времени можно сделать 10-100 замеров по прерыванию (или без него) и усреднить значения. Пока в Вашей задаче проблем не вижу. Аналогичную задачу (измерение напряжения, тока мощности и коэффициента мощности я реализовал) см
http://arduino.ru/forum/proekty/kontrol-za-teplovym-nasosom-na-arduino-uno
можите код позаимстовать от туда.
Resolution=0.0293 - это 30/1024 Амперов в одном делении АЦП.
Интегрировать - правильный путь, но заранее известно, что сигнал это синусоида. Я стал мерить часто как это возможно, чтобы убедится, что успеваю поймать максимум. Кстати всего 168-172 измерения получается за 20 милисекунд. Для моего "частного" случая (бытовые 220В частота в 50 Гц) достаточным будет 100 раз за период.
Вы говорите: "Насколько я помню, у 30-амперного датчика чувствительность 66мВ/А." Надо подумать. Что то у меня явно не так.
Я полагал, что 30А - это на всю шкалу 5 Вольт. Поскольку, 0Ампер -это 2,5Вольта, то 30 Ампер в одном направлении будет 4,48 Вольта или если в другом, то 0,52 Вольта.
Получается, что 30Ампер - это 917 единиц АЦП, а -30А -это 106 единиц АЦП.
Когда я Включаю чайник у меня максимум за период синусоиды на АЦП 670 единиц, что соответствует 670 - 511(значение нуля) = 159 единиц = 11,75 Ампер =Амплитуда.
Измеренное действующее значение синусоидального тока для чайника 2,2-2,4 кВт -> 8,31 Ампера. Вполне честный результат (надо еще оценить погрешность)).
Все! Ошибка найдена! Амплитуда показаний датчика уже, чем я полагал изначально: 0.52 В это -30А, а 4,48 это +30А
Переделаю программу и положу результат сюда. Всем спасибо!
Спасибо за ссылки. Проанализирую.
Просто заранее известно, что действующее значение напряжения 220В и дальше совершаю достаточное > 100 измерений показаний с датчика, нахожу максимум и для синусоиды делю на корень квадратный из двух. Получаю действующее значение тока. Далее вычисляю мощьность действ ток умножаю на действ напряжение. И эта мощность в разы меньше заявленной на приборах. Я измерял ток на электрочайнике (активная нагрузка) и на фене (сложная нагрев и электродвигатель). В обоиз случаях разнича в разы.
Разве имеет значение активная или неактивная нагрузка если я вычисляю мощность по действующим значениям?
повторюсь.....
http://gizmosnack.blogspot.se/2014/11/power-plug-energy-meter-now-wireless.html
http://gizmosnack.blogspot.se/2014/10/power-plug-energy-meter-hack.html
https://hackaday.com/?s=power+meter
и кнопочка внизу: <--- Older posts для листания
http://geektimes.ru/post/259248/
http://majordomo.smartliving.ru/forum/viewtopic.php?f=4&t=2347
Разве имеет значение активная или неактивная нагрузка если я вычисляю мощность по действующим значениям?
имеет. Форма сигнала (в том числе и по току) на реактивной нагрузке будет отличаться от синуса, возможно даже сильно. В этом случае формула МАКСИМУМ/1.41 не работает, в этом варианте нужно считать среднеквадратияное то есть RMS
Изучил материал на http://openenergymonitor.org. в библиотеке EmonLib авторы не парятся, чтобы уловить один период сигнала. Просто измеряют столько времени сколько понядобится для заданного количества замеров. Типа чем больше замеров, тем точнее?
Еще интересно период замеров одинаковый внутри цикла?
Типа чем больше замеров, тем точнее?
А Вы не знали?
Случайная погрешность, которой грешат все аналоговые датчики, уменьшаеся пропорционально квадратному корню из числа измерений.
Форму сигнала при таком раскладе не нарисуешь. По делу то она не нужна, но было бы красиво. Форма напряжения и тока.) Наверное можно, придется фиксировать время каждого измерения, искать переход через 0 и усреднять значения из разных периодов. На ATMEGA328 это не сделать. Буду делать с большим количеством отсчетов.
Вот код, который считает ток, пытаясь произвести измерения не чаще 200 мксек (100 раз за период), но успевает сделать только 60 внутри периода.
Скорости работы платы не хватает((.
Вернусь на максимальное количество внутри периода (получалось 162 раза) без проверки, что уже прошло 200 микросекунд.
Еще добавлю возможность измерять несколько периодов подряд или буду сохранять измерения разных периодов с усреднением.
dimontie, функция analogRead не предназначена для скоростной оцифровки, для этого существует специальный режим ацп с использованием прерывания. Даташит в помощь :)
Может кому пригодиться кусок кода из большого проекта, работает уже год, меряетт ток на мой взгляд очень точно. Лампочка 60 ватт при 230 вольт выдает 0,26-0,27А. Данные на сервер в куске кода передаются в мА.
Ток меряется постоянно, раз в установленное время отправлет данные на сервер.
Все что нужно "просто добавь воды" - указать свои пины куда подключены датчики тока. Скетч для трех датчиков. (трехфазка)
Ты не прав, Axill !
Форма тока и напряжения (а также мощности) при реактивной нагрузке будет синусоидой.
Там ведь только фазы сдвигаются и идет перемножение одного синуса на другой, "...сдвинутый по фазе..."
А вот для нелинейной нагрузки - другое дело.
Вот код, который считает ток, пытаясь произвести измерения не чаще 200 мксек (100 раз за период), но успевает сделать только 60 внутри периода.
Скорости работы платы не хватает((.
Вернусь на максимальное количество внутри периода (получалось 162 раза) без проверки, что уже прошло 200 микросекунд.
Еще добавлю возможность измерять несколько периодов подряд или буду сохранять измерения разных периодов с усреднением.
В теории, господа, для сети 50 Гц достаточно оцифровывать с частотой 100 Гц, но лучше, конечно, 500 Гц, т.е 10 раз за период для надежности.
Тем более, вы смотрите не переходные процессы, а довольно стационарные.
При достаточном быстродействии можете тупо умножать мгновенные значения тока на мгновенные значения напряжения, и тупо суммировать за несколько периодов.
Поправьте, ежли я не прав...
Все верно говорите, 100Гц - за глаза.
У меня задача как раз и стояла чтобы мерять среднее значение в периоде опроса и пиковое.
Как видите на картинке пиковые значения есть в каждом периоде. Лампочкой накаливания щелкнул ток в 1.7 раза подскочил. В доме никто не живет на постоянке - наездами, поэтому таке маленькие покаатели. Качели потому что котел, так же управлемый arduino то сильнее то меньше топит + покомнонатное управление температурой, сервопривода туда сюда крутят нагрузку :)
Класс.
Полезное действие АЦП откалибровать. Я не предусмотрел.
Я еще не реализовал свой проект((( Подзабил.
Получил ESP8266 и 12Е и на ней попробовал реализовать. Там АЦП успевает за период почти 3000 раз померить. И как сервер TCP, UDP работает, и как MQTT клиент. Планирую периодически соединяться на нее и получать данные.
У ESP есть библиотека с серво. Можно и регулятор крутить)).
Есть ряд нюансов: 3.3 вольта питания, 3.3 уровни логические и АЦП только 1, но памяти полно и производителность высока.
Делаю 5В питание на датчик и с датчика через делитель на вход АЦП ESP-12E.