Главная » Микроконтроллеры
Призовой фонд
на март 2017 г.
1. UNI-T UT-39C
Паяльник
2. Тестер компонентов LCR-T4
Паяльник
3. 100 руб.
От пользователей

Контроллер люстры

Данная схема не претендует на какую либо новизну и я осмелюсь представить на ваш суд схему контроллера или блока управления люстрой с шестью лампами. Данное устройство предназначено для управления шестью лампами любого типа. Традиционно схемы такого типа выполнялись с использованием тиристоров или симисторов, но с появлением малогабаритных люминесцентных ламп (энергосберегающих) такие схемы стали не пригодны. В данной схеме для управления используются электромеханические реле, которые управляются напряжением 12в при помощи ключей Т1..Т6, которыми в свою очередь управляет процессор АТ89С2051-24PI. Несколько странный, некоторым может показаться архаичный выбор процессора с ядром MCS-51 был обусловлен его наличием и достаточно низкой ценой, к тому же для начала освоения микроконтроллеров он на мой взгляд более подходит чем AVR контроллеры, так как он гораздо проще. Тактирование контроллера производится с использованием встроенного генератора с внешним кварцем на частоту 8,0 МГц.

Принципиальная схема блока управления люстрой с шестью лампами

Для управления контроллером используется стандартный пульт от телевизоров Горизонт 5го поколения с протоколом RC5. На пример такой как на рисунке ниже. Там же указаны коды данных передаваемых пультом.

Пульт управления Горизонт

Для приема сигналов пульта используется любой доступный ИК приемник на частоту 36 или 38кгц. Светодиод предназначен для индикации приема сигналов пульта управления. Питается схема от линейного блока питания состоящего из трансформатора, диодов, двух фильтрующих конденсаторов и микросхемы стабилизатора. Напряжение 12в используется для питания реле, 5в для питания остальной части схемы. Выключатели S1 и S2 это выключатели люстры установленные на стене. В данном случае люстра была подключена с использованием двух выключателей, включающих каждый свою секцию ламп, после модернизации люстры путем установки описываемого контроллера логика работы выключателей не поменялась и люстра может управляться только ими.

Логика работы прибора проста, при включении обоих выключателей люстра включается, контроллер не выполняет ни каких действий и ждет команды с пульта, все реле обесточены. При поступлении команды с пульта контроллер выполняет ее. Предусмотрены следующие команды: кнопки 1..6 выключают соответствующую им лампу, кнопка 9 включает все лампы, кнопки VBSCT+/- выключают и включают лампы по одной (уменьшают и увеличивают свет), кнопка с кодом 38 выключает все лампы по очереди (как в кинотеатре), кнопка М демонстрирует бегущий огонек, а затем возвращает люстру в исходное состояние, кнопки Р+/- позволяют "вращать" источник света (довольно полезная функция).

Контроллером управляет программа написанная с использованием среды Keil uVision2 на языке С.

Текст программы:

//*****************************************************************************************************
//
//			Lamp controller
//			CPU - AT89C2051
//			Clock 8.000 MHz
//			Six lamp controller. IR control RC-5
//			Autor Panda okt 2011
//
//******************************************************************************************************

#include 


#define Lamp_A P1_7 
#define Lamp_B P1_6 
#define Lamp_C P1_5 
#define Lamp_D P1_4 
#define Lamp_E P1_3 
#define Lamp_F P1_2 

#define IR     P3_2 //IR Port
#define LED    P3_4 //LED

#define LOW        16		//VBSCT - button
#define HI	       17		//VBSCT + button   +- button is swop. 
#define SLOW_OFF   38		//Timer off button
#define RUN_LIGHT  41		//M button   run light.
#define SHIFT_R    32		//P+ button
#define SHIFT_L    33		//P- button
#define ORDER	   59		//SL button	
 

#define ON  0
#define OFF 1

unsigned char _cmd, temp, cnt, MIRROR;
unsigned int  _addr;

//**********************************************************************************
// External Interrupt 0 service routine receive command from IR remote control unit
//**********************************************************************************
void ext_int0_isr(void) interrupt 0
{unsigned char ppp, pin;
 unsigned int _tmp, tout;
  EA   = 0; //ALL interrupt disable
  _tmp = 1;  
  LED = ON;
  
for(ppp = 1; ppp<14; ppp++)
    {for (tout = 100; tout >0; tout--);
     pin = IR;
     for (tout = 100; tout > 0; tout--)
        if (pin != IR) break;
     if (tout == 0) {EA = 1;   //timeout
	  IE0 = 0; //clear external interrupt flag
                    LED = 1;
                     return;};
     _tmp = _tmp << 1;
     if (!IR) _tmp++;
     };      
 _cmd  = _tmp & 0x003F;
 _addr = _tmp & 0xFFC0;
 _addr = _addr >> 6; 
 IE0 = 0; //clear external interrupt flag
 EA = 1;
 LED = OFF;
}      


void main(void) 
{
EA  = 1;
EX0 = 1;
IT0 = 1; //external interrupt 0 activated on falling age
LED = 1; //off led
IR  = 1;

P1     = 0x00; //All lamp on
MIRROR = 0x00;

LED = ON;
_addr = 50000;
while (_addr)
	_addr--;
LED = OFF;

while (1)
{
 if (_cmd == 1) {Lamp_A  = OFF;
 				 MIRROR |= OFF<<7;};
 if (_cmd == 2) {Lamp_B = OFF;
  				 MIRROR |= OFF<<6;};
 if (_cmd == 3) {Lamp_C = OFF;
  				 MIRROR |= OFF<<5;};
 if (_cmd == 4) {Lamp_D = OFF;
 				 MIRROR |= OFF<<4;};
 if (_cmd == 5) {Lamp_E = OFF;
 				 MIRROR |= OFF<<3;};
 if (_cmd == 6) {Lamp_F = OFF;
 				 MIRROR |= OFF<<2;};
 if (_cmd == 9) {P1 = 0x00; //All lamp on
 				 MIRROR = 0x00;};
 if (_cmd == LOW) 
 	{temp = MIRROR;
	 for (cnt = 2; cnt <= 7; cnt++)
	 {temp &= (0xFE <<  cnt);
	  if (MIRROR > temp)
	 		break;};
	  if (cnt < 8) 
	  	 {P1 = temp;	
		  MIRROR = temp;};
	  };
 if (_cmd == HI) 
    {temp = MIRROR;
	 for (cnt = 2; cnt <=7; cnt++)
	  {temp |= (0x01 << cnt);
	   if (temp > MIRROR)
	   		break;};
	   if (cnt < 8)
	   	  {P1 = temp;	
		   MIRROR = temp;};
			};
  if (_cmd == SLOW_OFF)
  {for (cnt = 2; cnt <= 7; cnt++)
	 {P1 |= (1 << cnt);
	  MIRROR |= (1 << cnt);
	  _addr = 60000;
	  while (_addr)
	  	_addr--;};
		 };
  if (_cmd == SHIFT_R)
  {temp = MIRROR;
   temp = temp >> 1;
   if ((temp & 0x02) > 0)
   		temp |= 0x80;
   P1 = temp & 0xFC;
   MIRROR = temp & 0xFC;};
  
  if (_cmd == SHIFT_L)
  {temp = MIRROR;
   if ((temp & 0x80) > 0)
   		temp |= 0x02;
   temp = temp << 1;
   P1 = temp;
   MIRROR = temp;};
  
  if (_cmd == RUN_LIGHT)
  {for(temp = 2; temp <= 7; temp++)
	  {P1 = ~(1 << temp);
	   _addr = 50000;
	   while(_addr) _addr--;};
	   P1 = MIRROR;
	   };

  _cmd = 0;
	};
}

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

Протокол RC-5используемый во многих системах управления теле-видео и другой аппаратурой достаточно подробно описан здесь. Коротко опишу: посылка состоит из 14 бит длительностью 1.778мс каждый и содержит два стартовых бита которые всегда равны 1, далее следует триггерный бит, который изменяет свое состояние при каждом нажатии клавиши. В простых проектах как этот, его совершенно не обязательно обрабатывать, затем 5 бит адреса и 6 бит данных, затем следует пауза длительностью 89мс. Для передачи данных используется так называемый манчестерский код, еще такую кодировку называют бифазной. При таком способе передачи данных логическая 1 кодируется как перепад сигнала с высокого на низкий уровень (отрицательный или задний фронт импульса), и логический 0 кодируется перепадом сигнала с низкого на высокий уровень (положительный или передний фронт импульса). Смена состояний производится в середине периода. Выглядит посылка как показано ниже:

Формат посылки

Такую посылку можно декодировать несколькими способами, самый простой из которых после приема первого импульса подождать примерно три четверти периода – это 1200-1300 мкс, затем в течении оставшегося времени отслеживать изменение уровня сигнала. Если в течении примерно 700мкс не произошло изменения сигнала, то прием пакета прерывается и ожидаем следующий. Если изменение произошло, то фиксируем 0 либо 1 (в зависимости от состояния линии) и цикл повторяем еще 13 раз.

for(ppp = 1; ppp<14; ppp++)
    {for (tout = 100; tout >0; tout--);        //Ожидание 1200мкс
     pin = IR;
     for (tout = 100; tout > 0; tout--)	//Ожидание 700-1200мкс, начальное значение tout можно уменьшить (для тех кого 
        if (pin != IR) break;		// напугали одинаковые значения инициализиции tout)
     if (tout == 0) {EA = 1;   //timeout
	  IE0 = 0; //clear external interrupt flag
                    LED = 1;
                     return;};
     _tmp = _tmp << 1;
     if (!IR) _tmp++;
     };

Здесь ррр – счетчик импульсов, tout – счетчик времени ожидания прихода импульса, pin – переменная в которой хранится состояние линии до изменения. В переменную _tmp записываем принятую посылку. Всякий раз после приема очередного бита данные в _tmp сдвигаются влево и в случае когда принята лог.1 к ней прибавляется единица.

Прием сигналов ИК пульта осуществляется в процедуре обработки внешнего прерывания INT0,

//**********************************************************************************
// External Interrupt 0 service routine receive command from IR remote control unit
//**********************************************************************************
void ext_int0_isr(void) interrupt 0

что избавляет от необходимости постоянно опрашивать порт в ожидании сигнала.
В случае успешного приема команды, ее код записывается в глобальную переменную _cmd,

_cmd  = _tmp & 0x003F;
_addr = _tmp & 0xFFC0;
_addr = _addr >> 6; 

А адрес в переменную _addr. Эта переменная в дальнейшем не используется, и разделение пультов по адресу не производится, но это довольно легко добавить. Используемые пульты работали оба на 0м канале, по этому необходимости их делить не было. Дальнейшая обработка команды, производится в основном теле цикла программы:

while (1)
{
 if (_cmd == 1) {Lamp_A  = OFF;
 				 MIRROR |= OFF<<7;};
 if (_cmd == 2) {Lamp_B = OFF;
  				 MIRROR |= OFF<<6;};
 if (_cmd == 3) {Lamp_C = OFF;
  				 MIRROR |= OFF<<5;};

…
…
…

   P1 = temp;
   MIRROR = temp;};
  
  if (_cmd == RUN_LIGHT)
  {for(temp = 2; temp <= 7; temp++)
	  {P1 = ~(1 << temp);
	   _addr = 50000;
	   while(_addr) _addr--;};
	   P1 = MIRROR;
	   };

  _cmd = 0;
	};

По окончании обработки команды, ее код обнуляется.
Еще несколько особенностей программирования с которыми сталкиваются начинающие. В программе есть переменная MIRROR, для чего она? В контроллерах серии АТ89СХХХХ обращение к портам ввода вывода производится с помощью одного регистра, но запись и чтение из порта производятся в разных регистрах внутри контроллера. То есть когда вы записываете данные в порт P1 = 0xff; внутри контроллера запись производится в один регистр не доступный для пользователя, при чтении порта aa = P1; чтение производится из другого регистра и фактически порт настраивается на чтение данных с ножек контроллера. Таким образом записав в порт любое число скажем 0х05, а затем прочитав состояние порта вы получите совсем другое число. (P1 = 0x05) != (aa = P1) à aa != 0x05; Это обстоятельство нужно учитывать при разработке программ.

Хотелось бы еще дать один совет теперь уже по работе со средой программирования Keil_uVision2. Для решивших повторить проект, а может быть сделать что то свое с использование ИК управления захочется адаптировать программу для работы с другим кварцевым резонатором. Для этого достаточно будет изменить параметры всего двух циклов программы:

for(ppp = 1; ppp<14; ppp++)
    {for (tout = 100; tout >0; tout--);       //Ожидание ~1200мкс
     pin = IR;
     for (tout = 100; tout > 0; tout--)       //Ожидание ~700мкс-1200мкс
        if (pin != IR) break;
     if (tout == 0) {EA = 1;   //timeout
	  IE0 = 0; //clear external interrupt flag
                    LED = 1;
                     return;};
     _tmp = _tmp << 1;
     if (!IR) _tmp++;
     };

Сделать это без расчетов будет довольно просто. Среда Keil uVision2 имеет в своем составе отладчик и в режиме отладки всегда можно посмотреть текущее процессорное время.

Контроль процессорного времени

Засекая время начала и окончания цикла при пошаговой отладке легко можно посчитать время работы цикла. Для того, чтобы оно совпало с реальным, необходимо в свойствах проекта правильно установить частоту кварцевого резонатора.

Установка параметров проекта

Установка частоты кварцевого резонатора

Программа получилась очень простой и надежной, блок управления уже несколько месяцев работает без сбоев.

Теперь о конструкции. Контроллер не программируется внутрисхемно, по этому усажен в панельку, Fuse битов не имеет, что сильно упрощает процесс программирования. Для программирования использовался программатор Blow it. Взять его можно здесь, пост #3. Это очень простой и надежный программатор, который служит уже без малого 10 лет. Вопросы по программатору можно задать в указанном топике. Контроллер АT89C2051-24PI, транзисторы Т1..Т6 можно применить любые маломощные, структуры n-p-n на пример кт3102, кт315. Реле К1..К6 на напряжение 12в, способные коммутировать 220в. Ток потребляемый одним реле ~20ма. Диоды могут быть любыми выпрямительными на ток до 1А и напряжением более 100в, на пример 1N1044, 1N1050, 1N1056. Конденсатор С4 должен быть рассчитан на напряжение не менее 25в. Выпрямитель и трансформатор использованы от китайского блока питания на ток 300 мА.

Фото блока люстры

Фото блока люстры

Список радиоэлементов

Обозначение Тип Номинал Количество ПримечаниеМагазинМой блокнот
МК AVR 8-бит
AT89C2051
1 АТ89С2051-24PIПоиск в FivelВ блокнот
VR1 Линейный регулятор
LM7805
1 Поиск в FivelВ блокнот
ИК-приемник1 Поиск в FivelВ блокнот
Т1-Т6 Биполярный транзистор
КТ3102
6 КТ315Поиск в FivelВ блокнот
D1-D10 Диод1N104410 1N1050, 1N1056Поиск в FivelВ блокнот
С1, С2 Конденсатор33 пФ2 Поиск в FivelВ блокнот
С3 Электролитический конденсатор1 мкФ1 Поиск в FivelВ блокнот
С4, С5 Электролитический конденсатор200 мкФ2 Поиск в FivelВ блокнот
С6 Конденсатор0.1 мкФ1 Поиск в FivelВ блокнот
R1 Резистор
2.2 кОм
1 Поиск в FivelВ блокнот
R2 Резистор
470 Ом
1 Поиск в FivelВ блокнот
R3-R8 Резистор
20 кОм
6 Поиск в FivelВ блокнот
Qz1 Кварцевый резонатор11.0592 МГц1 Поиск в FivelВ блокнот
LED1 Светодиод1 Поиск в FivelВ блокнот
К1-К6 Реле12 В6 Поиск в FivelВ блокнот
Tr1 Трансформатор220/12 В1 Поиск в FivelВ блокнот
L1-L6 Лампочка220 В6 Входят в состав люстрыПоиск в FivelВ блокнот
Пульт дистанционного управленияRC-5001 Поиск в FivelВ блокнот
Добавить все

Скачать список элементов (PDF)

Теги:

Panda_Y2K Опубликована: 2012 г. 0 0
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (3) | Я собрал (0) | Подписаться

0
Алекс #
... Традиционно схемы такого типа выполнялись с использованием тиристоров или симисторов, но с появлением малогабаритных люминесцентных ламп (энергосберегающих) такие схемы стали не пригодны.
Это почему интересно? У меня работает именно с такими лампами, 6 ламп. Зачем городить огород с трансформатором и электромагнитыми реле, которые ни в одну люстру не поместятся? Бредовато ИМХО.
Ответить
0
Panda_Y2k #
Плавной регулировки не получиться, но на вкл. выкл. вполне можно применить и симисторы. От трансформатора я думаю избавиться едва ли удастся избавиться если только не использовать импульсный преобразователь, что сильно усложнит схему. Суммарный ток потребления схемы не позволит использовать гасящий резистор, если только не на каждый симистор отдельно, но это будет печка будь здоров. У меня были реле и не было необходимости встраивать в люстру (чудесно прячется под потолком). Если хочется симисторов, вполне можно заменить реле на симисторы с соответствующей схемой управления и будет работать.
Ответить
0
Panda_Y2K #
P.S. Когда я так писал, то подразумевал плавное управление яркостью.
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется сила тока?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Программатор Pickit3
Программатор Pickit3
Осциллограф DSO138 USB-реле (2 канала)
вверх