Fernauslöser für Kameras via Servosteuerung

 

(c) C. Winter 2009, v1.1

 

Als Wetterinteressierter haben mich Blitze schon immer fasziniert. Durch diese Seite (http://www.techlib.com/electronics/lightning.html) bin ich auf einen Blitzdetektor und eine Möglichkeit, darüber seine Kamera bei Blitzen auslösen zu lassen („Readers Versions“), aufmerksam geworden.

 

Da ein Blitz normalerweise aus mehreren Entladungen besteht, die im Abstand weniger Millisekunden den gleichen Entladungskanal entlang laufen (s. auch Wikipedia), besteht eine gute Chance, beim Auslösen der Kamera im ersten Entladungsfall noch weitere Entladungen (=Blitz) aufs Bild zu bannen.

 

Leider hat meine Kamera keine Möglichkeit, über ein externes Signal zur Aufnahme bewegt zu werden. Außerdem suchte ich schon seit längerem nach einen Fernauslöser.. Also musste ich einen Weg suchen, die Kamera über den normalen Druckknopf-Auslöser zu betätigen. Dafür biete sich ein Servo an, dessen Ruderhorn statt meines Fingers auf den Knopf drückt.

 

Das vorliegende Programm läuft auf einem ATtiny25. Mit einer (!) LED werden die Betriebszustände angezeigt:

 

  1. Bleibt nach dem Einschalten die LED rot, bedeutet dies, dass vermutlich kein EEPROM mit Werten gebrannt wurde. Da initiale Positionswerte für das Servo benötigt werden und ohne diese das Servo in eine schädigende Anschlagposition gefahren werden könnte, wird aus Sicherheitsgründen kein Programm ausgeführt. Bitte das EEPROM entsprechend brennen!

  2. Initialisierung: ca. 3 Sekunden blinkt die LED sehr schnell. Wenn man innerhalb dieser Zeit beliebige zwei der drei Tasten gleichzeitig betätigt, kann man die folgenden Servopositionen festlegen.

    1. „Ruhestellung“: Während die LED etwas langsamer blinkt, kann die Position mit den Schaltern 1 und 2 verändert werden (während des Drückens leuchtet die LED dauernd).  Das Ruderhorn sollte hier gerade noch nicht den Auslöse-Knopf berühren. Durch Drücken von Schalter 3 wird die LED für eine Sekunde hell geschaltet und der Wert ins EEPROM übernommen.

    2. Die LED blinkt nun wieder moderat für das Setzen der zweiten Position, „Vorgespannt“: Das Ruderhorn wird mit Taste 1 oder 2 so positioniert, dass es das den Knopf soweit herunterdrückt, dass die Fokussierung einsetzt. Praktisch auch dann, wenn sich die Kamera ohne Betätigung schnell schlafen legt – so bleibt sie aktiv. Durch Drücken von Schalter 3 wird die LED wieder für eine Sekunde hell geschaltet und der Wert ins EEPROM übernommen.

      Natürlich kann man das Ruderhorn auch so positionieren, dass in der vorgespannten Stellung keine Berührung des Knopfes stattfindet, wenn man dies nicht möchte – dann z.B. einfach Taste 3 drücken und die „Ruhestellung“-Position auch für die „Vorgespannt“-Position verwenden.
    3. Die Dritte Positionsfestlegung wird wieder durch moderat schnelles Blinken angezeigt, Position „Ausgelöst“: Das Ruderhorn wird mit Taste 1 oder 2 so weit herabgesenkt, dass die Aufnahme ausgelöst wird. Wieder durch Drücken von Schalter 3 wird die LED für eine Sekunde hell geschaltet und der Wert ins EEPROM übernommen.

  3. Wenn innerhalb der Zeit, in der die LED schnell blinkt, kein Knopf gedrückt wurde, oder wenn die Neu-Positionierung vorgenommen wurde, gelangt man zum folgenden Punkt:

  4. Das Servo fährt in die Ruhestellung, die im EEPROM hinterlegt ist/war, die LED blinkt in langsamen Rhythmus.

 

Die folgenden Punkte können in beliebiger Reihenfolge ausgeführt werden:

 

 

Nun noch das Servo an der Kamera angebracht (kann durchaus der schwierigere Teil sein ;)), und schon hat man einen Fernauslöser (Schalter 3), der auch durch Gewitterblitze ausgelöst werden kann :)

 

 

Zum Programm:

Vorab: dies ist erst mein drittes AVR-Projekt, bin also kein Profi :)

 

Der ATtiny25 wird auf 8 MHz getaktet (Vorteiler wird auf 1 zurückgestellt), die Fuses bleiben unberührt. Damit lässt sich der Servo-Befehl gut ausführen. Alle Pins des Controllers werden entweder als Schalter-PINs oder LED- und Servo-PORT genutzt. Timer0 (Servo) und Timer1 werden geschaltet, letzter als Zeitintervall. Der Timer1 wird derzeit von BASCOM nicht über alle BASCOM-Codes unterstützt, hier muss man diverse Register direkt ansprechen – dank an FarmTech für den Tipp).

 

Zum Schaltbild:

Vorab: Dies ist mein erster selbst gezeichneter Schaltplan. Fehler dürfen korrigiert werden und gehören dem Finder.

 

Schalter wurden gegen GND und nicht gegen 5V geschaltet, um Bauteile zu sparen. SV1 sind die Stecker für die Spannungsversorgung (a.k.a. „Stecker“), J2 sind drei Pins einen Pinleiste als Steckseite für die Buchse des Servos (JR-Kupplung).

 

Schaltplan als Eagle-Datei auf Anfrage!

 

 

Das Bild zeigt die Servosteuerung (grün umrandet) mit dem Blitzdetektor (rot umrandet) auf einer Lochrasterplatine. Nur die Stromversorgung und der Trigger für den Blitzt verbindet beide Bauabschnitte.

Schalter 1 und 2 wurden als Wechselschalter realisiert. Ein zusätzlicher, optionaler 1µF-Kondensator wurde zwischen den Stromversorgungs-Pins zum Servo geschaltet.

Der Servo wurde mit einem Telefonkabel/Telefonbuchse als Verlängerungskabel verbunden.

 

Für die Beschaltung des Blitzdetektors siehe http://www.techlib.com/electronics/lightning.html

 

 

Verdrahtungsseite (nicht hübsch, aber funktioniert!):

 

Servo-Montage an der Kamera mithilfe eines Blitzhalters.

 

Ruhe- und Auslöseposition des Servos (das Ruderhorn wurde geknickt, um eine einfacheres Auslösen zu ermöglichen).

 

... selbiges von vorne.

 

Code:

 

'-------------------------------------------------------------------------------

' Filename   : FernausloeserATtiny25_2.bas

' Zweck      : Fernauslösersteuerung mit Servo für Kameras ohne externe Auslösemöglichkeit.

' Datum      : 06.06.2009, 28.06.09

' Autor      : Dr. Christoph Winter

' Funktion   : siehe http://www.jurmo.de/AVR

' Controller : ATtiny25

' Compiler   : BASCOM-AVR   Rev. 1.11.9.4

'

' Features:

' - Conrad BestNr: 227726 - Top Line Standard Servo ES-30 JR

' - Arbeitet mit dem Blitzdetektor von http://www.techlib.com/electronics/lightning.html zusammen

'

' To Do:

' -

'

' Features for the future:

' -

'

' History:

' - V1.0 06.06.2009 Fertigstellung

' - V1.11 28.06.2009 Position setzen am Anfang nur mit Taster1+2 o. 1+3 o. 2+3, nicht 3 allein!

'

' Free for noncomercial use!

' For commercial use contact avr@jurmo.de

' All rights reserved!

'--------------------------------------------------------------

 

'-------------------------------------------------------------------------------

' Testaufbau auf Pollin+BreadBoard +  Lochrasterplatine.

' ATMEL Evaluations-Board V2.0.1 mit ATtiny25

'-------------------------------------------------------------------------------

'$sim

 

' Pin Configuration ATtiny25

'     +-------+

' PB5 |1     8| VCC

' PB3 |2     7| PB2

' PB4 |3     6| PB1

' GND |4     5| PB0

'     +-------+

' Nicht relevant, aber zu merken:

' On ATtiny25, the programmable I/O ports PB3 and PB4 (pins 2 and 3) are exchanged in ATtiny15 Compatibility Mode for supporting the backward compatibility with ATtiny15.

'

$regfile="ATtiny25.dat"

 

$crystal=8000000 ' externer Quarz oder interner Oszillator mit Vorteiler 1 (Fuse CKSEL0=0 CKSEL1=0 CKSEL2=1 CKSEL3=0 SUT0=0 SUT1=0) 0=programmiert, 1=nicht programmiert

' Setzt CLKPR auf Vorteiler=1 -> Kein Vorteiler -> 8 MHz statt 1MHz

$ASM

    Ldi R16 , &B10000000

    Out CLKPR,R16

    Ldi R16, &B00000000

    Out CLKPR,R16

$END ASM

 

$hwstack=40

$swstack=30

$framesize=30

'$Baud    =4800 'Baudrate für UART

$EEPROMHEX ' Nicht mit   PonyProg!!!

$eepleave

 

 

'===============================================================================

' BELEGUNGEN PIN und PORT

 

DDRB =&B11111000

PortB=&B00000111 'pullup (0= low level; 1= high level)

 

Taste3 alias PinB.0 ' Pin benamsen

Taste2 alias PinB.1 ' Pin benamsen

Taste1 alias PinB.2 ' Pin benamsen

LED1         alias PortB.4 ' Port Signalausgabe-Anzeige (flackert schell)

SignalServo1 alias PortB.3 ' Port für Servosignal - Pin #20 im Mega16-Sockel

 

'===============================================================================

' VARIABLEN

 

' Werte aus dem EEPROM:

dim BDummy       as ERAM Byte ' die erste EEPROM-Speicherstelle leer lassen

dim EEChk        as ERAM Byte ' Prüfen, ob EEPROM schon belegt ist

dim E_Ruhe       as ERAM Byte ' Ruheposition

dim E_Vorspannen as ERAM Byte ' Position "Vorgespannt"

dim E_Ausloesen  as ERAM Byte ' Position "Auslösen"

 

' Vorbelegungen:

' Verwendetes Servo: Conrad ES-05 BestNr. 230500

dim Ruhe as Byte        ' Position

dim Vorspannen as Byte  ' Position

dim Ausloesen as Byte   ' Position

dim B as Byte           ' Hilfsvariable

dim PosVal as Byte      ' Hilfsvariable Positionierung

 

dim Bitleiste as Byte   ' Bitleistenvariable

Flag_Mitte alias Bitleiste.0 ' mittlerweise obsolet

Flag_Timer1_Overflow alias Bitleiste.1 ' Überlaufindikator

Flag_Taste1 alias Bitleiste.2 ' Tastenindikator

Flag_Taste2 alias Bitleiste.3 ' Tastenindikator

Flag_Taste3 alias Bitleiste.4 ' Tastenindikator

Flag_Vorgespannt alias Bitleiste.5 ' Positionsindikator

 

const Timervorgabe=62000 '62000 ' 49911 ' 34286

dim Timersetting as Word ' Blink- und Überlauffrequenz

dim MaxDrehung as Byte   ' Ginge auch als CONST

dim MinDrehung as Byte   ' Ginge auch als CONST

 

 

'===============================================================================

' TIMER

 

' config Timer1=Timer, prescale=8192 '-> s. page 87 of datasheet, geht nicht mit ATtiny25!

Tccr1 = &B00001110

 

on Timer1 Timer1_IRQ

 

' TIMER0 = Servo

config Servos=1, Servo1=SignalServo1, Reload=10

enable Interrupts

Servo(1)=60

 

'===============================================================================

' DEFINITIONS

declare Sub Presetting(Wert as Byte)

 

 

'===============================================================================

' INIT

 

#IF _SIM

  E_Ruhe=60

  E_Vorspannen=70

  E_Ausloesen=80

#ELSE

  if EEChk<>127 then

    LED1=0 ' ROT! Kein EEPROM gebrannt!

    end

  end if

#ENDIF

 

Ruhe=E_Ruhe ' fixer Positionswert (empirisch bestimmt)

Vorspannen=E_Vorspannen ' fixer Positionswert (empirisch bestimmt)

Ausloesen=E_Ausloesen ' fixer Positionswert (empirisch bestimmt)

 

MaxDrehung=150 ' Maximalwert! Anschlag!

MinDrehung=30 ' Minimalwert! Anschlag!

 

 

enable timer0

enable timer1

enable Interrupts

Servo(1)=Ruhe ' In Startstellung

B=0 ' hier: Zeitintervall-Zähler

wait 1 ' Entprellen nach Einschalten (Kondensatoren laden, Servo in Startposition fahren, etc...)

 

Timersetting=65000 ' Schnell blinken!

do

  if Flag_Timer1_Overflow=1 then

    Flag_Timer1_Overflow=0

    toggle LED1

    incr B

  end if

  ' Mindestens 2 Tasten müssen gleichzeitig gedrückt sein -> kein Entprellen notwendig!

  if Taste1=0 and Taste2=0 then Flag_Taste3=1 ' Ändern? Dann einfach mal flaggen!

  if Taste1=0 and Taste3=0 then Flag_Taste3=1 ' Ändern? Dann einfach mal flaggen!

  if Taste2=0 and Taste3=0 then Flag_Taste3=1 ' Ändern? Dann einfach mal flaggen!

  if Flag_Taste3=1 then

    B=255

  end if

loop until B>=100 ' 50 mal blinken (100x toggle)

if Flag_Taste3=0 then goto Main ' Keine Änderung der Settings! Mit GOTO! (urgs!)

 

LED1=1 ' Aus

wait 1 ' Loslassen aller Tasten!

 

' Voreinstellungen ändern

Flag_Taste1=0

Flag_Taste2=0

Flag_Taste3=0

Timersetting=63500 ' Step- und Blinkfrequenz etwas langsamer

 

' Positionen einstellen

call Presetting(Ruhe)

E_Ruhe=Ruhe

'MinDrehung=Ruhe

 

Vorspannen=Ruhe ' Position übernehmen

call Presetting(Vorspannen)

E_Vorspannen=Vorspannen

'MinDrehung=Vorspannen

 

Ausloesen=Vorspannen ' Position übernehmen

call Presetting(Ausloesen)

E_Ausloesen=Ausloesen

 

Timersetting=65000 ' Schneller ISR, aber Zähler für Blinken (s.u.)

Main:

 

Servo(1)=Ruhe ' In Startstellung

Flag_Taste1=0

Flag_Taste2=0

Flag_Taste3=0

 

'===============================================================================

' MAIN

do

 

  if Flag_Timer1_Overflow=1 then

    Flag_Timer1_Overflow=0

    incr B

    if B>=35 or Flag_Vorgespannt=1 then

      B=0

      LED1=0

    else

      LED1=1

    end if

 

    PosVal=Servo(1)

    Servo(1)=PosVal ' Immer mal wieder aktualisieren zum Stabilisieren (*nicht* dringend benötigt!)

  end if

 

  debounce Taste1, 0, SubTaste1, sub

  debounce Taste2, 0, SubTaste2, sub

  debounce Taste3, 0, SubTaste3, sub

 

  if Flag_Taste2=1 then ' Bei Taste 2 Vorspannen

    Flag_Taste2=0

    Servo(1)=Ruhe

    Flag_Vorgespannt=0

  end if

  if Flag_Taste1=1 then ' Bei Taste 1 Ruhen

    Flag_Taste1=0

    Servo(1)=Vorspannen

    Flag_Vorgespannt=1

  end if

  if Flag_Taste3=1 then ' Bei Taste 3 Auslösen

    Flag_Taste3=0

    Servo(1)=Ausloesen

    Flag_Vorgespannt=1

    B=0

    do

      waitms 25

      incr B

      toggle LED1

    loop until B>=10 and Taste3=1 ' Wenn Schalter gedrückt bleibt, bleibt auch das Servo in Auslöseposition (Serienaufnahmen).

    Servo(1)=Ruhe

    B=0

    do

      waitms 25

      incr B

    loop until B>=10

    Servo(1)=Vorspannen

  end if

 

loop

end

 

'===============================================================================

' SUBROUTINEN

Timer1_IRQ:

  tcnt1=Timersetting

  '"Timer1=Timervorgabe" geht nicht

  Flag_Timer1_Overflow=1

return

 

SubTaste1: ' rechts

  Flag_Taste1=1

return

 

SubTaste2: ' links

  Flag_Taste2=1

return

 

SubTaste3:

  Flag_Taste3=1

return

 

Rechts:

  LED1=0

  do

     if Flag_Timer1_Overflow=1 then

       Flag_Timer1_Overflow=0

       incr PosVal

       if PosVal>MaxDrehung then PosVal=MaxDrehung

       Servo(1)=PosVal

     end if

  loop until Taste1=1

  waitms 25 ' Debounce

return

 

Links:

  LED1=0

  do

     if Flag_Timer1_Overflow=1 then

       Flag_Timer1_Overflow=0

       decr PosVal

       if PosVal<MinDrehung then PosVal=MinDrehung

       Servo(1)=PosVal

     end if

  loop until Taste2=1

  waitms 25 ' Debounce

return

 

Sub Presetting(byref Wert as Byte)

  PosVal=Wert ' Voreinstellen

  Servo(1)=PosVal

  do

 

    if Flag_Timer1_Overflow=1 then

      Flag_Timer1_Overflow=0

      toggle LED1

      Servo(1)=PosVal ' immer mal wieder...

    end if

 

    debounce Taste1, 0, SubTaste1, sub

    debounce Taste2, 0, SubTaste2, sub

    debounce Taste3, 0, SubTaste3, sub

 

    if Flag_Taste1=1 then

      Flag_Taste1=0

      gosub Rechts

    end if

    if Flag_Taste2=1 then

      Flag_Taste2=0

      gosub Links

    end if

 

    if Wert<>PosVal then ' Wenn sich was geändert hat...

      Wert=PosVal

      Servo(1)=Wert

    end if

 

    ' Wenn Taste 3 gedrückt wurde

    if Flag_Taste3=1 then ' Im Eeprom speichern

      LED1=0

      wait 1

      LED1=1

    end if

 

  Flag_Taste1=0 ' jetzt obsolet, Code-Leiche ;-)

  Flag_Taste2=0 ' jetzt obsolet, Code-Leiche ;-)

 

  loop until Flag_Taste3=1

  Flag_Taste1=0

  Flag_Taste2=0

  Flag_Taste3=0

  waitms 25 ' Debounce

end Sub

 

 

 

'===============================================================================

'  .NNNL.   JNNN_  N)JNN_  (NJNN  JNNN.  (N.NNL.JNN.

' (NN"4NN. NNF"NNL NNN"NNL (NN"N NNF"NN) (NN"NNNF4NN

' NN___JN)(NL___NN NN   NN (N)  (N)   NN (N)  NF  (N

' NNNNNNN)(NNNNNNN N)   (N (N   (N    (N (N   N)  (N

' NN   ._.(N)   __ NN   NN (N   (N)   NN (N   N)  (N

' (NNLJNN` NNN_NNF NNN_NN) (N    NNL_NN) (N   N)  (N

'  `NNNF`   4NNN"  NF4NN"  (N     4NNN`  (N   N)  (N

'                  N)

'==================N)===========================================================

$eeprom

  DATA 0   ' 1. Stelle - immer ungenutzt!

  DATA 127 ' 2. Stelle: Kennung: Beschrieben! (default ist 255):

  DATA 50, 60, 70 ' Initial-Positionen

  DATA "Fernausloeser (c) C. Winter 2009"

$data

end

 

 

Christoph Winter, 2009

Alle Rechte vorbehalten

Zurück zur Hauptebene / Back to main level



Last change: freigeschaltet C. Winter, 7. Juni  2009