9. Детектор нуля на AVR микроконтроллере

Предположим что перед нами стоит задача, знать, когда синусоидальное напряжение в розетке переходит через ноль. Для этого можно использовать в МК внешнее прерывание INT0 или INT1. Схема будет не сильно сложной.

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

Начнем со второй схемы, так как трансформатор у меня есть. Да и программа обоих схем будет отличаться буквально одной строчкой. Итак вот пример кода детектора нуля для второй схемы.

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

//Битовые макросы
#define ClearBit(reg, bit)       reg &= (~(1<<(bit)))
#define SetBit(reg, bit)          reg |= (1<<(bit))
#define BitIsClear(reg, bit)    ((reg & (1<<(bit))) == 0)
#define BitIsSet(reg, bit)       ((reg & (1<<(bit))) != 0)

//Макроопределения
#define LED PC4
#define PORT_LED PORTC
#define DDR_LED DDRC

#define BUTTON PD2
#define PORT_BUTTON PORTD
#define PIN_BUTTON PIND
#define DDR_BUTTON DDRD

ISR(INT0_vect)//А это и есть наш прерывание INT0 (обработчик прерывания)
	{
		SetBit(PORT_LED,LED);//Включаем выход
        _delay_us(100);
		InvBit(MCUCR,ISC00);//Каждый раз меняем INT0 то на спадающий то на нарастающий фронт.
	}

int main(void)
{
	DDR_LED = 1<<LED;//Вывод PC4 будет выходом
	PORT_LED= 0<<LED;//Выключим выход.
	
	DDR_BUTTON = 0<<BUTTON;  //Вывод PD2 будет входом
	PORT_BUTTON= 0<<BUTTON;  //Выключим подтяжку 
	
	MCUCR=(0<<ISC11)|(0<<ISC10)|(1<<ISC01)|(0<<ISC00);//Настроим прерывание INT0 по спадающему уровню.
    GICR=(0<<INT1)|(1<<INT0);//Разрешили работу только прерывания INT0.

	sei();//Включили глобальный флаг резрешения прерываний
	
    while(1)
    {
		ClearBit(PORT_LED,LED);//Выключаем выход
    }
}

Загружаем программу в нашу отладочную плату AtmegaBoard32 собираем схему и проверяем осциллографом.

Сперва щуп осциллографа подключаем к выводу INT0(PD2) и наблюдаем такую картину

Все так как и должно быть. На вывод МК INT0 мы подали переменное синусоидальное напряжение 17Вольт(такое оказалось на вторичной обмотке) через резистор в 1мОм. И видим что отрицательный полупериод полностью срезается защитным диодом внутри МК. Положительный полупериод есть, но его верхушка тоже срезана на уровне 5 вольт защитным диодом в МК. Второй щуп подключаем к выводу PC4. Светодиод туда вешать бессмысленно, то что он загорается на 100мксек во время пререхода синусоиды через 0 это факт, но глазами мы этого не увидим. Поэтому лучше довериться осциллографу.

Как видим при переходе через ноль видны тонкие иголки на выводе PC4. Из чего можно сделать вывод что наша схема и программа работают. Теперь зная точку перехода через 0 можно к выводу PC4 подключить тиристор или симистор и управлять высокими напряжениями и токами в нагрузке, будь то лампочка или двигаетль. Впрочем данная идея уже реализована в регуляторе мощности управляемым радиомодулем или вот в этом симисторном регуляторе мощности. Программа для самой верхней схемы аналогична, единственное что в обработчике прерывания INT0 надо убрать строку InvBit(MCUCR,ISC00);

Напоследок возникла идея, а что если подать синусоиду не на 50 Гц как в сети, а скажем 50кГц. Частота выше в 1000 раз, справится ли МК с задачей детектирования? Генератора синусоидального сигнала у меня нету, но зато сам МК может выдавать ШИМ сигнал в 50кГц легко. А то что это не синусоида, это не проблема. Вывод OC1A(PD5) настроил на ШИМ сигнал частотой 62500Гц через Timer1, как это и что это будет рассказано в другой раз. Перемычкой подал сигнал с ШИМ вывода на INT0 и получилось вот что.

Тыкаем щупом в PC4 и INT0 и видим что:

Даже на высокой частоте МК справляется со своей задачей, однако иголки (синие) несколько отстают от спадающих и поднимающихся фронтов ШИМ сигнала. При более пристальном рассмотрении видим что

отставание ровно 1.5мксек что составляет 24 такта кварца МК. Если написать данную программу на ассемблере, то думаю что отставание можно было бы значительно сократить. Как видим микроконтроллер это быстрая штука, однако не сверх быстрая.