オリンパスのデジカメのリモコンをAVRで作った
オリンパスのリモコンRM-1
のコードを5分おきに送信してシャッターを切ります。
材料
- Atmel AVR Tiny2313V
- 赤外線LEDが1個
- (パスコン)
- 単三電池2本&電池ボックス
// Olympus Remocon #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include <avr/wdt.h> #include <util/delay.h> #define nop() __asm__ __volatile__ ("nop") void send_ir(int us, char on) { // 38KHz 1sec=1000ms=1000000us => 38000 // 1000000/38000 = 26.3157895us on/off 13.1578947us // 1MHz => 1sec => 1000000 => 1op=1us for(; 0<=us; us-=26){ PORTB = on ? 0b00000011 : 0b00000000; nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); // ON 12 / OFF 1.. 6 // ON 10 / 3.. 8 // ON 5 / 8..13 PORTB = 0b00000000; nop(); nop(); nop(); nop(); nop(); } } void send_data(char* data, int bits) { int i; int lead_high_len = 9000; int lead_low_len = 4500; int data_high_len = 560; int data_low0_len = 560; int data_low1_len = 1690; int stop_high_len = 560; DDRB = 0b00000011; send_ir(lead_high_len, 1); send_ir(lead_low_len, 0); for(i=0; i<bits; i++){ int on = data[i/8] & (1<<(7-i%8)); send_ir(data_high_len, 1); send_ir(on ? data_low1_len : data_low0_len, 0); } send_ir(stop_high_len, 1); _delay_ms(1000); } EMPTY_INTERRUPT(WDT_OVERFLOW_vect); void init_wdt_interrupt(int interval) { cli(); wdt_reset(); MCUSR &= ~(1<<WDRF); // 「WDTリセットされた」フラグクリア WDTCSR |= (1<<WDCE)|(1<<WDE); // wdt変更前処理 #define _WDT_15MS ((0<<WDP3)|(0<<WDP2)|(0<<WDP1)|(0<<WDP0)) #define _WDT_30MS ((0<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0)) #define _WDT_60MS ((0<<WDP3)|(0<<WDP2)|(1<<WDP1)|(0<<WDP0)) #define _WDT_120MS ((0<<WDP3)|(0<<WDP2)|(1<<WDP1)|(1<<WDP0)) #define _WDT_250MS ((0<<WDP3)|(1<<WDP2)|(0<<WDP1)|(0<<WDP0)) #define _WDT_500MS ((0<<WDP3)|(1<<WDP2)|(0<<WDP1)|(1<<WDP0)) #define _WDT_1S ((0<<WDP3)|(1<<WDP2)|(1<<WDP1)|(0<<WDP0)) #define _WDT_2S ((0<<WDP3)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0)) #define _WDT_4S ((1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(0<<WDP0)) #define _WDT_8S ((1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0)) WDTCSR = (1<<WDIE)|(0<<WDE)|interval; // wdt設定 reset=0, interrupt=1 sei(); } void main_olympus(void) { char shutter[] = {0b01100001, 0b11011100, 0b10000000, 0b01111111}; char wide[] = {0b01100001, 0b11011100, 0b01000000, 0b10111111}; char tele[] = {0b01100001, 0b11011100, 0b11000000, 0b00111111}; char minus[] = {0b01100001, 0b11011100, 0b00100000, 0b11011111}; char plus[] = {0b01100001, 0b11011100, 0b10100000, 0b01011111}; int i, t; init_wdt_interrupt(_WDT_1S); set_sleep_mode(SLEEP_MODE_PWR_DOWN); for(;;){ send_data(shutter, 32); send_data(shutter, 32); send_data(shutter, 32); for(i=0; i<57; i++){ sleep_mode(); } // 57sec.. for(t=0; t<4; t++){ // 1min x 4. send_data(wide, 32); for(i=0; i<59; i++){ sleep_mode(); } } } } int main(void) { main_olympus(); }