диммер MOC3021 + BT136

Все прочитали, вроде даже поняли, взяли паяльник - а нифига не получается? Скорее сюда! Поможем. Чем можем...
Ответить
Родился
Сообщения: 1
Зарегистрирован: Пн фев 15, 2016 21:23:07

Сообщение bess_gusev »

Доброго времени суток. Прошу помощи в изгнании диавола из кода!!1
Пытаюсь соорудить диммер на MOC3021 + BT136, детектор нуля повесил на обработчик внешнего прерывания. Суть проблемы в чем: Схема ведет себя так, будто оптосимистор с zero-cross: если подать сигнал на оптопару точно в момент перехода нуля - лампа загорается. Если сигнал подать чуть с задержкой относительно перехода - симистор не открывается. Собственно, почему?

Код: Выделить всё

void EXTI4_15_IRQHandler(void)
{  
		HAL_Delay(2);   // c этой задержкой лампочка не горит
                HAL_GPIO_WritePin(GPIOA, GPIO_PIN_14, GPIO_PIN_SET);	
                HAL_Delay(1);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_14, GPIO_PIN_RESET);
		HAL_NVIC_ClearPendingIRQ(EXTI4_15_IRQn);
		HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
}
Реклама
Родился
Сообщения: 1
Зарегистрирован: Чт янв 12, 2017 15:59:06

Сообщение msaygak »

Подниму-ка старую тему.
Проблема с обработкой прерываний или таймерами.


Собрал вот такой диммер, подключенный к ардуино нано (atmega328) детектором нуля на Digital2 и гейтом триака на Digital9.

Изображение
Плата
Изображение

логически всё просто -- определяем переход нуля, запускаем таймер на определенное время, ловим переполнение таймера,включаем триак, устанавливаем таймер на макс (65535) минус продолжительность импульса, ловим переполнение таймера, отключаем гейт триака.

Всё нормально, если диммером управлять через радиоинтерфейс (на nrf24) или просто в бесконечном цикле прописывать значения от 70 о 500 в output compare register.

Если же параметр "скважности" брать с потенциометра, как в коде ниже, то лампочка на нагрузке моргает. То есть яркость её меняется правильно (70 -- яркое свечение, 500 -- выкл), но она постоянно моргает. Причем это проблема явно не связана с оптроном или тиаком -- на d9 припаян светоиод и он тоже моргает.
Если вывести на serial значения от analogRead (A0) и значения, которые попадают в OCR1A то с ними все в порядке -- считываются и мапятся более-менее точно.

Такое впечатление, что обработка analogRead со стороны avr использует таймеры, которые я со своей стороны дергаю из прерывания.

Кто знает как этот analogRead работает?
В принципе вопрос скорее "на поговорить", т.к. потенциометр там стоит временно и в дальнейшем будет заменен на энкодер.

Код: Выделить всё


#include <avr/io.h>
#include <avr/interrupt.h>

#define DETECT 2  // детектор нуля
#define GATE 9    // гейт триака
#define PULSE 10   // продолжительность импульса на триак

const int analogInPin = A0;  // Потенциометр
int sensorValue = 0;        // читаем с потенциометра
int outputValue = 0;        // пишем в OCR
void setup(){

  pinMode(DETECT, INPUT);    
  digitalWrite(DETECT, HIGH); 
  pinMode(GATE, OUTPUT);   

  // Установка таймера
  OCR1A = 100;     
  TIMSK1 = 0x03;    //включаем прерывания comparator A и overflow 
  TCCR1A = 0x00;    
  TCCR1B = 0x00;   


  // прерывание на детектор нуля
  attachInterrupt(0,zeroCrossingInterrupt, RISING);    
  

}  


 // Переход нуля
void zeroCrossingInterrupt(){ 
  TCCR1B=0x04; //Делитель 256 для таймера
  TCNT1 = 0;   //стартуем с нуля
}

ISR(TIMER1_COMPA_vect){ //Компаратор 
  digitalWrite(GATE,HIGH);  //включаем нагрузку
  TCNT1 = 65536-PULSE;      //устанавливаем значения для overflow inetrrupt
}

ISR(TIMER1_OVF_vect){ //timer1 overflow
  digitalWrite(GATE,LOW); //выключаем триак
  TCCR1B = 0x00;          //выключаем таймер
}

void loop(){ 
  sensorValue = analogRead(analogInPin);
  outputValue = map(sensorValue, 0, 1023, 70, 500);
  //Serial.println (outputValue);
  OCR1A = outputValue;
}
Вложения
dimmer.png
(25.63 КБ) 544 скачивания
Реклама
Ответить

Вернуться в «Практика»