Canon EOS 350D über Arduino Nano ansteuern

Hallo zusammen!

Ich möchte meine Spiegelreflex über einen Arduino Nano ansteuern. Dazu muss ich zwei verschiedene Kontakte auf Masse ziehen.
Kann ich das über zwei kleine Relais machen? Ich habe bei Reichelt folgendes Relais gefunden:
http://www.reichelt.de/Reedrelais-Magnete/DIP-7212-D-5V/3/index.html?;ACTION=3;LA=446;ARTICLE=27651;GROUPID=3291;artnr=DIP+7212-D+5V
Den Code habe ich soweit fertig und mit zwei LEDs die Relais Simuliert.
Muss ich bei den Relais etwas beachten wenn ich diese am Arduino anschließe?
Ich würde an die Spule des Relais einmal Masse und einen Pin des Arduino anschließen.
Funktioniert das so?
Über eure Hilfe würde ich mich freuen!

Grüße

Lutz

Reed Relais sind Magnetschalter (oder sehr zuverlässige Relais mit Reed-Kontakten). Du willst eher Miniaturrelais. z.B.:
http://www.reichelt.de/Miniaturrelais/G5V-1-5V/3/index.html?;ACTION=3;LA=2;ARTICLE=28332;GROUPID=3292;artnr=G5V-1+5V
http://www.reichelt.de/Miniaturrelais/JV-05/3/index.html?;ACTION=3;LA=2;ARTICLE=79391;GROUPID=3292;artnr=JV+05

Und dann einen kleinen Transistor (z.B. BC337 oder irgendeinen anderen NPN in TO-92) als Treiber davor, da ein Arduino Pin nur 40mA liefert. Nimm diese Schaltung:

Die linke, und ganz wichtig: die Diode nicht vergessen. Für den Basiswiderstand etwa 1-2kOhm

Wenn da nicht viel Strom fließt, kann man auch Analogschalter HC4066 nehmen. Das kommt darauf an was du da genau schalten willst. Ich habe bei mir z.B. ein Gerät durch den UNO steuern wollen und dabei die Taster des Geräts mit Analogschaltern überbrückt (das Gerät "denkt" dann sie wären gedrückt) und ein Relais nur für den AN/AUS Taster genommen wo mehr Strom geflossen ist. Funktioniert sehr schön, nimmt wenig Platz weg und ist lautlos. Wenn du aber was mit Leistung auf Dauer schalten willst sind Relais die korrekte Wahl.

Hallo zusammen,

ich habe mir eben mal das Datenblatt des genannten Relais angeschaut.

Das Relais hat einen Spulenwiderstand von 200 Ohm, daraus resultiert ein Spulenstrom von 25mA, also kein Problem für einen Ausgang.
Solange es bei zwei Relais bleibt, ist kein Treiber erforderlich, da der Summenstrom von 200mA nicht überschritten wird.

Da das Relais eine Freilaufdiode integriert hat, ist jedoch unbedingt die Polung zu beachten!
An Pin 2 kommt der Arduino-Ausgang, Pin 6 kommt an Masse.

Grüße

Martin

Hab ich auch gerade gemacht :wink:

Die Variante mit einem 4066 halte ich aber auch für die bessere, da die EOS sicherlich auch damit zurechtkommt. Sollte mich sehr wundern wenn nicht :~

Vorteil: kleiner, deutlich weniger Stromverbrauch

Danke erstmal für eure schnellen Antworten!

Wenn ich das richtig verstanden habe kann ich den 4066 verwenden da ich nur ca 10mA schalten muss.
Kann ich dann einfach den Control-Pin vom 4066 mit nem Arduino-Pin ansteuern oder muss ich da noch Widerstände oder ähnliches integrieren?

Grüße

Lutz

Das geht einfach so, wie bei anderen Logic-ICs auch.

Ich habe bei mir einen der Ausgänge jeden Schalters fest auf Masse gelegt und den anderen mit dem offenen Kontakt des Tasters verbunden. Dann muss man nur noch die Masse des ICs/Arduinos einmal mit der Masse des Geräts verbinden.

Du solltest die Eingänge der zwei unbenutzten Taster (es sind 4 pro IC) auch auf Masse legen.

Du brauchst gar kein Relais.
Möglichkeiten:

  • Für Selbsichere und solche die wissen was sie machen der minimalismus: Negativeren Pol des Remoteanschlußes auf Gnd Arduino schalten und auf die anderen 2 Anschlüße je ein Pin und dieses zwischen Eingang ( offen) und Ausgang LOW (gedrückt) umschalten Ausgang HIGH darf dabei nie geschalten werden!!!.
  • NPN Transistor über Basiswiderstand ansteuern, Emittor auf GND, negativeren Pol des Remoteanschlußes auf Gnd Arduino schalten und Positiveren auf Collektor
  • Optokopler: Emittor auf negativeren Pol des Remoteanschlußes; Collektor auf positiveren. Optokoppler mit vorwiderstand wie LED ansteuern.
  • Über Infrarotschnittstelle der EOS 350D http://sebastian.setz.name/arduino/my-libraries/multi-camera-ir-control/
  • Über Universal-TV-Fernsteuerung bei bestimmten Codeeinstellung Universal remote with Canon cameras
  • Über PTP Interface USB- Interface wie von PC und mitgelieferten Steuerprogramm. Dazu brauchst Du ein USB HOST Shield. http://www.circuitsathome.com/tag/ptp . Vollkontrolle inclusive Verschlußzeiten, Blende ecc. bei einigen Objektiven auch Fokussteuerung.

Grüße Uwe

Mhh stimmt, bei nur 10mA gibt es noch andere Optionen. Optokoppler wären sehr gut. Die brauchen keine extra Betriebsspannung wie die ICs :slight_smile:

z.B. hier mit 2 in einem DIP-8 Gehäuse:
http://www.reichelt.de/Optokoppler/ILD-74/3/index.html?;ACTION=3;LA=446;ARTICLE=8773;GROUPID=3046;artnr=ILD+74

Kam bei mir leider nicht in Frage, da die Pullups des Geräts sehr niedrig waren und ich keine mit genügend Kollektorstrom gefunden habe (bzw. das oft nicht vernünftig angegeben ist)

Optokoppler: Du nimmst einen H11F1M, H11F2M, H11F3M und Du brauchst die Polung an der Kamera nicht zu beachten.
Grüße Uwe

Einen Großen Dank nochmal für die vielen Tipps und Hilfestellungen!
Ich hab mich für den 4066 entschieden und das funktioniert auch 1A!

Beim weiteren aufbau meines Projekts habe ich festgestellt das die delay-Funktion nur bis 32000ms funktioniert. Ich variiere die Belichtungsdauer über ein Poti. Dabei möchte ich den Bereich von 30Sekunden bis 600 Sekunden abdecken. Die Zeit lasse ich mir in Sekunden auf einem LCD-Display anzeigen. Wenn ich jetzt aber den Wert in Millisekunden anzeigen lasse kann ich beobachten das der Wert ab 32000ms wieder sinkt und sogar bis -32000 sinkt obwohl ich das Poti weiter erhöhe.

Habt ihr da einen Tipp für mich wie ich das Problem umgehen kann?
Hier mein Code:

// include the library code:
#include <LiquidCrystal.h>
int sensor1=A0;
int sensorvalue=0;
int verschlusszeitsekunden=0;
int verschlusszeit=0;
int ausloeser=10;
int ausloeseknopf=9;
int buttonstate=0;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  pinMode(ausloeser, OUTPUT);
  pinMode(ausloeseknopf, INPUT);
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.clear();
  lcd.setCursor(15, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(15, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(14, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(14, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(13, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(13, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(12, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(12, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(11, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(11, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(10, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(10, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(9, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(9, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(8, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(8, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(7, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(7, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(6, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(6, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(5, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(5, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(4, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(3, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(2, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(3, 1);
  lcd.print("INTERFACE");
  delay(100);
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Canon Digital");
  lcd.setCursor(3, 1);
  lcd.print("INTERFACE");
  delay(4000);
  lcd.clear();
}

void loop() {
  sensorvalue=analogRead(sensor1);
  verschlusszeitsekunden=map(sensorvalue, 0, 1023, 30, 600);
  verschlusszeit=(verschlusszeitsekunden*1000);      
  buttonstate=digitalRead(ausloeseknopf);
  lcd.clear();
  lcd.setCursor(1, 0);
  // print the number of seconds since reset:
  lcd.print("Verschlusszeit:");
  lcd.setCursor(1,1);
  lcd.print(verschlusszeitsekunden);
  lcd.setCursor(7,1);
  lcd.print("Sekunden");
  delay(200);

  if(buttonstate == HIGH){
    digitalWrite(ausloeser, HIGH);
    lcd.clear();
    lcd.setCursor(1,0);
    lcd.print("Bitte LAECHELN");
    lcd.setCursor(1,1);
    lcd.print(verschlusszeitsekunden);
    lcd.setCursor(5,1);
    lcd.print("Sekunden");
    delay(verschlusszeit);
    digitalWrite(ausloeser, LOW);
  }
  else {
    digitalWrite(ausloeser, LOW);
  }
}

Gruß Lutz

Du meinst sicher 32768 ms

Dein Code ist mir zu lang um das zu suchen *), aber
int ist einfach der falsche Datentyp für Zahlen die

  • nicht < 0 sein können
  • größer als 32767 werden können

Und für Zahlen, die nicht größer als 255 werden, ist es einfach Verschwendung.
Das einzige schlechte Grund, int zu nehmen, ist dass man so wenige Tasten tippen muss.


*) verschlusszeit=(verschlusszeitsekunden*1000);     

Und warum sind verschlusszeit und verschlusszeitsekunden globale Variable ?
Nur damit man den Fehler nicht gleich sieht ?

Danke erstmal für die Antwort.
Leider komme ich mit der Antwort nicht weiter.

int ist einfach der falsche Datentyp für Zahlen die

  • nicht < 0 sein können
  • größer als 32767 werden können

Welchen Datentyp muss ich für große Zahlen benutzen?

Und warum sind verschlusszeit und verschlusszeitsekunden globale Variable ?
Nur damit man den Fehler nicht gleich sieht ?

Wie muss ich das Verstehen?

Da Ich Anfänger im Programmieren bin und mir meine bisherigen Projekte aus Beispielcodes zusammengewürfelt habe war das für mich so erstmal richtig. Aber ich möchte gerne aus meinen Fehlern lernen und würde mich über Tipps sehr freuen!

Hier nochmal der gekürzte Code:

int sensor1=A0;
int sensorvalue=0;
int verschlusszeitsekunden=0;
int verschlusszeit=0;
int ausloeser=10;
int ausloeseknopf=9;
int buttonstate=0;


void setup() {
  pinMode(ausloeser, OUTPUT);
  pinMode(ausloeseknopf, INPUT);
}

void loop() {
  sensorvalue=analogRead(sensor1);
  verschlusszeitsekunden=map(sensorvalue, 0, 1023, 30, 600);
  verschlusszeit=(verschlusszeitsekunden*1000);      
  buttonstate=digitalRead(ausloeseknopf);
 
  if(buttonstate == HIGH){
    digitalWrite(ausloeser, HIGH);
    delay(verschlusszeit);
    digitalWrite(ausloeser, LOW);
  }
  else {
    digitalWrite(ausloeser, LOW);
  }
}

unsigned long ist das größte für positive Zahlen. Hat 4 Bytes und geht bis 4,294,967,295:
http://arduino.cc/en/Reference/UnsignedLong

Das ist auch womit Delay intern arbeitet:
http://arduino.cc/en/Reference/Delay

Wenn du da einen 2-Byte int übergibst wandelt der das in einen ulong um

Rein theoretisch könntest du auch unsigned int nehmen. Dann hättest du schon maximal das doppelte als mit dem normalen signed int: max. 65,535

Generell zu den Datenbereichen kannst du dir z.B. mal das ansehen:

Das ist für .NET/Visual C++ und weicht daher etwas ab, aber grob passt es. Was es beim Arduino nicht gibt sind 8-Byte Double. Die sind genauso breit wie Float (4 Byte). Und 64-Bit Typen gibt es natürlich generell nicht. Dafür aber "byte" für 0-255. Ints sind 2-Byte, also Int16 und immer signed. Da sieht man z.B. auch dass bools immer ein ganzes Byte belegen. Aber die Bereiche sind halt übersichtlich angegeben.

Wenn du durch Tips mehr lernst als durch selber googeln, bitte sehr:

int  verschlusszeitsekunden=map(sensorvalue, 0, 1023, 30, 600);
unsigned long  verschlusszeit=(verschlusszeitsekunden*1000L);

Ein Tip: (int)600 * 1000 ist beim Arduino nicht 600000, probiere es aus und staune !
Zu den Datentypen findest du hier einige Anregungen: Arduino - Home

Danke für die Hilfe!
Hab den Tipp ins Programm übernommen und es funktioniert :slight_smile:
Bisher war mir das nicht klar, dass es verschiedene Datentypen gibt.Ich kannte nur int :frowning: Werd mir eure Links mal genau anschauen und durchlesen!

Grüße

Lutz

Int ist halt auch nicht gleich int. Das hängt von der Implementierung ab. Wenn du z.B. Programme für den PC schreibst hat int i.d.R. 4 Byte. Wir sind hier aber auf einem 8-Bit Prozessor, daher nur 2 Byte.

Oder nimm C#:

Da hat char plötzlich 2-Byte, da mit Unicode gearbeitet wird

Int ist halt auch nicht gleich int. Das hängt von der Implementierung ab.

Stimmt, int überlässt es dem Compiler, die natürliche Größe für den Prozessor auszuwählen.

Wenn man es genau festlegen will, gibt es übrigens auch die Datentypen
int8_t, int16_t, int32_t, uint8_t, uint16_t, uint32_t.

P.S.

Hab den Tipp ins Programm übernommen und es funktioniert

Funktioniert sogar, wenn du noch in deinem Sketch am Anfang die Zeilen

[s]int verschlusszeitsekunden=0;[/s]
[s]int verschlusszeit=0;[/s]

rausschmeisst :wink:

Habs gestern schon rausgeschmissen da es ja quasi doppelt vorkam. Ich dachte vorher immer, dass ich alle Variablen vor dem voidSetup aufführen muss. Wieder was gelernt :slight_smile:

Das kommt darauf wie du sie verwendest. Variablen die außerhalb der Funktionen deklariert werden, sind "global". D.h. sie sind für alle Funktionen sichtbar. Variablen die innerhalb einer Funktion deklariert werden - "lokal" - existieren für die anderen Funktionen nicht.

Man sollte globale Variablen nur verwenden wenn man es wirklich braucht. Manchmal lässt sich da natürlich nicht vermeiden oder es wird dann zu kompliziert. Also, lass dir nicht sagen, dass es immer schlecht ist.
Aber wenn du z.B. eine Variable durch eine Funktion ändern willst, dann macht man das i.d.R. durch das Übergeben von Parametern und gibt den geänderten Wert mit return zurück (oder bei C kann man auch Pointer als Parameter übergeben), statt die Variable global zu definieren.

Hier kommt noch hinzu dass wenn du "int var = 0" in der loop machst, diese Variable bei jedem Durchlauf zurückgesetzt wird. Wenn sie also ihren Zustand behalten soll muss man das außerhalb schreiben ("static" sollte dafür aber auch funktionieren).

Persönlich stelle ich bei globalen Variablen immer ein "" davor. Dann sieht man es gleich. Hat außerdem den Vorteil, dass man in einer IDE mit AutoComplete (wie VisualStudio) nur "" drücken muss und schon werden alle aufgelistet :slight_smile: