Автоматическое и ручное управление экраном проектора

axill
Offline
Зарегистрирован: 05.09.2011

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

Имеем - экран с встроенными концевыми выключателями за счет чего экран едет до райнего положения автоматически на 100% механике. Для смены направления нужно перекидывать дин из проводов сети между двумя разными проводами электромотора. Т.е. с точки зрения электрического управления все просто, достаточно одного реле с перекидным контактом, в положении выключено экран будет закрыт, в положении реле включено - будет орываться и оставаться открытым.

Для управления было решено использовать инвракрасный интерфейс, на стороне экрана это приемник VS1738 - интегрированный инфракрасный приемник на частоте 38КГц

Значит первый способ управления - любой обычный ПДУ.

Второй способ - кнопка на самом устройстве. Вторая кнопка на устройстве будет использована для програмирования двух кодов IR. Первый от ПДУ, а второй от второго устройства.

Значит второе устройство. Его идея в том, чтобы слать IR код тогда когда включен проектор. Тогда в принципе можно вообще не заботиться о ручном управлении экраном - включаем проектор, экран открывается. Выключаем проектор - через какое-то время экран закрывается.

Впрочем, чтобы экран не пылился и не соблазнял собаку он будет закрываться при ручном открытии, но через несколько часов

Так как у проектора есть USB то самым простым вариантом узнать когда он работает оказалось запитать стройство от USB. Но есть одно уточнение. В тот же USB необходимо вставлять адаптер WIFI, поэтому еще одно требование к устройству - оно должно так же выступать как USB удлинитель, т.е. устройство вставляем в проектор, а адаптер в устройство.

Схемы. Контроллер экрана:

Устройство на проекторе:

axill
Offline
Зарегистрирован: 05.09.2011

Логика работы устройства на проекторе чертовски проста - после подачи питания шлем код и делаем паузу, спустя паузу снова шлем код и так до отключения питания. В момент отправки кода мигает светодиод

#define SENDING_PERIOD_SEC	120

#define LED_PIN		A2

#include <avr/interrupt.h>
#include <util/delay.h>

#include <IRremote.h>

IRsend irsend;

struct {
	struct {
		volatile uint8_t	presecond;
		volatile uint16_t	period_sec;
	} timers;
} var;

ISR(TIMER2_OVF_vect) {
	// срабатывает примерно 31 раз в секунду
	if(++var.timers.presecond == 31) {
		var.timers.presecond = 0;

		if(var.timers.period_sec) var.timers.period_sec--;
	}
}

void setup()
{
	pinMode(LED_PIN, OUTPUT);

	TCCR2 = (1 << CS22) | (1 << CS21) | (1 << CS20);
	TIMSK |= (1 << TOIE2);
}

void loop() {

	if(!var.timers.period_sec) {
		var.timers.period_sec = SENDING_PERIOD_SEC;

		irsend.sendNEC(0x12345678, 32);
		TIMSK |= (1 << TOIE2);

		digitalWrite(LED_PIN, LOW);
		_delay_ms(400);
		digitalWrite(LED_PIN, HIGH);
	}
}

 

axill
Offline
Зарегистрирован: 05.09.2011

Логика работы контроллера экрана посложнее. В первой части loop он определяет какое действие с экраном нужно соврешить. Список действий опрелделен enum { relay_none, relay_to_on, relay_to_off, relay_to_reverse } action

Во второй части действие исполняется.

В третьей проверяем нажатие кнопки насйтройки и если она нажата то в ходим на 30 секунд в цикл програмирования кодов. Первым програмируется код устройства проектора, вторым код ПДУ. при успешном програмировании кода проектора паузы между вспышками светодиода в три раза увеличиваются. После програмирования кода ПДУ происходит автоматический возврат в режим работы. Изменение кода проектора или кода ПДУ можно пропустить (без изменения) нажав еще раз кнопку конфигурирования (button1).

Зеленый светодиод горит постоянно в нормальном режиме работы когда экран закрыт или находится в процессе закрытия. Медленно мигает когда экран открыт или открывается. Часто моргает с короткими паузами при програмировании кода проектора и быстро моргает с длинными паузами при програмировании кода ПДУ

ПДУ может быть любой который поддерживается библиотекой IRremote. При нажатии кнопки ПДУ экран меняет состояние по кругу. Точно так же работает button2 на самом устройстве. После исполнения любой из команд делается пауза 5 секунд в течении которой ни на какие команды устройство не реагирует, сделано, чтобы не дергать экран туда-сюда

В обоих скетчах применен Timer2 для равления временными задержками.

#define TIMEOUT_RELAY_PROJECTOR_SEC		60*10		// время в минутах после получения последней IR посылки когда экран закрывается
#define TIMEOUT_RELAY_MANNUAL_SEC		60*60*5		// 60*5 - 5 часов при ручном открытии кнопкой или пультом


#define LED_PIN		A2
#define RELAY_PIN	13
#define IR_PIN		2
#define BUTTON1_PIN	8
#define BUTTON2_PIN	9

#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <IRremote.h>

IRrecv irrecv(IR_PIN);
decode_results results;

typedef struct {
	unsigned long	keycode_projector;
	unsigned long	keycode_remote;
} struct_keycode;

struct_keycode eeprom_keycodes EEMEM;

struct {
	struct_keycode	keycodes;
	struct {
		volatile uint8_t	presecond;
		//volatile uint8_t	second;
		volatile uint16_t	relay_off_sec;
		volatile uint16_t	change_sec;
		volatile uint8_t	configure_sec;
	} timers;
} var;

ISR(TIMER2_OVF_vect) {
	// срабатывает примерно 45 раз в секунду
	if(++var.timers.presecond == 48) {
		var.timers.presecond = 0;

		if(var.timers.relay_off_sec) digitalWrite(LED_PIN, (digitalRead(LED_PIN) == HIGH)?LOW:HIGH);
		if(var.timers.change_sec) var.timers.change_sec--;
		if(var.timers.configure_sec) var.timers.configure_sec--;
		if(var.timers.relay_off_sec > 1) var.timers.relay_off_sec--;

		//if(++var.timers.second == 60) {
			// примерно раз в минуту
		//	var.timers.second = 0;
		
		//}
	}
}

void setup()
{	
	pinMode(LED_PIN, OUTPUT);
	pinMode(RELAY_PIN, OUTPUT);
	digitalWrite(BUTTON1_PIN, HIGH);
	digitalWrite(BUTTON2_PIN, HIGH);
	
	irrecv.enableIRIn(); // Start the receiver
	eeprom_read_block(&var.keycodes, &eeprom_keycodes, sizeof(var.keycodes));
	
	TCCR2 = (1 << CS22) | (1 << CS21) | (1 << CS20);
	TIMSK |= (1 << TOIE2);
}

void loop()
{
	enum { relay_none, relay_to_on, relay_to_off, relay_to_reverse } action;

	action = relay_none;

	// -------------------------------------------------------
	// определения действия
	//
	if (irrecv.decode(&results)) {
		if(results.value == var.keycodes.keycode_projector) action = relay_to_on;
		else if(results.value == var.keycodes.keycode_remote) action = relay_to_reverse;
		irrecv.resume(); // Receive the next value
	}
	if(digitalRead(BUTTON2_PIN) == 0) action = relay_to_reverse;	
	if(var.timers.relay_off_sec == 1) {
		action = relay_to_off;
		var.timers.relay_off_sec = 0;
	}

	// -------------------------------------------------------
	// выполнение действия
	//
	if(!var.timers.change_sec) {
		// действие выполняем только если прошел мараторий на него
		switch(action) {
			case relay_to_on:
				RelayOn();
				var.timers.relay_off_sec = TIMEOUT_RELAY_PROJECTOR_SEC + 1;
				break;
			case relay_to_reverse:
				if(isRelayOn()) action = relay_to_off;
				else {
					RelayOn();
					var.timers.relay_off_sec = TIMEOUT_RELAY_MANNUAL_SEC + 1;
				}
				break;
		}
		if(action == relay_to_off) {
			RelayOff();
			var.timers.relay_off_sec = 0;
			LedOn();
		}
		if(action != relay_none) var.timers.change_sec = 5;	// новый мараторий в секундахё
	}
	  
	// -------------------------------------------------------
	// конфигурирование
	//
	if(digitalRead(BUTTON1_PIN) == 0) {
		_delay_ms(400);
		var.timers.configure_sec = 30;

		for(uint8_t codes=0; var.timers.configure_sec && codes < 2;) {
			LedOff();
			if(codes) _delay_ms(400); else _delay_ms(100);
			LedOn();
			_delay_ms(100);

			if (irrecv.decode(&results)) {
				switch(codes) {
					case 0:
						var.keycodes.keycode_projector = results.value;
						break;
					case 1:
						var.keycodes.keycode_remote = results.value;
						break;
				}
				_delay_ms(500);
				irrecv.resume();
				codes++;
			}

			if(digitalRead(BUTTON1_PIN) == 0) {
				_delay_ms(600);
				codes++;
			}
		}
		eeprom_write_block(&var.keycodes, &eeprom_keycodes, sizeof(var.keycodes));
	}
}

void RelayOn()			{ digitalWrite(RELAY_PIN, HIGH); }
void RelayOff()			{ digitalWrite(RELAY_PIN, LOW); }
uint8_t isRelayOn()		{ return digitalRead(RELAY_PIN) == HIGH; }
void LedOn()			{ digitalWrite(LED_PIN, LOW); }
void LedOff()			{ digitalWrite(LED_PIN, HIGH); }
uint8_t isLedOn()		{ return digitalRead(LED_PIN) == LOW; }
	
	

 

axill
Offline
Зарегистрирован: 05.09.2011

Програмирование делал в Atmel Studio с плагином для ардуино от visualmicro. Завливку скетчей через атмеловский програматор mkII без применения бутлоадера. В устройстве проектора кварц 8МГц (так как напряжение 3В, оно снижено, чтобы уменьшить ток потребления от USB при одновременном применении step-down преобразователя), в контроллере экрана 12МГц (можно и 16, просто у меня большой запас 12)

В boards.txt вставлены такие настройки:

###########################################################################
atmega8A8MHZ.name=ATmega8A (8MHz no bootloader)
atmega8A8MHZ.bootloader.low_fuses=0xFF
atmega8A8MHZ.bootloader.high_fuses=0xCF
atmega8A8MHZ.bootloader.unlock_bits=0x3F
atmega8A8MHZ.bootloader.lock_bits=0x0F
atmega8A8MHZ.upload.maximum_size=8192
atmega8A8MHZ.upload.tool=avrdude
atmega8A8MHZ.build.mcu=atmega8
atmega8A8MHZ.build.f_cpu=8000000L
atmega8A8MHZ.build.core=arduino:arduino
atmega8A8MHZ.build.variant=standard

# вариант без загрузчика и частотой м/к 8 мгц.

###########################################################################
atmega8A12MHZ.name=ATmega8A (12MHz no bootloader)
atmega8A12MHZ.bootloader.low_fuses=0xFF
atmega8A12MHZ.bootloader.high_fuses=0xCF
atmega8A12MHZ.bootloader.unlock_bits=0x3F
atmega8A12MHZ.bootloader.lock_bits=0x0F
atmega8A12MHZ.upload.maximum_size=8192
atmega8A12MHZ.upload.tool=avrdude
atmega8A12MHZ.build.mcu=atmega8
atmega8A12MHZ.build.f_cpu=12000000L
atmega8A12MHZ.build.core=arduino:arduino
atmega8A12MHZ.build.variant=standard

# вариант без загрузчика и частотой м/к 12 мгц.

 

axill
Offline
Зарегистрирован: 05.09.2011

в белой коробке устройство экрана. в черной устройство проектора

корпуса напечатаны на 3Д принтере

axill
Offline
Зарегистрирован: 05.09.2011

art100
Offline
Зарегистрирован: 09.03.2014

Урааа присоединяюсь. Много лет назад тоже горел желанием с пульта крутить экран вверх вниз. Так как не включал проектор много лет, Сегодня жена предложила может поднимать вверх вниз телевизор с метровой диагональю. Если будет время после работы думаю на противовесах посоздаю кнструкцию. По поводу эрана проектора. Сворачивать в рулон это правильно. Ключевые слова пыль грязь. Кто не понял проходите мимо. Мои экраны это механичесике конструкции. Концевички думал не на просвет, а магниты со скользящими герконами или классические механические скользящие . Надо будет почитать местный вариант. Мотор думаю если не червяк то только шаговик за удержание. У меня один экран червяк а второй заводсткого изготоволения с защелками. Я меня экраны 2.5метра на 2 метра. Есть моменты когда нет необходимости полностью разворачивать. Думал шаговиком шагать на 3 позиции. Кратко тех задание такое. Это тех задание больше для меня.

P.S. на принтере что-нибудь распечатать для необычности возможно

 

axill
Offline
Зарегистрирован: 05.09.2011

Вчера все установил и прямо в Новый Год все проверил - работает как задумано. 

m1tya52
Offline
Зарегистрирован: 29.04.2016

Отличная схема, как раз искал что-то подобное! У меня два USB выхода проектора и WI-FI встроенный поэтому нет необходимости делать разветвитель, если конечно он выполняет только эту роль. Хотелось чтобы открытие экрана происходило после включения проектора, а закрытие после выключения. Чем можно пренебречь в схеме, чтобы реализовать данный алгоритм? 

axill
Offline
Зарегистрирован: 05.09.2011

у меня так и происходит - открытие сразу после включения проектора, а закрытие через пару минут после выключения

так как вам разветвитель не нужен то из схемы можно убрать только разъем USB предназначенный для установки wifi свистка

все остальное нужно

но если можно протянуть проводок от проектора до экрана, тогда все очень сильно упрощается, по большому счету даже микроконтроллер не нужен

m1tya52
Offline
Зарегистрирован: 29.04.2016

axill пишет:

но если можно протянуть проводок от проектора до экрана, тогда все очень сильно упрощается, по большому счету даже микроконтроллер не нужен

Да, протянуть провод возможность есть. Подскажите как можно сделать в моем случае?

axill
Offline
Зарегистрирован: 05.09.2011

В вашем случае можно взять блок питания на 5в (usb зарядку), релейный модуль с транзисторным ключем (они почти все такие, но лучше уточнить) и все

если экран у вас как у меня, то там концевые выключатели и три провода, условно A/B/C. Чтобы открыть экран надо 220 подать на A/B, закрыть - B/C

Ставите реле так, чтобы когда оно выключено напряжение подавалось на B/C, а когда включено - на A/B

Теперь релейный модуль цепляете к блоку питания, а два провода со входа тянете к USB разьему проектора

- проектор включен - срабатывает реле и экран открывается

- проектор выключен - реле выключается и экран закрывается

m1tya52
Offline
Зарегистрирован: 29.04.2016

У меня мотор с редуктором от шуруповерта. Да, привязать схему к питанию от USB я как то не полумал. А если сделать только экранный модуль по вашей схеме будет так работать плюс с ИК пульта ?

axill
Offline
Зарегистрирован: 05.09.2011

Мой модуль вполне может работать только от ик пульта без второй части

m1tya52
Offline
Зарегистрирован: 29.04.2016

Значит можно сделать модуль управления экраном и он будет работать с пульта и автоматически разворачивать и сворачивать экран при включении и выключении проектора? Понравилась идея в качестве концевиков использовать KTIR0821DS

m1tya52
Offline
Зарегистрирован: 29.04.2016

А можно файл схемы, а то мелковато плохо видно?

axill
Offline
Зарегистрирован: 05.09.2011

Файл в формате altium designer. Могу в pdf выгрузить

m1tya52
Offline
Зарегистрирован: 29.04.2016

Если можно в pdf, буду признателен.

m1tya52
Offline
Зарегистрирован: 29.04.2016

У меня еще такой вопросик... можно hex для прошивки, а то у меня нет Atmel St., в понипрог МК прошиваю

axill
Offline
Зарегистрирован: 05.09.2011

Там скетчи ардуиновские, их можно компилить в среде ардуино

чуть позже выложу

m1tya52
Offline
Зарегистрирован: 29.04.2016

Попытался компилировать скетч в среде ардуино, выдал ошибку  'IRrecv' does not name a type. Это значит библиотеки нет?

axill
Offline
Зарегистрирован: 05.09.2011

Нужна библиотека IRremote

m1tya52
Offline
Зарегистрирован: 29.04.2016

Установил библиотеку, опять ошибку при проверке выдал: "'TCCR2' was not declared in this scope" - 65 и 66 строка

axill
Offline
Зарегистрирован: 05.09.2011

m1tya52 пишет:

Установил библиотеку, опять ошибку при проверке выдал: "'TCCR2' was not declared in this scope" - 65 и 66 строка

код для Мега8. Выше написано как настроить среду ардуино

m1tya52
Offline
Зарегистрирован: 29.04.2016

Я с Ардуино мало имел дело, мне бы файл прошивки в hex, по возможности фюзы и схему покрупнее. Если это коммерческий вариант то можно на почту m1tya52@yandex.ru

axill
Offline
Зарегистрирован: 05.09.2011

Вы какой Мк планируете использовать? 

m1tya52
Offline
Зарегистрирован: 29.04.2016

На схеме Атмега8, ее и хотел использовать.

axill
Offline
Зарегистрирован: 05.09.2011

Ок. Посмотрю хекс. Если честно никогда не задавался вопросом где он создается, надо найти

m1tya52
Offline
Зарегистрирован: 29.04.2016

  Я читал на форумах в папке Temp. Искать по дате и времени когда компиляция была произведена.  

armlive
Offline
Зарегистрирован: 07.12.2015

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

m1tya52
Offline
Зарегистрирован: 29.04.2016

http://ru.aliexpress.com/item/Free-shipping-3d-led-projector-full-hd-bui...
Я не нашел там триггер-выхода

armlive
Offline
Зарегистрирован: 07.12.2015

Действительно, но 2 усб за то

m1tya52
Offline
Зарегистрирован: 29.04.2016

И снова здравствуйте! А платы в lay не дадите?