диммер на прерываниях
- Войдите на сайт для отправки комментариев
Пытаюсь сделать простой диммер для ламппочки накаливания 220 В. Перерыл кучу информации, спаял плату детектора нуля и плату силовоо ключа. Нашел скетч которы более менее работает (и еще вагон), но все они мне не нравятся со своими делаями и magic number. По скольку сам немного программист, решил написать свой с основной лоикой на прерываниях. Вот загготовка:
int PIN_LOAD = 5; // пин симистора volatile unsigned int timer_tick = 0;//счетчик срабатываний таймера (одно срабатывание в 1 миллисекунду) unsigned int last_timer_val = 0; unsigned int dim_time;// интервал диммирования, задается в loop void setup() { Serial.begin(115200); pinMode(PIN_LOAD, OUTPUT); // назначаем выходом attachInterrupt(0, zero_crosss, RISING); // прерывание детектора нуля //настройка тамера на срабатывание 1 раз в мс TCCR0A |= (1 << WGM01); OCR0A = 0xF9; TIMSK0 |= (1 << OCIE0A); TCCR0B |= (1 << CS01) | (1 << CS00); sei(); } ISR (TIMER0_COMPA_vect) //прерывание таймера для отслеживания нужного времени включения { timer_tick++; if (timer_tick == dim_time) { digitalWrite(PIN_LOAD, HIGH); timer_tick = 0; } } void zero_crosss() { digitalWrite(PIN_LOAD, LOW); timer_tick = 0; } void loop() { int val = analogRead(A0); //потенциометр dim_time =map(val, 0, 1023, 0, 20); //масштаб от 0-20 мс - период полуволны }
Идея простая от пересечения через ноль выключаем симистор на определенный период (0 - 20 мс - это время полуволны), потом включаем симистор до следующего перехода через 0. Например, если задать 10 мс, то лампа должна светиться в полнакала. Шаги такие:
1. ловим ноль по внешнему прерыванию, закрываем симистор сбрасываем счетчик миллисекунд в 0
2. таймер начинает отсчитывать миллисекунды и по достижении заданного интервала диммирования открывает симистор. Возвращаемся к шагу 1.
3. Профит.
Алгоритм вроде очень стройный, но только вот профита нет, видимо какой-то момент упускаю или с логикой что-то не так. Прошу помочь разобраться что тут не так?
Уточнюсь: симистор не открывается вообще
А если просто тупо (хоть в сетапе) исполнить digitalWrite(PIN_LOAD, HIGH);, он открывается? Вы проверяли?
Кстати, какой контроллер? 328?
Если он, то коду.
1. Строка 24. Кто, когда и при каких обстоятельствах возвращает пин PIN_LOAD в состояние LOW. Снаружи этого не сделать, т.к. он OUTPUT. Так где он становится LOW? Похоже, нигде. Тогда какой вообще смысл в прерывании? Достаточно было сделать его HIGH в сетапе.
3. Нулевой таймер до Вас настраивала ардуиновская среда и она много чего напихала в регистры. чего Вам не нужно. Потому Вам надо сконфигурировать все биты так, как Вам надо. Это означает, что никаких |= в строках 12-15 быть не должно. Только прямые присваивания "="
4. Никогда не работайте вслепую! Для проверки по частям, просто дергайте какой-нибудь левый пин в обработчике прерываний и посмотрите осциллографом (или частотометром) дергается ли он и с какой частотой. Хоть будете уверены, что с таймером не ошиблись.
5. В строке 13 нужно FA вместо F9
Пытаюсь сделать простой диммер для ламппочки накаливания 220 В.
Идея простая от пересечения через ноль выключаем симистор на определенный период (0 - 20 мс - это время полуволны), потом включаем симистор до следующего перехода через 0.
Я чего-то не понял, какой смысл в таком диммере? Чем он будет отличаться от обычного диммера с использованием динистора? И там и тут срезается начало полуволны.
Я бы еще понимал, когда наоборот - при переходе через ноль включаем симистор и через время выключаем. За счет этого избавляемся от неприятностей, которыми грешит обычный диммер.
Евгений, спасибо за ответ!
По порядку тоже отвечу.
1. как обычный ключ все работает (digitalWrite HIGH работает). В LOW его перводит функция по внешнему прерыванию от срабатывания детектора нуля на 2 пине (zero_crosss). детектор нуля дает HIGH на 2-й пин в момент перехода через этот самый ноль.
2. dim_time, точно надо поставить volatile. хотя он меняется только в одном месте...
3 и 5. честно стырил код с уроков, так как под мои цели настройки вроде как раз. Моя вина, уже туго соображаю. попробую Ваш вариант.
4. действительно не подумал тупо подергать.
А в целом алгоритм рабочий? Я боюсь, что рассматриваю идеальную модель, на самом деле наверное может влиять например время закрытия оптопары на детекторе при переходе через ноль или еще какие-то факторы...
vk007, дак это тоже можно сделать, если с начала по переходу включать, а потом выключать. HIGH на LOW поменять местами да и все... Это в целом не суть. для меня главное алгоритм рабочий
А в целом алгоритм рабочий?
Не знаю, скетч-то, как выяснилось, неполный, т.к., например,
В LOW его перводит функция по внешнему прерыванию
а функции-то этой и нету :(
если с начала по переходу включать, а потом выключать. HIGH на LOW поменять местами да и все...
С этого места можно поподробней?))))
vk007, подскажите что погуглить что за проблемы могут быть
bwn, в zero_cross write HIGH, в функции таймера write LOW??? что может пойти не так? =)
vk007, подскажите что погуглить что за проблемы могут быть
Та чего там гуглить, включение нагрузки не в момент перехода нуля с минимальной помехой, хотя по мне, что совой об пень, что пнем об сову, подключу я мощную нагрузку или отключу, один хрен помеху поймаем. ИМХО.
Да как же нету а zero_crosss привзанная к прерыванию на RISING пин 2?
bwn, в zero_cross write HIGH, в функции таймера write LOW??? что может пойти не так? =)
Симистор не транзистор, если включился, то хрен отключится, пока силовое напряжение не снимешь.
bwn, в zero_cross write HIGH, в функции таймера write LOW??? что может пойти не так? =)
Вам предлагают не полуволны на середине резать, а пропускать их через одну, две и тд. чтобы возмущения в силовой сети не порождать.
Вы хотите сказать, что если я запишу LOW в пин управления симистором, то он не выключится? Мой выключается честно-честно. И щас у меня моск (остатки) взорвется наверное
Тогда ты не понимаешь, как работает симистор. Выключается он не от LOW, а када синус через 0 проходит
bwn, в zero_cross write HIGH, в функции таймера write LOW??? что может пойти не так? =)
Вам предлагают не полуволны на середине резать, а пропускать их через одну, две и тд. чтобы возмущения в силовой сети не порождать.
Думаю это тоже осуществимо с парой дополнительных флагов, пытаюсь с малого начать. Чтоб хоть что-то получилось
Тогда ты не понимаешь, как работает симистор. Выключается он не от LOW, а када синус через 0 проходит
Пажди, Семен. Мы еще не выяснили - честный у него Си или как у илита.
Ну акей. Паду тогда квасить, пора уже
Но всеравно, ставлю его чесный С против двух бутылок моего срецтва, что человек за симисторы знает не все.
Тогда ты не понимаешь, как работает симистор. Выключается он не от LOW, а када синус через 0 проходит
Чо-то видимо да не понимаю. Один пишет в нуле он закрывается другой что он открывается))) Включаю я симистор по HIGH на оптопару котрая замыкается на управляющую ногу симистора (оптопара MOC3021). Симистор открывается. подаю на оптопару LOW - оптопара размыкается и сисмистор закрывается на переходе через ноль так?
Народ, хорош прикалыватся, ато мне придется тоже бутылку средство доставать. Печально мне, я новичок а новичка обидеть каждый может)
Тогда ты не понимаешь, как работает симистор. Выключается он не от LOW, а када синус через 0 проходит
Запугали меня уже, я даже твой ответ неправильно прочитал ( Да все верно, это я понимаю
Включается он у вас по HIGH, но не на нуле, а определенном минимальном напряжении, по этой причине ни один симисторный диммер не отдает 100% мощности. А отключается, да, опять таки на определенном минимальном напряжении. Останется HIGH, выключится и снова включится.
Ну, вам же пишут - симистор откроется по HIGH, закроется в переходе через ноль, невзирая на звания. LOW можете сразу подать после HIGH - ему пофигу уже.
Да как же нету а zero_crosss привзанная к прерыванию на RISING пин 2?
Виноват, с пьяных глах не заметил :(
В общем с алгоритмом включения нагрузки, тут пограмотнее меня люди подключились.
А по поводу настройки таймера - заменяйте |= на = чтобы вычистить все ьиты, которые туда среда внесла (но, кстати, Вы понимаете, что таким образом Вы убиваете функции типа millis, delay и всё, что на 0-ом таймере живёт?) И как проверить работает ли прерывание, я Вам идею дал, проверяйте.
Простейший силовой ключ moc3021 и сисмистор BTA 146-800. подаю HIGH - лампочка горит не тухнет. Или он закрывается но тут же открывается опять?
Да как же нету а zero_crosss привзанная к прерыванию на RISING пин 2?
Виноват, с пьяных глах не заметил :(
В общем с алгоритмом включения нагрузки, тут пограмотнее меня люди подключились.
А по поводу настройки таймера - заменяйте |= на = чтобы вычистить все ьиты, которые туда среда внесла (но, кстати, Вы понимаете, что таким образом Вы убиваете функции типа millis, delay и всё, что на 0-ом таймере живёт?) И как проверить работает ли прерывание, я Вам идею дал, проверяйте.
Это понимаю. Читал, подумал что если в скече не юзаются делэи и прочее стандартное то ничего страшного если |=
Простейший силовой ключ moc3021 и сисмистор BTA 146-800. подаю HIGH - лампочка горит не тухнет. Или он закрывается но тут же открывается опять?
Истинно. Если повесите на постоянный сглаженный ток, то отключите только принудительно, выключателем.
Простейший силовой ключ moc3021 и сисмистор BTA 146-800. подаю HIGH - лампочка горит не тухнет. Или он закрывается но тут же открывается опять?
Истинно. Если повесите на постоянный сглаженный ток, то отключите только принудительно, выключателем.
Ну вот спасибо дошло до меня. Это учту. и про 100% мощности тоже понял что не получиться, тем не менее есть ли замечания по алгоритму ()кроме замечаний Евгения) Пусть и с полуволнами пока
если в скече не юзаются делэи и прочее стандартное то ничего страшного если |=
А если в процедуре прерывания таймера по сравнению в конце поставить TCNT0 = 0xFF то и delay и millis работать будут. Чучуть врать будут, да, но не критично
И вот еще. Раз пошел такой разовор, то пропуск целой полуволны в принципе с симистором не возможен или мгновенное закрытие/открытие можно назвать "пропуском полуволн"?
если в скече не юзаются делэи и прочее стандартное то ничего страшного если |=
А если в процедуре прерывания таймера по сравнению в конце поставить TCNT0 = 0xFF то и delay и millis работать будут. Чучуть врать будут, да, но не критично
delay мне религия не позволяет использовать а milis я заменю своим таймером легко
Возможен, только для регулировки света этот метод не подходит и там уже можно х-ней не маяться, а поставить моську с ZG и рулить по времени. ИМХО.
Это понимаю. Читал, подумал что если в скече не юзаются делэи и прочее стандартное то ничего страшного если |=
Там, в МК, есть еще Timer1 и Timer2. Используйте их и тогда миллис будет мягким и шелковистым. А если сразу начнете в прерывании делать HIGH только на каждой 10-й полуволне, то получите свои проценты, попадающие в нагрузку, полагаю. И с таймерами морочаться не будете.
моську с ZG
Это кто? MOC с ZERO CROSS типа 3061?
Это кто? MOC с ZERO CROSS типа 3061?
Угу.
Там, в МК, есть еще Timer1 и Timer2. Используйте их и тогда миллис будет мягким и шелковистым. А если сразу начнете в прерывании делать HIGH только на каждой 10-й полуволне, то получите свои проценты, попадающие в нагрузку, полагаю. И с таймерами морочаться не будете.
Timer1 и Timer2 тоже свое назначение имеют по шимам если правильно помню. timer0 только для подсчета мс мне нужен и дерганья ноги
Друзья, всем спасибо за помощь, за ликбез! Завтра буду пробовать, а потом опять приду уж не обессудьте
Тиристор или симистор закрываются когда ток через них становиться меньше тока удержания. Для лампочки или нагревателя это почти соответствует нулю напряжения, для индуктивных нагрузок - нет. Если есть Zero Cross в цепи управления, то тиррристор откроется с началом следующего периода тока сети, независимо от того в какой момент времени и какой длительности будет импульс управления во время текущего периода. В текущем не откроется. Не подходит для фазового управления. Если метод управления фазовый, то тиристор открывается после подачи импульса управления. Задержка включения зависит от тока в цепи управления. Чем больше ток, тем быстрее включится тиристор. Последнее важно с точки зрения обеспечения минимального и максимального открытия тирристора. Чем уже импульс управления, тем шире углы регулирования, но надо больше тока. Тут главное не сжечь цепи управления. Также важна схема контроля перехода тока (не напряжения!!!) через ноль. Чем точнее схема выдает импульс привязки к нулю тока, тем шире угол регулирования. Это собственно все соображения для програмирования диммера. Т.е. по приему импульса синхронизации заряжаем таймер на время t=0-10 мс или два канала - один на угол открытия, второй угол открытия + длительность импульса управления . По срабатыванию таймера устанавливаем единицу в управление и заряжаем таймер на длительность импульса управления и (или ждём второй канал) выключаем импульс управнения. Заряжать таймеры можно по разному. Главная идея обеспечить в прерывании таймеров задержку и импульс управления.
Схему синхронизации лучше делать как то так http://www.3e-club.ru/view_full.php?id=14&name=zero-cross
http://arduino.ru/forum/programmirovanie/pomogite-porulit-tiristorom#comment-337384 Вот тут мне помогали, все работает.
И время 20мс в корне не правильно, период полуволны 10мс
тоько хотел написать что получволна это 10 мс, а у автора получается отрезает один кусочек от двух полувол.
я вот только создал тему и тоже есть несколько вопросов. http://arduino.ru/forum/proekty/upravlenie-elektro-dvigatelem-ot-stiralnoi-mashinki-s-podderzhaniem-oborotov
добавлю сюда
Я вообще не уверен нужны ли тут таймер и прерывания.
Таймеры и прерывания нужны, если нужно иметь управление не просто крутилкой, а программно. Обмениваться информацией и каждый период сети точно выдерживать тайминг без прерываний не получится.
Таймеры и прерывания нужны, если нужно иметь управление не просто крутилкой, а программно. Обмениваться информацией и каждый период сети точно выдерживать тайминг без прерываний не получится.
Мы так то тут простой диммер мутим. Он как нибудь без таймеров поработает и прерываний.
Таймеры и прерывания нужны, если нужно иметь управление не просто крутилкой, а программно. Обмениваться информацией и каждый период сети точно выдерживать тайминг без прерываний не получится.
Та ладно, просветите.
Можно и простой. Но тот код, что приведён в #41, имеет склонность к дёрганию на 1 мс фазы управления. Если это нормально, то да пусть. Имеет право на существование. Мне кажется простой как раз с таймерами и прерываниями - думать не надо. Зарядил таймер и он сам отработает.
Действительно косяк мой еще один. поделил млин 1000 на 50 и решил что 20, а пополам забыл... в отпуск надо походу, туплю. но алгоритм работает, правда как паралитик. но все же он мне больше нравится чем то что в интернете находил. покручу еще...
тоько хотел написать что получволна это 10 мс, а у автора получается отрезает один кусочек от двух полувол.
я вот только создал тему и тоже есть несколько вопросов. http://arduino.ru/forum/proekty/upravlenie-elektro-dvigatelem-ot-stiralnoi-mashinki-s-podderzhaniem-oborotov
добавлю сюда
Думается можно и Falling, все равно надо учитывать период скачка имхо. либо мудрить схему детектора с минимальным периодом перехода (я такую видел в интернетах повторить не смог из-за отсутствия компонентов). По второму вопросу я рассудил так: обработка прерываний гораздо меньше по времени чем собственно их выполнение, даже если процессору придется отложить выполнение все равно это ничтожно малое время. Пока на таких домыслах...
и да получается на 10%, диммер работает но хуево. моргает лампочка на значениях близких к минимуму. это наверное как раз 20 vs 10. я еще отпишусь. Спасибо за поддержку!