|
Исходник программы:
/*****************************************************
Date : 23.08.2011
Author : Evildesignсобачкаmail.ru
Chip type : ATtiny13A
AVR Core Clock frequency: 4,800000 MHz
*****************************************************/
#include <tiny13a.h>
//Время горения лампы в секундах . Должно быть < 650 секунд.
#define TIME_LIGHT_ON 25U
// Вывод управления лампой
#define LAMP PORTB.0
//voltage limit in relative units for six measurements
#define TH_V 60
volatile unsigned char phase_tick; // Текущий квант в 100мкс в полупериоде // - фактически значение фазы
volatile unsigned char max_measured_phase_tick; // Число вычисленных в полупериоде квантов // по 100мкс для текущей частоты сетевого // напряжения
volatile unsigned char measured_phase_tick; // Число измеренных в текущем полупериоде // квантов по 100мкс для автоподстройки // частоты сетевого
volatile unsigned char light_on; // Флаг- номер кванта в полупериоде при // котором происходит погасание лампы // от 0 до max_measured_phase_tick
volatile unsigned char phase_locked; // Флаг корректного захвата фазы сетевого // напряжения
volatile unsigned int num_half_sin; // Счетчик полупериодов с момента // включения лампы для расчета времени // управления лампой
// Pin change interrupt service routine
// Запускаем механизм включения лампы
interrupt [PC_INT0] void pin_change_isr(void)
{
// Если не было захвата фазы- не включаем
if(phase_locked==0) return;
if(PINB.2==1) return; // Линия внешнего управления. Должна быть притянута к земле.
if(light_on==0) light_on=1;
num_half_sin=0;
}
// Timer 0 output compare A interrupt service routine
// Every 100 us start ADC
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
// Автономно определяем фазу
phase_tick++;
if(phase_tick>=max_measured_phase_tick)
{
phase_tick=0;
num_half_sin++;
}
if(measured_phase_tick<115)measured_phase_tick++;
if(light_on)
{
// Действия по изменению фазы проводим только в начале каждого полупериода
if(phase_tick==0)
{
// Если у нас прошло больше 2500 полупериодов или 2500*10ms=25 секунд, //начинаем отключение
if(num_half_sin>=(TIME_LIGHT_ON*100U))
{
// В начале отключения запрещаем прерывания от входа с микрофона. //Для исключения наводок.
if(num_half_sin==(TIME_LIGHT_ON*100U)) GIMSK=(0<
light_on--;
// В последнюю фазу отключения включаем прерывания от микрофона
if(light_on==0)
{
GIFR=(1<
GIMSK=(1<
}
} else
// Наращиваем фазу включения лампы при запуске
if(light_on10)light_on++;
}
// Управляем лампой в зависимости от ее значения кванта
if (phase_tick==max_measured_phase_tick-light_on)
{
if(light_on<=10) LAMP=0;
else LAMP=1;
}
if (phase_tick>=max_measured_phase_tick-10) LAMP=0;
} else
LAMP=0;
}
// Analog Comparator interrupt service routine
// Возникает при превышении тока через канал MOSFETа
// Сбрасываем состояние и выключаем транзистор
interrupt [ANA_COMP] void ana_comp_isr(void)
{
if(light_on)
{
light_on=0;
num_half_sin=0;
phase_locked=0;
LAMP=0;
}
}
// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
static unsigned char adc_prev;
static unsigned char flag_direction_up; // Флаг перегиба функции напряжения
static unsigned char num_up_samples; // Число монотонно возрастающих сэмплов
static unsigned char num_down_samples; // Число монотонно убывающих сэмплов
unsigned char adc_data;
// Read the 8 most significant bits
// of the AD conversion result
adc_data=ADCH;
if((adc_data0))
{
if (flag_direction_up==0)
{
if (adc_data<=adc_prev)
{
num_down_samples++;
} else
{
if(num_down_samples>=5)
{
num_up_samples=1;
flag_direction_up=1;
} else
{
num_up_samples=0;
num_down_samples=0;
flag_direction_up=0;
}
}
} else
{
if (adc_data>=adc_prev)
{
num_up_samples++;
if(num_up_samples==5)
{
//if the frequency 47,5 to 52,5 Hz, phase locking
if((measured_phase_tick>=95)&&(measured_phase_tick<=105))
{
phase_tick=5;
// average
max_measured_phase_tick=(max_measured_phase_tick+(measured_phase_tick-5))>>1;
phase_locked=1;
}
measured_phase_tick=5;
num_up_samples=0;
num_down_samples=0;
flag_direction_up=0;
}
} else
{
num_up_samples=0;
num_down_samples=0;
flag_direction_up=0;
}
}
} else
{
num_up_samples=0;
num_down_samples=0;
flag_direction_up=0;
}
adc_prev=adc_data;
}
void main(void)
{
// Input/Output Ports initialization
// Port B initialization
// Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out
// State5=T State4=T State3=T State2=T State1=T State0=0
PORTB=0x00;
DDRB=(1<
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 600,000 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=(1<
TCCR0B=(1<
TCNT0=0x00;
OCR0A=0x3C;
OCR0B=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(1<
// Analog Comparator initialization
// Analog Comparator: On
// The Analog Comparator's positive input is
// connected to the Bandgap Voltage Reference
// Interrupt on Falling Output Edge
ACSR=(1<1<1<
ADCSRB=0x00;
// ADC initialization
// ADC Clock frequency: 300,000 kHz
// ADC Bandgap Voltage Reference: On
// ADC Auto Trigger Source: TIM0_COMPA
// Only the 8 most significant bits of
// the AD conversion result are used
// Digital input buffers on ADC0: Off, ADC1: Off, ADC2: On, ADC3: Off
DIDR0 = (1<1<1<1<1<
ADMUX = (1<1<1<1<
ADCSRA = (1<1<1<1<
ADCSRB = (1<1<
// Interrupt on any change on pin PCINT4
PCMSK=(1<
GIMSK=(1<
ACSR=(1<
TIFR0=(1<1<1<
GIFR=(1<
MCUCR=0x00;
max_measured_phase_tick=100; // 100samlpes*100us=10ms //Число квантов по 100мкс в одном полупериоде
// Global enable interrupts
#asm("sei")
for(;;);
}
|
Календарь |
« Май 2024 » | Пн | Вт | Ср | Чт | Пт | Сб | Вс | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
|
Статистика |
|
|