定期的な撮影のため、マイコンからニコンのDSLR(デジタル一眼レフ)のリモコン信号を出すものを作った。デバイスはATTiny13Aです。8pinの安いやつ。
内蔵RC発信器を使うので、時間間隔は割といい加減だが、そこはご愛敬。
Time Lapseの撮影とか、連続的に星の写真を撮ることを目的としているので、連続的にシャッター操作ができたらいいのだ。
なお、運用して思ったが、夜間30秒の露光をしてどんどん撮影していくような場合、1秒ごとにリモコンコマンドを送るようにしておけば良いことに気がついた。
撮影終了後1秒以内に撮影コマンドがやってくるので、ほぼ連続的な動作が出来る。
このリモコンの時間設定を行う場合は、きっと昼間の連続撮影だろうな。
しかしソースコードを載せるのは面倒くさいな。
/*
* _20130716_Nikon_IR_Remote.c
*
* Created: 2013/07/16 22:53:07
* Author: mako
*
* ATTiny13A
* +--------+
* -Reset ++ ++ Vcc
* | |
* PB3 ++ ++ PB2
* | |
* PB4 ++ ++ PB1 for IR LED output
* | |
* GND ++ ++ PB0
* +--------+
*
*
* PB1 --- 270ohm --- IR LED---GND // I think it work WITHOUT resistor.
* 4ch DIP switch or Rotary encoder(comprementary) connects PB0,PB2-PB4 to GND.
*
*/
#define F_CPU 1200000 //正確にしたい場合、微調節必要だが、そもそも内蔵RCクロックなのでアテにはならない
#defineSignalTime 100 //信号間隔を後でキャンセルするために設定
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
unsigned char IntervalStatus;
DDRB =0b00010; //Set PB1 for output, PB0,PB2-PB5 for input
PORTB =0b11101; //Pull Up PB0, PB2-PB5 with internal resister
// note DDR[Port][Number]=0 AND PORT[Port][Number]=1 -> Internal resistor pull up
TCCR0A =0b00000011; //start counter prescaler 1/1
// (0<
OCR0A =31; // set duration : 31 count takes 31/1.2MHz = 25.8us nealy equal to 26.3us (38kHz)
OCR0B =10; // set duty about 1/3
while(1)
{
//Start Sending Shutter Command for Nikon DSLR
//TCCR0Aの5bitの1/0で出力on/offさせている。タイマーは回しっぱなしで出力するかどうかを選択。
//DDRDなどで制御してもいいかもしれない。
TCCR0A =0b100011; _delay_us(2000);
TCCR0A =0b000011; _delay_us(27850);
TCCR0A =0b100011; _delay_us( 390);
TCCR0A =0b000011; _delay_us(1580);
TCCR0A =0b100011; _delay_us( 410);
TCCR0A =0b000011; _delay_us(3580);
TCCR0A =0b100011; _delay_us( 400);
TCCR0A =0b000011; _delay_us(63200);
//Total 99.4ms
IntervalStatus=(((PINB & 0b11101)+1)>>1)^0b1111; //Pinの入力は反転。pull upで
//1加算することで、0b11101の配列が0b11110になる。そして、1ビットシフトし、0b1111とXOR演算し、
//コンプリメンタリーのスイッチの状態を読み込める
//以下一行にif文を入れてしまったので、少々わかりにくいかもしれないが、ひたすら入力ピンに合わせてひたすら信号間隔を決めるだけ
//なお、待ち時間が長いときに設定変更する場合、リセット端子が便利なので、リセットスイッチor電源スイッチを活用しよう
//時間間隔は必要に応じて変更
if(IntervalStatus == 0) {_delay_ms( 1000-SignalTime);} //Inteval for 1sec
if(IntervalStatus == 1) {_delay_ms( 2000-SignalTime);} //Inteval for 2sec
if(IntervalStatus == 2) {_delay_ms( 3000-SignalTime);} //Inteval for 3sec
if(IntervalStatus == 3) {_delay_ms( 4000-SignalTime);} //Inteval for 4sec
if(IntervalStatus == 4) {_delay_ms( 5000-SignalTime);} //Inteval for 5sec
if(IntervalStatus == 5) {_delay_ms(10000-SignalTime);} //Inteval for 10sec
if(IntervalStatus == 6) {_delay_ms(15000-SignalTime);} //Inteval for 15sec
if(IntervalStatus == 7) {_delay_ms(20000-SignalTime);} //Inteval for 20sec
if(IntervalStatus == 8) {_delay_ms(25000-SignalTime);} //Inteval for 25sec
if(IntervalStatus == 9) {_delay_ms(30000-SignalTime);} //Inteval for 30sec
if(IntervalStatus == 10) {_delay_ms(45000-SignalTime);} //Inteval for 45sec
if(IntervalStatus == 11) {_delay_ms(60000-SignalTime);} //Inteval for 1min
if(IntervalStatus == 12) {_delay_ms(120000-SignalTime);} //Inteval for 2min
if(IntervalStatus == 13) {_delay_ms(180000-SignalTime);} //Inteval for 3min
if(IntervalStatus == 14) {_delay_ms(240000-SignalTime);} //Inteval for 4min
if(IntervalStatus == 15) {_delay_ms( 200-SignalTime);} //when open for testing.
}
}