вольтмер 220V

бмм
Offline
Зарегистрирован: 04.04.2012

нужно устройство,которое при повышении/понижении напряжения до заданных пределов выключало питание.был такой план:
есть зарядное ненужное-в нем трансформатор и диодный мост,я думал его включить в розетку и ардуиной мерять напряжение.взял латр,мультиметр,проверил-все нормально.зарядное даёт 7,2 В,я подключил через делитель 100 кОм и 82 кОм.а analogRead показывает от 40 до 1023 :(
это какие то мгновенные значения,или неправильно подключил? я запутался :(

step962
Offline
Зарегистрирован: 23.05.2011

 После трансформатора+моста вы получаете не постоянное а выпрямленное (пульсирующее в пределах 0...Х Вольт) напряжение.

Чтобы получать более-менее постоянные результаты, его необходимо сгладить, конденсатором, например. 

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

бмм
Offline
Зарегистрирован: 04.04.2012

step962 пишет:

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

все равно не то :( я сделал 10 через 100 мсек

а какой нужен конденсатор,есть такой,пойдет?

 

maksim
Offline
Зарегистрирован: 12.02.2012

 Если через делитель, то по напряжению точно пойдет, а по емкости пробуйте, что у вас в сериал-мониторе кажет.

step962
Offline
Зарегистрирован: 23.05.2011

бмм пишет:

все равно не то :( я сделал 10 через 100 мсек

 

Частота сети - 50 Гц. Одна полуволна в 10 мсек. Период 100 мсек в этом смысле очень нехороший - вы снимаете показания в одной и той же точке каждой десятой полуволны. Период измерений не должен быть кратен периоду изменений контролируемой величины и не иметь с ним общих делителей. Возьмите период 23 мс. Или 29.  

 

И кстати - а что "не то"? Читатели теряются в догадках...

бмм
Offline
Зарегистрирован: 04.04.2012

step962 пишет:

Частота сети - 50 Гц. Одна полуволна в 10 мсек. Период 100 мсек в этом смысле очень нехороший - вы снимаете показания в одной и той же точке каждой десятой полуволны. Период измерений не должен быть кратен периоду изменений контролируемой величины и не иметь с ним общих делителей. Возьмите период 23 мс. Или 29.  

 

И кстати - а что "не то"? Читатели теряются в догадках...

спасибо!!:) при 23 уже нормально!все просто...

я еще не смог  придумать как грамотно считать среднее :( поэтому так-

а если поставить конденсатор,то будет 1020-1023

step962
Offline
Зарегистрирован: 23.05.2011

 Среднее подсчитывается очень просто.

Определяем переменные:

int mean;  // здесь будем вычислять среднее арифметическое
long oldTime;  // с помощью этой переменной будем определять момент очередного обращения к АЦП

В loop() пишем:

if(millis()-oldTime>23) { // наступило время опрашивать АЦП?
  oldTime = millis();     // приготовимся к следующему опросу
  mean = mean*9/10+analogRead(PIN); // а теперь собственно опрос и подсчет среднего арифметического последних 10 результатов
}

Все. Никаких delay() не надо. Программа работает без задержек и после 11-12 прохождения цикла (т.е. ок. 250-300 мсек) в переменной mean будет среднее арифметическое последних 10 измерений. И с каждым очередным проходом цикла это среднее будет обновляться, отслеживая возможное "плавание" напруги.

Demax
Offline
Зарегистрирован: 04.04.2012

Не упустите только один важный момент - требуемая скорость реакции на изменение напряжения в сети?

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

Можно погуглить по словам RC-цепь, напр. http://www.skilldiagram.com/gl1-13.html

бмм
Offline
Зарегистрирован: 04.04.2012

step962 пишет:

 Среднее подсчитывается очень просто.

Определяем переменные:

int mean;  // здесь будем вычислять среднее арифметическое
long oldTime;  // с помощью этой переменной будем определять момент очередного обращения к АЦП

В loop() пишем:

if(millis()-oldTime>23) { // наступило время опрашивать АЦП?
  oldTime = millis();     // приготовимся к следующему опросу
  mean = mean*9/10+analogRead(PIN); // а теперь собственно опрос и подсчет среднего арифметического последних 10 результатов
}

Все. Никаких delay() не надо. Программа работает без задержек и после 11-12 прохождения цикла (т.е. ок. 250-300 мсек) в переменной mean будет среднее арифметическое последних 10 измерений. И с каждым очередным проходом цикла это среднее будет обновляться, отслеживая возможное "плавание" напруги.

блин не могу посмотреть значение переменной mean после 11-12 прохождений цикла :( пожалуйста покажите как

Demax пишет:

Не упустите только один важный момент - требуемая скорость реакции на изменение напряжения в сети?

несколько секунд,не принципиально в общем )

step962
Offline
Зарегистрирован: 23.05.2011

бмм пишет:

блин не могу посмотреть значение переменной mean после 11-12 прохождений цикла :( пожалуйста покажите как

Почему через 11-12 прохождений?

Смотрите либо - ну скажем, каждые полсекунды (секунду, три, пять, десять ...):

if (millis()-timetoout>=500) {
  timetoout=millis(); // подготовимся к следующему выводу информации
// и произведем вывод текущего значения mean
 Serial.print("mean: ");
 Serial.println(mean);
}

Или каждый 10-й (20-й, 100500-й) проход loop():

loopCnt++;
if (loopCnt%10==0) {
// произведем вывод текущего значения mean
 Serial.print("mean: ");
 Serial.println(mean);
}

 

 

бмм
Offline
Зарегистрирован: 04.04.2012

крайне неприятно доставать,но хочется разобаться,почему то этот пример не работает,значения обновляются очень быстро,не раз в полсекунды точно,и это не среднее :(

 

step962 пишет:

if (millis()-timetoout>=500) {
  timetoout=millis(); // подготовимся к следующему выводу информации
// и произведем вывод текущего значения mean
 Serial.print("mean: ");
 Serial.println(mean);
}

вот так это выглядит:

а второй пример вообще ничего не пишет,но его я не понял и,вероятно,неправильно употребил

step962
Offline
Зарегистрирован: 23.05.2011

 Ну и не доставайте.

Просто приведите весь код в его нынешнем состоянии - без этого сказать что-либо конкретное весьма проблематично.

бмм
Offline
Зарегистрирован: 04.04.2012

step962 пишет:

 Ну и не доставайте.

Просто приведите весь код в его нынешнем состоянии - без этого сказать что-либо конкретное весьма проблематично.

так он же на скриншоте есть :)

step962
Offline
Зарегистрирован: 23.05.2011

 Но там же только loop() ;)

Попробуйте строку

if(millis()-oldTime>23)

(здесь фактически происходит вызов АЦП каждые 24, а то и вообще каждые 25 миллисекннд, что лежит слишком близко (24 мсек) либо вообще кратно периоду изменения напряжения (25 мсек - 2,5 периода, т.е. практически измеряются напряжения в двух фиксированных точках полуволны - никакого усреднения))

чуть-чуть изменить:

if(millis()-oldTime>=23)

Если не поможет (не сильно поможет) возьмите условие

if(millis()-oldTime>=22)

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

step962
Offline
Зарегистрирован: 23.05.2011

 Кстати, еще я бы вынес определения переменных из функции loop() в общую секцию (т.е. в самый верх скетча). Зачем? А затем, что если верить различным источникам, функции setup() и loop() при компиляции обертываются в необходимую каждой написанной на C программе функцию main():

int main(void)
{
	init();
	setup();
	for (;;)
		loop();
	return 0;
}

И локальные переменные функции loop() начинают инициализироваться непонятно каким образом. Они сидят в стеке (а не в "нормальной" оперативной памяти), создаются при каждом новом вызове loop() и уничтожаются перед завершением этой функции. Каждый раз при новом вызове функции loop() под одну и ту же переменную выделяется одно и то же место в стеке и значения как бы "сохраняются". Но ведь стеком могут воспользоваться и функции обработки прерывании, и если прерывание произойдет в момент между завершением очередного вызова функции loop() и следующим ее вызовом, то вполне может произойти модификация участков стековой памяти и в следующий раз вы получите совсем не то значение, которое сохранили в переменной.

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

maksim
Offline
Зарегистрирован: 12.02.2012

 step962, а если добавить перед ними static, то можно и оставить и внутри loop(). А вообще никогда так не делал(глобальные переменные в loop()), почему-то привык считать, что то что хранится в выделяемой памяти для переменной в момент ее создания это "мусор".

бмм
Offline
Зарегистрирован: 04.04.2012

о.O :))

step962
Offline
Зарегистрирован: 23.05.2011

 Определите mean как unsigned int и строчку

mean = mean*9/10+analogRead(0);

перепишите в виде

mean = mean/10*9+analogRead(0);

Сейчас, похоже, происходит выход за пределы диапазона положительных чисел, представимых типом int (0...32767)

maksim
Offline
Зарегистрирован: 12.02.2012

Правильно вот так: 

mean = (mean*9+analogRead(0))/10;

а тип mean можно оставить как есть эта переменная теперь будет принимать значения от 0 до 10230 и не сможет выйти за предел 32767.

бмм
Offline
Зарегистрирован: 04.04.2012

вот так :) лучшие результаты попрежнему при mean=23.напряжение в сети по мультиметру  210-213 В.

десятипроцентная неточность терпима.большое спасибо!!!! :)

maksim
Offline
Зарегистрирован: 12.02.2012

Если сильно колеблится то можно попробовать усреднять по 15, 20, 25 и т.д. значениям:

mean = (mean*14+analogRead(0))/15; // по 15 значениям

mean = (mean*19+analogRead(0))/20; // по 20 значениям

mean = (mean*24+analogRead(0))/25; // по 25 значениям

но тогда возрастает инерционность измерения напряжения. 
 

maksim
Offline
Зарегистрирован: 12.02.2012

Сейчас тестил эти усреднения и вот к чему пришел, если использовать целочисленный тип переменной mean, то появляется неточность в усреднении, так по 10 значениям:

а по 40 вот такая неточность:

поэтому если нужна точность, переменная mean дожна быть типа float или double:

 

step962
Offline
Зарегистрирован: 23.05.2011

maksim пишет:

Сейчас тестил эти усреднения и вот к чему пришел, если использовать целочисленный тип переменной mean, то появляется неточность в усреднении, так по 10 значениям:

Именно поэтому предлагалась формула

mean = mean/10*9+analogRead(0);

При этом в mean хранится не среднее арифметическое, а сумма последних 10 измерений (т.е. перед использованием еще потребуется разделить на 10). Соответственно, ошибка усреднения существенно меньше.

Формула 

mean = mean*9/10+analogRead(0);

еще точнее (говорим о целочисленной арифметике), однако, в этом варианте для суммы уже достаточно велик риск переполнения, если первая операция в формуле - умножение. (сумма 10 измерений - это около 7000, умножение на 5 уже дает результат больше 32767, а уж на 9 - тем более). Поэтому приходится сначала делить. Или переходить на тип long. 

Переходом на вещественные типы этого можно легко избежать, однако придется платить весьма высокую цену: скорость исполнения соответствующего участка кода снизится раз в десять. Для данной задачи это не критично, ибо она все равно ничем другим пока не занимается. Но с течением времени - и ростом возлагаемых на скетч задач - все может измениться. 

maksim
Offline
Зарегистрирован: 12.02.2012

Да, вы совершенно правы

DimaP.
Offline
Зарегистрирован: 21.04.2013

Здравствуйте!

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

 

DimaP.
Offline
Зарегистрирован: 21.04.2013

Идея следующая создать устройство которое контролировало бы изменение напряжения в фазах источника!

с последующим выводом информации в виде времени и даты, а также напряжения во всех 3 фазах!!!

Скажите выше описанный метод имеет достаточное быстродействие??

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

вообщето с измерением 220В в сети не все так просто...

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

если сигнал синусоида, то можно брать и средневыпремленное напряжение(просто среднее значение с ацп за N измерений), но в реальной сети будут большие погрешности

 

В дешовых стабилизаторах применяют вот такую схему для контроля за входным или выходным напряжением

ourlive
Offline
Зарегистрирован: 26.05.2012

Интересно, как с такой мегасложной задачей справляются стрелочные приборы? Получить действующее значение (а другие никому и не нужны обычно) аппаратным методом проще некуда, где смотреть RC цепочки ссылки выше уже есть.

Клапауций
Offline
Зарегистрирован: 10.02.2013

ourlive пишет:
Интересно, как с такой мегасложной задачей справляются стрелочные приборы? Получить действующее значение (а другие никому и не нужны обычно) аппаратным методом проще некуда, где смотреть RC цепочки ссылки выше уже есть.

Вообще то, интересно справляются - пробовали мерять переменное напряжение стрелочным вольтметром, если, внезапно так, в электрической сети присутствует постоянная составляющая?

Вольтметр говорит, о!, да! - всё прекрасно, у нас ровно 220В переменки, а почему первичные обмотки блоков питания горят, дык, это ты спроси у стрелочного вольтметра постоянного напряжения, а про отклонения от синусоиды - это ты иди к осциллографу.

А, так, да - показывают исправно стрелкой по шкале.

 

 

ourlive
Offline
Зарегистрирован: 26.05.2012

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

Клапауций
Offline
Зарегистрирован: 10.02.2013

ourlive пишет:

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

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

ourlive
Offline
Зарегистрирован: 26.05.2012

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

Клапауций
Offline
Зарегистрирован: 10.02.2013

ourlive пишет:
Ааа.. Тогда оно понятно, каждый начинающий просто обязан... 

Верно. Тех, кто не пожелает добровольно - придётся заставить.

ourlive пишет:
Так что здесь не место для флуда, говорите по существу.

С чего бы это здесь не место для флуда?

 

DimaP.
Offline
Зарегистрирован: 21.04.2013

Всем кто откликнулся спасибо!!

На сколько я понимаю RC цепочки надо будет добавить для того чтобы избавиться от высокочастотных помех!!! я пробовал собрать активный фильтр на ОУ

Ну почемуто ничего не получилось!

 

DimaP.
Offline
Зарегистрирован: 21.04.2013

видел вот такую  схему!!!

что думаете в роли двухполупериодного выпрямителя если её применить???

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

вон приводил выше схему, получаешь синусоиду относительно 2В, щитай спокойно напругу...

а вот всякие кондеры в ОС усилка ето уже надо смотреть чо вы там на выходе получаете... вроде сигнал будет интегрироваться и ето походу можно будет снимать среднее значение напряжения, что годиться для чистой синусоиды. Если нагрузка реальная из жизни, то у вас не совсем правильная синусоида получится и будут неплохие ошибки при измерении. Щитайте действующее(среднеквадратическое) напряжение, как делается во всех нормальныйх RMS вольтметрах

Snubist
Offline
Зарегистрирован: 18.02.2013

Посмотри еще http://cxem.net/izmer/izmer90.php

 

DimaP.
Offline
Зарегистрирован: 21.04.2013

  А скажите Michal предложенная вами схема как вы сказали будет ихмерять напряжение относительно 2.5 вольт я не совсем понимаю как это!!! Моли бы вы растолковать это?

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

на выходе второго ОУ будет синусоида относительно 2В. Если считаем действующее напряжение, то нам все равно в какой момент начинать считать. Главное кратность соблюдать(я пол периода считал). А раз измеряемое напряжение смещено на 2В, то надо каждый раз от измеренного значения отнимать это смещение. На знак нам плевать, потому что квадрат. Ну как то так...

схема рабочая, т.к ето входная цепь китайского стабилизатора напряжения, у одних в качестве МК моторола кажись НС8 серия, а в других пики.

 

DimaP.
Offline
Зарегистрирован: 21.04.2013

 

 

а если я для гальванической развязки трансформатор поставлю, вместо сопративлений надеюсь это координально не повлияет на работу схемы!

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

та можно, только перещитать сопротивления на ОУ, да и в исходной схеме там почти 3МОм сопротивление, так что почти развязано :)

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

да и если соберетесь измеренное кидать на ПК, то лучше развязать ПК и плату, 110В в порт можно словить.

 

DimaP.
Offline
Зарегистрирован: 21.04.2013

Хорошо как спаяю схему на макете проверю, надеюсь все получится!!!

DimaP.
Offline
Зарегистрирован: 21.04.2013

Уважаемый Michal пробовал собрать схему предложенную вами но на входе стоит у меня трансформатор, как пересчитать сопративление на 2 ОУ я не могу понять. Какие сопративления надо пересчитывать??? Пробовал гуглить но нигде такого включения ОУ не нашел!

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

не силен в математике, но в в протеусе замутил ету схемку, получилось, что при трансе на 9В вместо 2.8МОм нужно ставить 110кОм

даже не спрашивайте как я к этому пришел :)

DimaP.
Offline
Зарегистрирован: 21.04.2013

Ну вот собрал я схему и через осцеллограф посмотрел  что на выходе получается,  на выходе мы получаем синусоиду поднятую примерно на 2 вольта, теперь чтобы получить напряжение мы должны по идее ловить пики синусоиды и это будет действующее значение! другие материалы читал там риводят вот такие формулы

получается что применение прерывания по таймеру неизбежно???

подскажите, все же как измерять напряжение с частотой 50 Гц??

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

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

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

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

Unreturned
Offline
Зарегистрирован: 04.05.2013

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

по делу - надо же знать когда снимать замеры, этож синусоида! можно с кондёром выпрямить, но получаем инэртность, а можно и привязаться к началу полуволны, к нолю.

 

 

 

 

 

 

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

в трёхфазной сети дополнительно можно замутить контроль фаз, следить будут ли идти последовательно А->B->C... 

DimaP.
Offline
Зарегистрирован: 21.04.2013

 

А вот по поводу детектора нуля  интересная мысль!!! стоит обдумать. 

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

Unreturned скажите у вас есть информация рускоязычная по таймерам Atmega328?

DimaP.
Offline
Зарегистрирован: 21.04.2013

вот нашел кусок кода где настроен таймер!!

/* Timer reload value, globally available */
unsigned int tcnt2;

//Setup Function will run once at initialization
void setup()
{

/* First disable the timer overflow interrupt*/
 TIMSK2 &= ~(1<<TOIE2);

/* Configure timer2 in normal mode (no PWM) */
 TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
 TCCR2B &= ~(1<<WGM22);

/* Select clock source: internal I/O clock */
 ASSR &= ~(1<<AS2);

/* Disable Compare Match A interrupt (only overflow) */
 TIMSK2 &= ~(1<<OCIE2A);

/* Configure the prescaler to CPU clock divided by 128 */
 TCCR2B |= (1<<CS22)  | (1<<CS20); // Set bits
 TCCR2B &= ~(1<<CS21);             // Clear bit

/* We need to calculate a proper value to load the counter.
 * The following loads the value 248 into the Timer 2 counter
 * The math behind this is:
 * (Desired period) = 64us.
 * (CPU frequency) / (prescaler value) = 125000 Hz -> 8us.
 * (desired period) / 8us = 8.
 * MAX(uint8) - 8 = 248;
 */
/* Save value globally for later reload in ISR */
 tcnt2 = 248;

/* Finally load end enable the timer */
 TCNT2 = tcnt2;
 TIMSK2 |= (1<<TOIE2);

}

/* Install the Interrupt Service Routine (ISR) for Timer2.  */
 ISR(TIMER2_OVF_vect)
 {
/* Reload the timer */
 TCNT2 = tcnt2;}

 

На первый взгляд ничего сложного но никак не могу я разобраться что к чему!!

 

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

впринципе детектор нуля можно и не делать, просто брать по модулю значение (это для среднего значения)... для сред. квадр. пофиг вообще когда снимать показания.

 

для настройки таймеров используйте codeVision. Там хороший мастер настройки оборудования, сразу код нужный на С выдает

Unreturned
Offline
Зарегистрирован: 04.05.2013

DimaP. пишет:

Unreturned скажите у вас есть информация рускоязычная по таймерам Atmega328?

к сожалению нет, да и я сам немного в коде не того... как в 90-тые пытался с турбопаскаля на си перейти, так и не смог, теперь страдаю...

по поводу прерывания, тут натыкался на тему о хронографе, нашёл блог этого человека, он реализовал в простом коде прерывания. http://justforduino.blogspot.ru/2013/05/arduino-2.html

сейчас занят хронографом, но думаю этот код применить и для вольтметра-самописца.