Печать

Изучаем энкодер. Делаем простой RGB контроллер.

Автор: AntonChip Опубликовано . Опубликовано в Программирование на Си

Рейтинг:   / 8
ПлохоОтлично 

Можно ли одной «ручкой» регулировать контрастность ЖКИ, изменять уровни срабатывания исполнительных устройств, выбирать язык меню, включать или выключать опции настроек? Оказывается, можно. И элемент, при помощи которого возможно осуществить все эти регулировки, носит название энкодер. Далее, собственно, мы и будем знакомиться с этим элементом.

По выполняемым функциям и внешнему виду энкодеры напоминают аналоговые потенциометры, но на этом их сходство заканчивается. Области применения энкодеров шире и разнообразнее. Как правило, с появлением цифровых систем ранее применявшиеся внешние элементы управления, такие как переключатели, аналоговые потенциометры с ручками на панелях управления, плохо стыкуются с их основным элементом — микроконтроллером.

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

Энкодер, в зависимости от направления его вращения, формирует два сигнала. Благодаря ним микроконтроллер может определять направление вращения вала энкодера. Всю остальную работу по реализации аналогового потенциометра или переключателя микроконтроллер берет на себя. Отмечу, что по своему исполнению энкодеры весьма разнообразны. Так, например, приведенный на рисунке сверху энкодер имеет механическую «трещотку», что, несомненно удобно для использования его в качестве переключателя. Кроме того, данный энкодер снабжен независимой нормально разомкнутой кнопкой, что оказывается довольно удобно в целом ряде применений. Существуют энкодеры и без «трещоток», которые плавно вращаются. Их удобно использовать в качестве регуляторов уровня вместо аналоговых потенциометров.

Рассмотрим, как осуществляется взаимодействие микропроцессора (микроконтроллера) с энкодером. На микропроцессорное устройство подаются два сигнала с контактов А и В энкодера. Необходимо, чтобы один из них, например, с контакта А, подавался на вход, который формирует прерывания в микроконтроллере по изменению уровня входного сигнала (по перепаду из 1 в 0). Вызывающая программа должна анализировать при этом состояние сигнала В. Так как устройство является механическим и может выдавать в линию «дребезг», то необходимо это учитывать в алгоритме обработки прерывания. Обработчик прерывания будет таким:

ISR(SIG_INTERRUPT0)
{
_delay_us(50);
if((PIND&(1 << PD2))==0)
{
_delay_us(50);
if((PIND&(1 << PD0))==0)
{ 
// вращение по часовой стрелке
// здесь выполняем операцию
}
else
{
// вращение против часовой стрелки
// здесь выполняем операцию
}
}
GIFR |= (1 << INTF0); // очищаем флаг
return;
}

На основе такого механизма сделаем простой RGB контроллер, где яркость каждого цвета можно будет регулировать отдельно. Переключение между цветами производится нажатием кнопки энкодера. Также предусмотрим 3 дополнительных светодиода HL1 - HL3, которые будут индикаторами регулируемого цвета. Схема для нашего примера будет такой:

Изучаем энкодер. Делаем простой RGB контроллер.

Микроконтроллер Atmega8 работает от внутреннего тактового генератора частотой 8МГц. Резисторы R4 - R6 подтягивающие, на всякий случай, подключим и внутренние. Энкодер можно использовать любой с кнопкой, маркировка используемого в проекте неизвестна. RGB светодиод для поверхностного монтажа размера 5050. Полный текст программы ниже:

// Принцип работы энкодера. Управляем RGB светодиодом с помощью энкодера
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h> 

volatile char pwm_counter,pwm_r,pwm_g,pwm_b, button = 0;

// Обработчик прерывания int0
ISR(SIG_INTERRUPT0)
{
_delay_us(50);
if((PIND & (1 << PD2)) == 0)
{
_delay_us(50);
if((PIND & (1 << PD0)) == 0)
{ 

if(button == 0) // уменьшаем красный цвет
{ 
pwm_r--;
if(pwm_r < 1)
pwm_r = 1;
} 

if(button == 1) // уменьшаем зеленый цвет
{  
pwm_g--;
if(pwm_g < 1)
pwm_g = 1;
}

if(button == 2) // уменьшаем синий цвет
{
pwm_b--;
if(pwm_b < 1)
pwm_b = 1;
}
}

else
{
if(button == 0) // увеличиваем красный цвет
{
pwm_r++;
if(pwm_r > 64)
pwm_r = 64;
}

if(button == 1) // увеличиваем зеленый цвет
{
pwm_g++;
if(pwm_g > 64)
pwm_g = 64;
}

if(button == 2) // увеличиваем синий цвет
{
pwm_b++;
if(pwm_b > 64)
pwm_b = 64;
}
}
}
GIFR = (1 << INTF0); // очищаем флаг внешнего прерывания
return;
}	

// прерывание по переполнению Т0
ISR(TIMER0_OVF_vect)
{
if(pwm_counter++ > 63) 
{
PORTB = 0x00;
pwm_counter = 0;
}
if(pwm_counter > pwm_r)
PORTB |= (1 << PB0);
if (pwm_counter > pwm_g)
PORTB |= (1 << PB1);
if (pwm_counter > pwm_b)
PORTB |= (1 << PB2);	
}

// Главная функция
int main (void) 
{
DDRB |= (1 << PB5)|(1 << PB4)|(1 << PB3)|(1 << PB2)|(1 << PB1)|(1 << PB0); // выходы
PORTB = 0x00;
DDRD |= (0 << PD2)|(0 << PD1)|(0 << PD0); // входы
PORTD |= (1 << PD2)|(1 << PD1)|(1 << PD0); // подключаем подтягивающие резисторы

TIMSK |= (1 << TOIE0); // разрешение прерывания по таймеру0
TCCR0 |= (1 << CS00); 

MCUCR |= (0 << ISC00)|(1 << ISC01); // прерывание по заднему фронту INT0(по спаду импульса)

GIFR |= (1 << INTF0);		// очищаем флаг внешнего прерывания
GICR |= (1 << INT0);		// разрешаем внешние прерывания INT0
	
sei(); //глобально разрешаем прерывания

pwm_r = 64; // начальные установки цветов, min яркость
pwm_g = 64;
pwm_b = 64;
 
while(1)
{	 
if((PIND & (1 << PD1)) == 0) // если нажата кнопка
{
while((PIND & (1 << PD1)) == 0){} // ждем отпускания кнопки
button++;
_delay_ms(100);
if(button == 3)
button = 0;
}  
		
if(button == 0)
PORTB |= (1 << PB3);
if(button == 1)
PORTB |= (1 << PB4);
if(button == 2)
PORTB |= (1 << PB5);
}
}

В данном примере используется программный ШИМ, о реализации которого говорилось на прошлых занятиях. Переменная button хранит состояние кнопки, в зависимости от того сколько раз нажата кнопка регулируется определенный цвет и горит его индикатор. Для удобства практического применения такого контроллера необходимо записывать состояние яркости всех цветов в EEPROM, чтобы при выключении питания не настраивать цвета заново.

Файлы:
Проект AVRStudio
Дата 12.06.2012 Размер файла 38.47 KB Закачек 1974

Комментарии  

0 #21 Chip 11.09.2016 23:27
Код:

// Главная функция
int main (void)
{
DDRB |= (1 << PB5)|(1 << PB4)|(1 << PB3)|(1 << PB2)|(1 << PB1)|(1 << PB0); // выходы
PORTB = 0x00;
DDRD |= (0 << PD2)|(0 << PD1)|(0 << PD0); // входы
PORTD |= (1 << PD2)|(1 << PD1)|(1 << PD0); // подключаем подтягивающие резисторы

TIMSK |= (1 << TOIE0); // разрешение прерывания по таймеру0
TCCR0 |= (1 << CS00);

MCUCR |= (0 << ISC00)|(1 << ISC01); // прерывание по заднему фронту INT0(по спаду импульса)

GIFR |= (1 << INTF0); // очищаем флаг внешнего прерывания
GICR |= (1 << INT0); // разрешаем внешние прерывания INT0

sei(); //глобально разрешаем прерывания

if (i==2)
{
PORTB=0b00000001;
}

while(1)
{
}


}
Сообщить модератору
0 #22 AntonChip 12.09.2016 21:33
переменную i сделать volatile unsigned int
Сообщить модератору
0 #23 Chip 15.09.2016 16:58
Странно. Добавил volatile unsigned int и все равно не работает.
Сообщить модератору

Рекомендуем посмотреть