Сетевой ФИ димер - временнОе реле.
- Войдите на сайт для отправки комментариев
Доброго времени суток.)
Мужики, подскажите, что не так. Третий вечер мозг ломаю и уже не знаю что не знаю.
нужно сделать симисторный диммер, который каждые 12 часов будет вкл/выкл нагрузку в сети 220В на треть мощности.
по железу
есть датчик ноля на 814(работает. при пересечении ноля - выдает импульс. сампаялопал)
"драйвер" симистора на МОС-ьке(работает, как и симистор. сампаялопал)
PRO Mini 5V 16MHz x2(разные кварцы, большой и маленький, ВовГат и еще-что)
ЛАТР
под рукой осциллограф 1канал 0-16МГц
и еще куча барахлишка и инструмента, которое собралось за бОльшую часть жизни, в последствии увлечения электроникой.
по программе.
на сколько понял, логика простая. но есть несколько(много) способов реализации. решил пробовать делать так:
ловим импульс на INT0 от датчика ноля и в прерывании запускаем таймер, прерывания которого будут повыше в приоритете в таблице векторов - т.е. второй(третий) таймер.
в прерывании таймера2 считаем задержку до подачи импульса на управляющий электрод симистора и длительность импульса. после чего останавливаем таймер. чем больше задержка до подачи импульса, тем, соответственно, меньше мощность в нагрузке. длительность импульса от 10мкс до 150мкс в зависимости от симистора.
ну и сам опытный образец проги (простите за не причесанность))
volatile unsigned int timer2count;
volatile unsigned int dimmingLVL = 1; //1 == 0.00001c 1000==10ms задержка до импульса на УЄ
volatile unsigned int pulseToTriac = 2; //1 == 0.00001c длительность импульса на УЭ симистора
void setup() {
//enable global interrupt
sei();
pinMode(2, INPUT); //ZD input
pinMode(13, OUTPUT); //Triac
attachInterrupt(0, zerroDetect, RISING); //zeroDetect ловим импульс от датчика ноля и перемещаемся по прерыванию в zerroDetect()
//********TIMER2 Configuration**********
//activate CTC mode
bitSet(TCCR2A, WGM01); //TCCR2A |= (1 << WGM01);
//set value to compare register
OCR2A = 0b10100000; //160
}
/////////////////////////////////////////////////////////////
void loop() {
}
//////////////////////////////////////////////////////////////////
void zerroDetect() {
//reset register value
TCNT2 = 0b00000000; //чистим считалку на всякий случай
//enable compare match interrupt on TIMER2
bitSet(TIMSK2, OCIE2A); //разрешаем прерывания по совпадению таймера2
//prescaller configuration. start timer.
TCCR2B |= (1 << CS20);//no presc //запускаем таймер2 без прескаллера и ждем прерывание уже от него
}
/////////////////////////////////////////////////////////////////
//TIMER2 CTC interrupt handller
ISR (TIMER2_COMPA_vect)
{
timer2count++; //считаем количество срабатываний if (timer2count == dimmingLVL) { //подаем импульс на симистор
//start pulse
digitalWrite (13, HIGH);
}
if (timer2count == dimmingLVL + pulseToTriac) { //считать наверное лучше отдельно в переменную и подставлять сюда ее длясравнения
//end of pulse
digitalWrite (13, LOW);
//disable TC2
bitClear(TCCR2B, CS20); //set no clock sorce mode
//disable compare match interrupt on TIMER2
bitClear(TIMSK2, OCIE2A); timer2count = 0; }
}
частота срабатываний(тиков таймера) 16МГц / 160(OCR2A) = 100 000Гц 1/100 000 = 0,000010 т.е.10микросекунд
на один полупериод синусоиды будет приходится 0,010 / 0,000010 = 1000 тиков это и должно быть разрешением регулировки Pload/1000tik мне хватит
только вот программа странно работает. если верить осцилографу то цифра один в переменной pulseToTriac в реальности равна 2 миллисекунды, а цифра 2 - 4 миллисекунды
т.е. осцил на ноге 13 показывает меандр с периодом 10мс и длину управляющего импульса 4мс если в pulseToTriac записать 2. а должно быть 20 микросекунд потому что таймер должен тикать с частотой 16МГц / 160(OCR2A) = 100 000 Гц даже без предварительного деления частоты.
по ходу что-то не так с кварцем, или ардуино как-то перенастроило АВР-ку. в общем, я уже не знаю что еще попробовать.
аппаратное прерывание работает. моргал светодиодом каждые 100 полупериодов. а таймер чет не осилю.
подскажите, что я упустил, что я не знаю?)
P.S. разработчик редактора этого форума явно не знает что такое когнитивное искажение - "проклятие знания" и подобные.
остальные надеюсь, поймут.
блть в строке 42 две строки. происки редактора форума. почему первый пост нельзя отредактировать?
Таймер ДО Вас настраивает среда Ардуино. Например, в регистр TCCR2B она пихает бит CS22. Вы же потом по ИЛИ добавляете туда ещё CS20 и получаете делитель не 1, как ожидаете, а 128. Вот и Ваша ошибка как раз в сто раз - всё точно, как доктор прописал.
Кстати, в TCCR2A она пихает WGM20, который Вам, как я понимаю, тоже там нахрен не нужен.
Настраивайте таймер полностью, прописывая все биты - не надейтесь, что там нули. Тогда всё получится.
Кстати, в строке №17 замените на WGM21. На скорость не влияет, но неаккуратненько :-)
блть в строке 42...
Ознакомьтесь вот с этой темой :-)
Ознакомился
простите если было не приятно, я не хотел.)
по поводу строки 17... эх, стыдоба. прост я начинал с нулевого таймера. фантомные боли..))
Да, нет, Вы чего - это тут шутки такие (как и та тема сама по себе) :-)))
Получилось с таймером?
https://playground.arduino.cc/Main/ACPhaseControl/
#include <avr/io.h> #include <avr/interrupt.h> #define DETECT 2 //zero cross detect #define GATE 9 //TRIAC gate #define PULSE 4 //trigger pulse width (counts) int i=483; void setup(){ // set up pins pinMode(DETECT, INPUT); //zero cross detect digitalWrite(DETECT, HIGH); //enable pull-up resistor pinMode(GATE, OUTPUT); //TRIAC gate control // set up Timer1 //(see ATMEGA 328 data sheet pg 134 for more details) OCR1A = 100; //initialize the comparator TIMSK1 = 0x03; //enable comparator A and overflow interrupts TCCR1A = 0x00; //timer control registers set for TCCR1B = 0x00; //normal operation, timer disabled // set up zero crossing interrupt attachInterrupt(0,zeroCrossingInterrupt, RISING); //IRQ0 is pin 2. Call zeroCrossingInterrupt //on rising signal } //Interrupt Service Routines void zeroCrossingInterrupt(){ //zero cross detect TCCR1B=0x04; //start timer with divide by 256 input TCNT1 = 0; //reset timer - count from zero } ISR(TIMER1_COMPA_vect){ //comparator match digitalWrite(GATE,HIGH); //set TRIAC gate to high TCNT1 = 65536-PULSE; //trigger pulse width } ISR(TIMER1_OVF_vect){ //timer1 overflow digitalWrite(GATE,LOW); //turn off TRIAC gate TCCR1B = 0x00; //disable timer stopd unintended triggers } void loop(){ // sample code to exercise the circuit i--; OCR1A = i; //set the compare register brightness desired. if (i<65){i=483;} delay(15); }почему первый пост нельзя отредактировать?
Премудрые студиозы, получив решение курсового, редактировали его в ноль. И оставались висящие между небом и землей темы.((((
на самом деле что-то пошло не так... я психанул, нашел несколько кандёров для конденсаторного БП на время, пока буду разбираться с симистором.
сейчас же достаточно просто вкл/выкл симистор, а кандеры гасят лишнее. так-что можно перейти к часам и расписанию по которому этот симистор вкл/выкл.
это некая костяшка программки которая удовлетворяет минимальные требования. время считаю от внешнего кварца. старался делитель выставить максимально большим что бы больше времени основной программе оставить. фазо-импульсную регулировку и модуль RTC оставлю для версии 1.1)) хах))
в общем, буду счастлив, если кто ни будь глянет.. может я накосячил фатально-фундаментально и часы будут кривыми как && мои руки?)
16МГц/1024(предделитель)=15625/125(OCR2A=124)=125Гц = 1с; или я что-то напутал?
главное что бы часы шли ровно. если основная программа где-то чуть еле подвиснет то это не страшно.
volatile byte timer2CTCInterruptCount; volatile byte secondCount; volatile byte minuteCount; volatile byte hourCount; volatile byte dayCount; byte nowSecond = 0; byte nowMinute = 0; byte nowHour = 0; byte nowDay = 0; byte valueForPWM = 0; void setup() { pinMode(13, OUTPUT); //SET CLOCK// установка текущего времени. значения для начала отсчета timer2CTCInterruptCount = 0;//предварительный сброс счетчика одной секунды secondCount = 13; minuteCount = 16; hourCount = 23; dayCount = 0; //TIMER2 CTC INTERRUPT CONFIG //activate CTC mode for TC2 TCCR2A = 0b00000010; //COM2A1 COM2A0 COM2B1 COM2B0 – – WGM21 WGM20 //set value to compare register OCR2A = 0b01111100;//124(125) //reset register value //prepare register to count TCNT2 = 0b00000000; //enable compare match interrupt for TIMER2//CTC Mode TIMSK2 = 0b00000010;//– – – – – OCIE2B OCIE2A TOIE2 // //q_freg prescaller configuration. start timer. TCCR2B = 0b00000111;//ON//1024 // FOC2A FOC2B – – WGM22 CS22 CS21 CS20 //reset timer control register//OFF// CS22&&CS21&&CS20 == 0 - TC2 //TCCR2B = 0b00000000; //OFF//FOC2A FOC2B – – WGM22 CS22 CS21 CS20 sei(); } ISR (TIMER2_COMPA_vect) { //timer tik increment timer2CTCInterruptCount++; if(timer2CTCInterruptCount == 125){// secondCount++; timer2CTCInterruptCount = 0; } if(secondCount == 60){ minuteCount++; secondCount = 0; } if(minuteCount == 60){ hourCount++; minuteCount = 0; } if(hourCount == 24){ dayCount++; hourCount = 0; } } void loop() { //bufering MC Clock Values valueForPWM = timer2CTCInterruptCount;//0...125 nowSecond = secondCount; nowMinute = minuteCount; nowHour = hourCount; nowDay = dayCount; //Day Plan if(nowHour == 0){ digitalWrite(13, LOW); } if(nowHour == 1){ digitalWrite(13, LOW); } if(nowHour == 2){ digitalWrite(13, LOW); } if(nowHour == 3){ digitalWrite(13, LOW); } if(nowHour == 4){ digitalWrite(13, LOW); } if(nowHour == 5){ digitalWrite(13, LOW); } if(nowHour == 6){ digitalWrite(13, HIGH); } if(nowHour == 7){ digitalWrite(13, HIGH); } if(nowHour == 8){ digitalWrite(13, HIGH); } if(nowHour == 9){ digitalWrite(13, HIGH); } if(nowHour == 10){ digitalWrite(13, HIGH); } if(nowHour == 11){ digitalWrite(13, HIGH); } if(nowHour == 12){ digitalWrite(13, HIGH); } if(nowHour == 13){ digitalWrite(13, HIGH); } if(nowHour == 14){ digitalWrite(13, HIGH); } if(nowHour == 15){ digitalWrite(13, HIGH); } if(nowHour == 16){ digitalWrite(13, HIGH); } if(nowHour == 17){ digitalWrite(13, HIGH); } if(nowHour == 18){ digitalWrite(13, LOW); } if(nowHour == 19){ digitalWrite(13, LOW); } if(nowHour == 20){ digitalWrite(13, LOW); } if(nowHour == 21){ digitalWrite(13, LOW); } if(nowHour == 22){ digitalWrite(13, LOW); } if(nowHour == 23){ digitalWrite(13, LOW); } }я вот не рискну браться. может не знаю где лежит.. как вообще выглядит корректная инициализация, настройка таймера на СТС прям по пунктам по порядку? или тут нет однозначности? каждый как-то делает по своему что-ли. срачи разводят..
нужно сделать симисторный диммер, который каждые 12 часов будет вкл/выкл нагрузку в сети 220В на треть мощности.
А зачем с таймером мутить если уже есть millis(). Используйте его для учета секунд/минут/часов.
SLKH, что за вопрос?)
asam, ну я тут несколькими постами выше словил граблями в виде высокого уровня абстракции. чуть ниже - чуть интересней.) ну и более гибко, явно, если писать понятно. может мне лучше на форум где сидят в атмел студио?) или как||куда?)
тут порог вхождения ниже, но мне кажется что все стремительно скатывается к AVR
часы то хоть ровные получились?))
а тут есть некий toggle pin? как адекватней вывести частоту срабатывания прерываний от таймеров на ножку что бы осциллом частоту посмотреть?
asam, ну я тут несколькими постами выше словил граблями в виде высокого уровня абстракции. чуть ниже - чуть интересней.)
Ну это не от уровня абстракции проблема, а от незнания матчасти.
Флаг вам в руки.
на сколько я понимаю, события, вызванные прерыванием, при равных условиях, должны "возникать" с частотой прерываний. мне кажется через If-ы будет криво. или я не прав? стесняюсь спросить, вы мне намекаете каждое срабатывание подвигать что-то типа unsigned long = 010101010101.....010101 на ноге?
не согласен по поводу "не знания мат части". это не очевидно что ардуина настраивает железо под себя даже если "явно" не нужно. думаю если бы подход был бы изначально на уровне регистров, где нужно явно указывать что-куда, то подобных граблей бы не возникло.
ну это не плохо. это хорошо если уметь этим пользоваться.
а что если
byte val = 0b0000 0000;
ISR (TIMER2_COMPA_vect){
val = ~val;//поразрядная инверсия
PORTB = val;
}
грубовато, но по идее должно быть ровненько.))
а тут есть некий toggle pin?
В даташите написано:
Добрый вечер AlexPython
На 4й странице в схожей теме
"Устройство ФИУ на симисторе (диммер) для Ардуино"
есть схема и скетч по вашему вопросу.