intervalometer2.jpg (72704 bytes) intervalometer1.jpg (57567 bytes)Intervalometer

"A device for periodically triggering a camera"

This application is designed to trigger a camera shutter using one of three methods on a periodic basis.  This devices allows for the creation of a very low weight high perfomance Kite Aerial Photography Rig.  There is a 8-position dip switch on Port B that configures the device on power-up. Port RA.0 is connected to a three pin header that is configured to connect to a standard remote control servo. A future modification of the code will also allow this port to trigger an Epic Stylus camera using a infrared remote trigger instead of a mechanical one.  Port RA.1 is connected to a small relay that is configured to trigger a Pentax ZX-M 35mm camera using its remote electronic trigger port.   The remaining pins of Port A are tied to ground and can be used in future revisions to the design.

I designed a simple pc board for the prototype circuit. I used the ExpressPC Board service. They provide a free package to design the circuits and they offer a prototype board service for about $60 (3 boards). My prototype board can be downloaded. The source code, including a hex file suitable for programming, is available for download.

Schematic

intervalometer.gif (12625 bytes)

Ciruit Diagram

Source Code

' Program:      intervalometer.bas
' Programmer:   Walter E Anderson
' Copyright 
' Notice:       Copyright (c) 2002 by Walter E Anderson
' Chip:         PIC 16F84
' Clock:        4 MHz
' Date Created: 29 May 2002
' Last Revised: 30 May 2002
'
'
' Revision History:
'
'
' Purpose:
'   This application is designed to trigger a camera shutter using one of 
' three methods on a periodic basis.  There is a 8-position dip switch on Port
' B that configures the device on power-up. Port RA.0 is connected to a three
' pin header that is configured to connect to a standard remote control servo.
' A future modification of the code will also allow this port to trigger an
' Epic Stylus camera using a infrared remote trigger instead of a mechanical
' one.  Port RA.1 is connected to a small relay that is configured to trigger
' a Pentax ZX-M 35mm camera using its remote electronic trigger port.  The
' remaining pins of Port A are tied to ground and can be used in future 
' revisions to the design.
'
'   As stated above the configuration of the application is controlled by the
' settings of an 8-position dip switch on port B.  The settings are as follows:
'
' Interval
' RB2 RB1 RB0   Value  Description
' --- --- ---   -----  ------------------
'  0   0   0      0    2 second interval
'  0   0   1      1    5 second interval
'  0   1   0      2    15 second interval
'  0   1   1      3    30 second interval
'  1   0   0      4    1 minute interval
'  1   0   1      5    2 minute interval
'  1   1   0      6    5 minute interval
'  1   1   1      7    10 minute interval
'
' Film capacity
' RB3: 0 - 24 exposure roll,  1 - 36 exposure roll
'
' Start-up delay
' RB4: 0 - 2 minute delay,  1 - 5 minute delay
'
' Output selection
' RB5: 0 - relay port (RA.1),  1 - servo port (RA.0)
'
' The following settings are only used if servo port selected.
'
' Signal type for servo port
' RB6: 0 - standard servo,  1 - infrared pulse stream
'
' Servo direction, only applicable if RB5=1 and RB6=0
' RB7: 0 - 1 millisecond, 1 - 2 millisecond
'
' @ __config _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
' -----------------------------------------------------------------
' VARIABLE and CONSTANT DEFINITION
'
FilmCount     	var     word ' Variable to hold picture count
TimerInterval 	var     word
Seconds		var 	word
ServoTime	var	word
TempByte      	var     byte
ClockTicks    	var     byte
Trigger       	var     bit  ' Variable to determine if trigger
' 
'
' -----------------------------------------------------------------
' Microcontroller Set-up
'
                ' Set PORTA.0, PORTA.1, and PORTA.2 for output
		TRISA = %11111000
                LOW PORTA.0
                LOW PORTA.1
		HIGH PORTA.2
                ' Set PORTB for input
		TRISB = %11111111
                ' Set TMR0 to trigger interrupt once every 16.384ms (61 ticks
                ' per second) 4MHz crystal, 1:64 prescaler, initialize TMR0
                ' to 0
                OPTION_REG = %10000101
                INTCON = %10100000
                ClockTicks = 0
                Seconds = 0
                TempByte = PORTB & %00000111 ' Based upon switch selection for
                SELECT CASE TempByte         ' RB0..RB2 set the timer interval
                   CASE 0                    ' to the number of seconds 
                      TimerInterval = 2      ' described above.
                   CASE 1                
                      TimerInterval = 5
                   CASE 2
                      TimerInterval = 15
                   CASE 3
                      TimerInterval = 30
                   CASE 4
                      TimerInterval = 60
                   CASE 5
                      TimerInterval = 120
                   CASE 6
                      TimerInterval = 300
                   CASE 7
                      TimerInterval = 600
                END SELECT
                IF (PORTB.3 = 1) THEN
                   FilmCount = 37 ' 37 exposures
                ELSE
                   FilmCount = 25 ' 25 exposures
                ENDIF
		PAUSE 1000
		LOW PORTA.2
                IF (PORTB.4 = 0) THEN
                   ' Wait for 2 minutes on start-up
                   FOR TempByte = 0 TO 119
                      PAUSE 1000 ' Ok to use long pause since no Interupts yet
                   NEXT TempByte
                ELSE
                   ' Wait for 5 minutes on start-up
                   FOR TempByte = 0 TO 299
                      PAUSE 1000
                   NEXT TempByte
                ENDIF
                Trigger = 0
		TMR0 = 0
                ON INTERRUPT GOTO IntHandler
                GOTO Main
' -----------------------------------------------------------------
' Interrupt Handler
'
IntHandler:     DISABLE ' Prevent any new interrupts during interrupt handler
                ClockTicks = ClockTicks + 1
                IF (ClockTicks < 61) THEN IntExit
                ClockTicks = 0
                Seconds = Seconds + 1
                IF (Seconds < TimerInterval) THEN IntExit
                Seconds = 0
                Trigger = 1
IntExit:        INTCON = %10100000 ' Clear the event flags
                ENABLE ' Re-enable interrupts
                RESUME
'
' -----------------------------------------------------------------
' Main program loop
'
Main:           ' This is the standard 'center' pulse for a servo
		ServoTime = 1500
                ' Test to see if TimerInterval has expired
                IF (Trigger = 1) THEN
                   IF (PORTB.5 = 0) THEN ' Use Relay Port
                      HIGH PORTA.1
		      HIGH PORTA.2
                      FOR TempByte = 0 TO 29 ' 0.3 second delay total while
                         PAUSE 5	     ' still allowing the timer 
                      NEXT TempByte          ' interrupt to be serviced
                      LOW PORTA.1
                      LOW PORTA.2
                   ELSE ' Use Servo Port
                      IF (PORTB.6 = 0) THEN 
                         ' Standard servo signals
                         ' This code only adjust the pulse length.
                         ' It does not actually send the pulse to the servo
                         IF (PORTB.7 = 0) THEN 
                            'Send 1 millisecond pulse
                            ServoTime = 1000
                         ELSE 
                            'Send 2 millisecond pulse
                            ServoTime = 2000
                         ENDIF
                      ELSE 
                         ' Send EPIC Pulse stream
                      ENDIF
                   ENDIF
                   ' Decrement Film Counter
                   FilmCount = FilmCount - 1
                   IF (FilmCount <= 0) THEN
                      'Shutdown the circuit
                      DISABLE ' Turn off interrupts
		      HIGH PORTA.2
		      PAUSE 30000
		      LOW PORTA.2
                      END ' Stop execution and place PIC in sleep mode
                   ENDIF
                   Trigger = 0
                ENDIF
                ' The following code tests to see if the servo output port is
 		' selected and if so send the pulse stream to maintain position
		IF ((PORTB.5 = 1) AND (PORTB.6 = 0)) THEN
                   HIGH PORTA.0
                   PAUSEUS ServoTime
                   LOW PORTA.0
		   IF (ServoTime <> 1500) THEN
		      HIGH PORTA.2
                      FOR TempByte = 0 TO 29 ' 0.3 second delay total while
                         PAUSE 10	     ' still allowing the timer
    	                 HIGH PORTA.0
          	         PAUSEUS ServoTime
                	 LOW PORTA.0 
                      NEXT TempByte          ' interrupt to be serviced
                      LOW PORTA.2
		      ServoTime = 1500
 		   ELSE
                      PAUSE 10  ' This delay results in a XX update frequency
		   ENDIF
                ENDIF
                GOTO Main

This page and all of its contents are Copyright © 2002 by Walter Anderson
Home Page