Фотографирование: пульт дистанционного управления к Canon EOS 650D

star tracks
Мое фото: Canon EOS 650D: f/4, 18 мм, 949 сек, ISO-200 (10 км от города и небо сильно засвечено).

Захотелось мне пофотографировать звезды на длинных выдержках. Так, чтобы оставить фотоаппарат неподвижным хотя бы минут на 10-15 и увидеть, как поворачиваются звезды вокруг Полярной звезды. Опыта у меня особо никакого нет, что я точно знаю - хорошо бы фотоаппарат во время съемки не трогать руками, чтобы он не дрожал во время нажатия кнопки. Поэтому нужен штатив для фотоаппарата и пульт дистанционного управления.

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

С длинными выдержками интересно фотографировать не только треки звезд, но и всякие события вроде пролета искусственных спутников Iridium. Конструкция спутника такая, что его блестящая антенна может давать на Землю блик от Солнца буквально на 10-20 секунд. При наблюдении неба пролет Iridium выглядит как появление слабой звездочки яркость которой быстро растет, а потом спадает. Поскольку затвор фотоаппарата при съемке с длинной выдержкой все время открыт, то на фото получается интересный след:

iridium flare

Вот что получилось у меня. Canon EOS 650D: f/4, 24 мм, 104.5 сек, ISO-400.
Вот если сделать зум той же фотографии:

Вспышка Иридиума

Расписание "вспышек Иридиумов" (Iridium Flares) конкретно для вашего местоположения можно посмотреть на сайте http://www.heavens-above.com/. Само ожидание пролета спутника и его наблюдение - довольно захватывающее мероприятие. Я, примерно зная время появления спутника и его местоположение, заранее направляю фотоаппарат со штатива и включаю его, открываю затвор в режиме BULB. После пролета спутника с пульта ДУ фотоаппарата выключаю съемку, закрываю затвор и смотрю, что получилось.

Теперь о том, как я делал пульт дистанционного управления.

rc6
Оригинальный пульт Canon типа RC-6 вроде бы имеет всего две кнопки: "сделать снимок" и "сделать снимок с задержкой 2 секунды".

Прежде всего нужно порыться в интернете и посмотреть, может кто-то что-то уже делал такое. Желательно найти описание или документацию на протокол передачи инфракрасных сигналов к фотоаппарату. Я надеялся, что тут есть какой-то стандарт, но я ошибался. Похоже каждый производитель изобретает свой велосипед.

Наиболее полная информация по пультам и протоколам собрана на странице http://www.numericana.com/answer/ir.htm#camera
Здесь я хотя бы узнал, что несущая частота передачи для пульта Кэнон должна быть 32768Hz.

Вторая интересная ссылка, которую я нашел http://sebastian.setz.name/arduino/my-libraries/multi-camera-ir-control/ - это библиотека на C/C++ для Ардуино в которой реализованы функции ShutterNow() и ShutterDelayed() - как раз они вызываются при нажатии первой и второй кнопки пульта соответственно. Функции простые они управляют всего одним выходным сигналом, который идет на инфракрасный излучающий диод.

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


 void Canon::shutterNow()
{
  for(int i=0; i<16; i++) { 

    digitalWrite(_pin, HIGH);
    delayMicroseconds(11);
    digitalWrite(_pin, LOW);
    delayMicroseconds(11);
  }
  delayMicroseconds(7330);
  for(int i=0; i<16; i++) {
    digitalWrite(_pin, HIGH);
    delayMicroseconds(11);
    digitalWrite(_pin, LOW);
    delayMicroseconds(11);
  }
}

void Canon::shutterDelayed()
{
  for(int i=0; i<16; i++) {
    digitalWrite(_pin, HIGH);
    delayMicroseconds(11);
    digitalWrite(_pin, LOW);
    delayMicroseconds(11);
  }
  delayMicroseconds(5360);
  for(int i=0; i<16; i++) {
    digitalWrite(_pin, HIGH);
    delayMicroseconds(11);
    digitalWrite(_pin, LOW);
    delayMicroseconds(11);
  }
}


Похоже передается пачка из 16-ти импульсов, потом пауза-задержка и еще пачка из 16-ти импульсов. По интервалу между пачками импульсов видимо фотоаппарат отпределяет какая кнопка нажата на пульте, первая или вторая.

К сожалению, библиотеки для Ардуино используют программную задержку, поэтому особенно доверять этим исходным текстам не приходится... Вот если предположить, что пачка 16 импульсов - это модулированный бит=1, то его длина получается (11+11)*16=352 микросекунды. Пауза между пачками - это несколько битов нулей. Посмотрим сколько: 7330 / 352 = 20,8238..
Видимо точно выдержать паузы программным способом на Ардуино очень непросто, раз число бит получилось не круглым.. Ну наверное пауза 21 бит? Или нет?

Опять же возникают вопросы по несущей частоте. Судя по коду программы период несущей частоты будет 11+11=22 микросекунды.
То есть частота: 45.45 КГц и это не соответствует 32768Hz, которые я вычитал с другого сайта. С другой стороны, я видел комментарии разных людей в интернете по этим задержкам, так некоторые говорят, что на Ардуино сам вызов процедуры установки бита в порту занимает какое-то время.

В общем, похоже четкой документации мне не найти, придется пробовать разные варианты пока не заработает.

Я написал модуль на Verilog HDL, ну и tesbench в придачу, чтоб быть уверенным, что все сделано правильно. Вот модуль Verilog:


module canon_rc6(
  input wire clk,
  input wire button0,
  input wire button1,
  output reg ir_line
);

localparam CMD_INSTANT_SHOT = 20'b01000000000000000100;
localparam CMD_DELAYED_SHOT = 20'b01000000000001000000;

//Canon RC-6 has modulation frequency 32768 Hz
//divide input 100MHz clock to get period
reg [15:0]div_cnt = 0;
reg mod_clk = 0;

always @(posedge clk)
  if(div_cnt<1526)
  begin
    div_cnt <= div_cnt +1'b1;
    mod_clk <= mod_clk;
  end
  else
  begin
    div_cnt <= 0;
    mod_clk <= mod_clk ^ 1;
  end

reg [2:0]button_fixed0 = 0;

always @(posedge mod_clk)
  button_fixed0 <= { button_fixed0[1:0] , button0 };

wire button_pressed0; assign button_pressed0 = (button_fixed0[2:1]==2'b10);

reg [2:0]button_fixed1 = 0;
always @(posedge mod_clk)
  button_fixed1 <= { button_fixed1[1:0] , button1 };

wire button_pressed1; assign button_pressed1 = (button_fixed1[2:1]==2'b10);

reg state = 0; //0 mean waiting, 1 mean sending

reg [3:0]cnt16 = 0;
always @(posedge mod_clk)
  cnt16 <= (state==0) ? 0 : cnt16+1;

reg [19:0]shift_reg = 0;
always @(posedge mod_clk)
  if( state==0 )
  begin
    if( button_pressed0 )
      shift_reg <= CMD_INSTANT_SHOT;
    else
    if( button_pressed1 )
      shift_reg <= CMD_DELAYED_SHOT;
  end
  else
  if(cnt16==15)
    shift_reg <= { shift_reg[19:0],1'b0 }; //shift out CMD to right

always @(posedge mod_clk)
  case( state )
  0: begin
    //waiting for button press
    if(button_pressed0 || button_pressed1)
      state <= 1'b1;
    end
  1: begin
    //sending
    if( shift_reg== 0)
      state <= 1'b0;
    end
  endcase

always @(posedge clk)
  ir_line <= shift_reg[19] & mod_clk;

endmodule


Надеюсь, что тут все более или менее понятно. 

Из входной частоты 100 МГц (на плате Марсоход стоит такой кварцевый генератор) делаю mod_clk = 32768Hz путем деления частоты. Дальше все происходит на этой низкой частоте. Во-первых, происходит опрос нажатия кнопок. Ловлю только момент нажатия кнопки, получаю сигналы button_fixed0 и button_fixed1. Если схема находится в режиме ожидания, если state==0, и если при этом обнаружено нажатие кнопки, то в сдвиговый регистр загружается одно из двух возможных значений CMD_INSTANT_SHOT или CMD_DELAYED_SHOT. Каждые 16 импульсов модулирующей частоты mod_clk содержимое регистра shift_reg сдвигается влево. Самый старший бит сдвигового регистра идет прямо на ИК светодиод, правда модулированный частотой mod_clk, вот так: ir_line <= shift_reg[19] & mod_clk; Возврат в состояние ожидания происходит, когда передающий сдвиговый регистр полностью опустошен: if( shift_reg== 0) state <= 1'b0;

Простейший тестбенч к модулю имитирует нажатие кнопки:


`timescale 1ns / 1ns

module testbench();

//assume basic clock is 100Mhz
reg clk;
initial clk=0;
always
  #5 clk = ~clk;

wire led;
reg but0;
reg but1;

canon_rc6 canon_rc6_inst(
  .clk( clk),
  .button0( but0 ),
  .button1( but1 ),
  .ir_line ( led )
  );

initial
begin
but0 = 1'b0;
but1 = 1'b0;
$dumpfile("out.vcd");
$dumpvars(0,testbench);

#5000;
but0=1'b1;
#80000;
but0=1'b0;

#10000000;
$finish;
end
endmodule


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

Я использую простой симулятор Icarus Verilog. Из командной строки вызываю команду компиляции:

>iverilog -o myout canon_rc6.v testbench.v


Теперь симуляции:

>vvp myout

Получаю файлы временных диаграмм *.vcd и смотрю их в GtkWave:

>gtkwave out.vcd

Вот что я вижу во временных диаграммах, пауза между пачками импульсов 7330 микросекунд:

wave1

Сама пачка импульсов выглядит вот так:

wave2

Период модулирующей частоты примерно правильный, соответствует частоте 32768 Гц.

Теперь модуль canon_rc6 можно вставить в проект в среде Altera Quartus II.

Весь проект можно скачать здесь: 

Проект совсем простой: три входа: вход от генератора, два кнопки, один выход на ИК диод. Диод подключается через резистор к контакту F5 платы Марсоход:

фрагмент схемы платы Марсоход с подключенным ИК диодом

Выглядит это вот так:

canon RC6 simulation IR ctrl brd

Небольшая видео демонстрация моего пульта дистанционного управления для фотоаппарата:

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

PS: все фото звезд вверху выполнены с большими выдержками с применением этого IR "пульта".

 


Добавить комментарий