среда, 10 октября 2012 г.

Пульт Canon RC-1

Всем привет! Продолжаю писать заметки по электронике.
Недавно прикупил себе зеркалку Canon EOS 600D, выяснилось, что в ней присутствует возможность дистанционного управления спуском затвора по ИК каналу. Покупать пульт мне показалось не спортивным, поэтому решил изготовить его самостоятельно. В результате поиска было обнаружено несколько вариантов пультов, однако все они мне не очень понравились, по разным причинам. "Значит буду придумывать свой!" - сказал я себе.

Итак, мой вариант пульта (№ стопиццот)

Описание протокола можно посмотреть тут.

Аппаратная часть
За основу был взят контроллер ATtiny2313(просто потому что был в наличии, как и все остальное). В качестве элементов управления взял две кнопки - одна для немедленного спуска затвора, вторая для спуска с 2х секундной задержкой, от использования переключателя, как в штатном пульте от Canon отказался, поскольку мне это показалось неудобным, да и конструктивно проще работать с кнопками.

Схема пульта:
Пара слов про комплектуху:
Конденсатор С2 - чип танталовый, малогабаритный с малыми утечками, дабы не сажал батарею и помогал ей при отправке ИК сигнала.
Транзистор Q1 - любой N-канальный с индуцируемым каналом.
Тинька в SO-20 корпусе, маленькая потому что.
ИК светодиод любой с длиной волны 940-950нМ, желательно помощней, конечно резистор R6 пересчитываем под свой светодиод(закон Ома рулит!).

Далее текст для тех, кто совсем ничего не знает, но хочет научится.
Расчет весьма прост - нам потребуются справочные данные на светодиод и транзистор:
  • Рабочий ток светодиода 
  • Падение напряжения на светодиоде
  • Сопротивление сток-исток транзистора в открытом состоянии

Считаем падение напряжения на открытом транзисторе:
U = I*R, где I - рабочий ток светодиода, R - сопротивление сток-исток транзистора в открытом состоянии.
Прибавляем падение напряжения на светодиоде к полученному значению падения напряжения на транзисторе и получаем общее падение напряжения.
Вычитаем из напряжения питания значение общего падения напряжения - это будет падение напряжения на токоограничивающем резисторе.
Сопротивление токоограничивающего резистора - R=U/I, где U - падение напряжения на токоограничивающем резисторе, I - рабочий ток светодиода.
Далее смотрим сюда и выбираем сопротивление резистора наиболее близкое к полученному значению из номинального ряда.

Логика работы:
Контоллер постоянно находится в спящем режиме(экономим заряд батареи), по нажатию кнопки он просыпается, отправляет ИК сигнал, моргает контрольным светодиодом и опять засыпает. Все просто, кроме мордобоя никаких чудес. :)

Корпус:
Для своей поделки я выбрал вот такой корпус:

Так же исходя из доступности, можно было купить далеко не ходя.

Печатная плата:

Плата как плата, единственное пожелание - толщина текстолита 0,5 мм, чтоб в корпусе поместилось нормально.

Программная часть.

Среда разработки - AVRStudio 6
Язык - С (ну не понимаю я ассемблер, хоть ты тресни!)

Основная часть программы, посылка пакета, честно стырена отсюда, огромное спасибо товарищу Maksoff. Остальное мое твочество.


/*
 * RC_1.c
 *
 * Created: 03.10.2012 15:35:51
 *  Author: Owner
 */

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

#define F_CPU 1000000UL //Частота контроллера 1МГц (8МГц генератор и делитель на 8)
//Leds port:
#define led_port PORTB
#define led_ddr DDRB
#define led_pin 0  //Нога на которой висит ИК диод
#define control_pin 1 //Нога на которой висит контрольный светодиод
#define led_one (1<<led_pin)
#define led_all (1<<led_pin|1<<control_pin)
//Control port в общем то и необязательно, все равно по прерываниям работаем
#define ctrl_port PORTD
#define ctrl_ddr  DDRD
#define ctrl_pin  PIND
#define im_but    2
#define dly_but  3
unsigned char act=2;

#define nop() asm("nop")

//Функция, которая отправляет одну посылку (это стырено)
void Post (char bits_to_set)
{
unsigned char i;
for (i = 0; i < 16; i++)
{
led_port |= (1<<bits_to_set);
nop();
nop();
nop();
nop();
nop();
nop();
nop();
nop();
nop();
nop();
nop();
nop();

led_port &= ~(1<<bits_to_set);
nop();
nop();
nop();
nop();
nop();
nop();
nop();
nop(); //Количество нопов высчитано в симуляторе
}

}

//Немедленный спуск
void Shutter (char led)
{
Post(led);
_delay_ms(7.324);
Post(led);
}

//Спуск с двух секундной задержкой
void Shutter2 (char led)
{
Post(led);
_delay_ms(5.371);
Post(led);
}
//Отсюда мои художества
ISR(INT0_vect)
{
cli(); //Запрещаем прерывания
act = 0; //Устанавливаем условие спуска без задержки
}
ISR(INT1_vect)
{
cli(); //Запрещаем прерывания
act = 1; //Устанавливаем условие спуска с 2х секундной задержкой
}
int main(void)
{
GIMSK=0xC0; //разрешаем прерывание int0 и int1 -  кнопка
MCUCR=0x00; //прерывания int0 и int1 по лог. 0, поскольку из спящего режима можно вывести только по прерыванию на уровень сигнала, по фронту никак.
led_ddr = 1<<led_pin|1<<control_pin;//Инициализация порта
ctrl_ddr = 0x00; //Порт D на вход (необязательно)
ctrl_port = 1<<im_but | 1<<dly_but; //Подтяжка на кнопки (необязательно, пригодится если лень внешние резисторы ставить)
ACSR |= (1<<ACD); //Гасим аналоговый компаратор
    while(1)
    {
_delay_ms(8); //чтоб окончательно проснуться ждем чуток
//В зависимости от нажатой кнопки посылаем ИК сигнал
if (act==0) Shutter(led_pin);
else if (act==1) Shutter2(led_pin);
led_port |= 1 << control_pin; //Зажигаем контрольный светодиод
_delay_ms(100);
led_port &= ~(1<<control_pin); //Гасим контрольный светодиод
_delay_ms(150); //на всякий який ждем, чтоб не сработало несколько раз подряд
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Устанавливаем режим сна МК
sleep_enable(); //Разрешаем уход в сон
sei(); //Разрешаем прерывания
sleep_cpu(); //Усыпляем МК
sleep_disable(); //Будим МК по прерыванию
    }
}
 Собственно на этом все. Описывать особенно нечего, исходник весьма подробно прокомментирован.
Фьюзы при прошивке не меняем, работает с заводскими
 High - 0xDF, Low - 0x64, Ext. - 0x01

Готовый пульт:


Файлы к статье:

  • Проект AVR Studio 6
  • Печатная плата в layout

Брать тут.

Всем успехов! До новых заметочек!

Комментариев нет:

Отправить комментарий