Contrôler son Appareil photo (Canon) et un Flash Cobra avec Arduino

Salut à tous

Petit partage pour piloter un appareil photo et des flash Cobra!

J'ai un Canon 5D Mark III et des flashs Cobra "Speedlight 600 EX-RT" donc ce que je décris ci dessous est testé sur ma configuration uniquement et même si je pense que c'est assez largement applicable aux autres reflex il faudra faire vos recherches. Vous prenez vos responsabilité en bidouillant votre appareil... (Attention certains anciens flash sont dits à haute tension et ne se pilotent sans doute pas ainsi).

Ce que je souhaitais effectuer depuis mon Arduino:

  • contrôler la mise au point (appui à mi Course sur le bouton)
  • Déclencher la prise de vue (appui à fond sur le bouton)
  • déclencher un coup de flash

l'idée derrière est bien sûr de coupler cela à un capteur adéquat au sujet que vous voulez capturer (mouvement, bruit, chaleur, luminosité, timing, etc). et déclencher une prise de vue sans avoir à rester derrière l'appareil.

De nuit quand tout est sombre, il est aussi possible de se mettre en pause B et d'ouvrir l'obturateur en attendant un événement. Quand il arrive vous donnez un coup de flash et refermez ensuite l'obturateur. ça vous permet de figer le moment et vous gagnez bien sûr le temps d'appui et d'ouverture et le temps d'exposition est hyper bref — la durée de l'éclair lumineux du flash — donc vous pouvez figer ainsi un mouvement. C'est une technique utilisée pour faire les photos de gouttes d'eau qui s'entrechoquent par exemple.


ETAPE 1: CONTROLE DU FLASH
Pour pouvoir piloter mon flash, j'ai regardé un peu quels étaient les contacteurs électriques sur le sabot et je me suis rendu compte qu'en faisant court-circuit entre un plot et le sabot ça déclenchait mon flash.

Le sabot semble être Commun et le plot le déclencheur lorsqu'il rejoint ce Commun.

D'un point de vue technique donc il suffit de pouvoir fermer un circuit pour déclencher le flash. ça ne semble pas trop compliqué.

Cependant, je ne me vois pas souder un truc sur le sabot (c'est pas donné ces flashs !!), donc il faut trouver un autre endroit où se connecter.

Le protocole de déclenchement Radio est propriétaire et celui par IR assez compliqué donc je n'ai pas exploré cette voie.

Mais mon flash dispose aussi sur le côté d'une synchro-déclenchement par fil quand on veut déporter son flash. C'est un petit contacteur circulaire avec un plot au milieu sur lequel on peut visser un câble relié à l'appareil photo.


et là encore, en fermant le circuit entre le plot central et le bord (sans doute le Commun) du connecteur, ça déclenche le flash.

Certains flash n'ont pas ce connecteur mais il existe des petits sabots offrant la même prise circulaire.
flash-3.png
ça me semble donc un bon plan, il suffit de trouver un petit câble adapté à cette prise ronde.

Une Recherche rapide sur eBay avec comme vocabulaire "Flash Sync Cable Screw" me permet de trouver pour moins de deux euros un "Flash PC Sync Cable Cord with Screw Lock". il y en a avec deux connecteurs à vis à chaque extrémité et d'autres avec un Jack d'un côté et le connecteur à vis de l'autre côté.


J'en avais acheté plusieurs de différents types et donc sans une seconde d'hésitation j'ai pris la pince coupante, enlevé le jack, dénudé les deux fils, et testé la continuité entre les fils et le connecteur.

Sans surprise le fil rouge va au picot central et le fil noir va au bord du connecteur. je m'empresse donc de visser le connecteur sur mon flash, je l'allume et lui laisse le temps de se charger et magique, quand je mets les deux fils dénudés en court-circuit, mon flash se déclenche.

Note: j'ai effectué quelques recherches sur internet avant, essayé avec une diode et résistance et connecté aussi mon appareil photo sur mon oscilloscope pour voir ce qu'il se passait sur cette prise avant de simplement faire un court circuit entre les fils juste au cas où un vrai courant important allait circuler mais je n'ai rien vu de tel. Je n'ai aucune garantie cependant que ce soit recommandé, donc à vos risques et périls :slight_smile:

Pour la petite histoire, comme j'avais plusieurs fils, au final c'est celui de 2m avec deux connecteurs ronds qui est le plus pratique, il permet en coupant le câble au milieu d'obtenir deux prises (j'ai plusieurs flashs).

J'ai donc soudé un header avec un peu de gaine thermique au bout de ce câble et j'étais paré.

ETAPE 2: CONTROLE DE LA PRISE DE VUE

Deuxième exploration, comment faire la mise au point et déclencher la prise de vue ? On pourrait bricoler avec un servo un mouvement qui appuie sur le bouton de l'appareil mais ce serait compliqué à faire tenir en place et ça fait du bruit qui pourrait faire fuir le sujet de votre photo avant le déclenchement...

Tous les reflex que je connais disposent d'une prise de télécommande à distance. En appuyant sur le bouton de la télécommande au lieu de l'appareil, on évite de faire trembler l'appareil pendant l'exposition et donc le flou de bougé. Certaines télécommande ont bien d'autres fonctions (time lapse, etc).

je me suis donc penché sur le connecteur de télécommande de mon appareil photo.


il présente une forme arrondie avec encoche pour détrompeur et 3 petits picots à l'intérieur. Il s'agit d'une prise dite N3 chez Canon.

J'ai donc cherché sur Ebay une télécommande la plus simple possible pour N3. en tapant "Câble Déclenchement à Distance Pour Canon N3" ou en anglais "Canon N3 Camera Remote Shutter Release Cable Cord" et je suis tombé sur ce produit à 2,68€ livraison comprise par exemple.

J'en ai vu quelques autre modèles et j'en ai acheté trois différentes dans les même prix, juste au cas où les choses tournaient mal.

J'ouvre la télécommande (deux vis au dos du boîtier) et l'intérieur du boîtier est extrêmement simple.
photo-2.png
Je m'attendais à un peu d'électronique mais rien de tout cela.



Il n'y a que trois languettes métalliques montées les une après les autres sur des picots de différentes hauteur et lorsqu'on appuie sur le bouton un à mi course on fait contact entre les deux premières languettes et quand on appuie à fond, les 3 languettes se touchent.

Les languettes métalliques sont assez rigides pour faire ressort, donc c'est tout ce qu'il y a dans la télécommande (outre une petite glissière moulée en plastique qui permet mécaniquement de bloquer les 3 languettes en positions appuyées quand on veut faire une pause longue).

Il part un fil de couleur depuis chaque languette (rouge, vert, bleu). Au bout du fil on retrouve le contacteur spécifique au format N3 avec ses 3 broches femelle et un simple test de continuité me permet d'identifier que câble va où.
photo-5.png
Vu le montage physique, il est évident que ça fonctionne par "court-circuit", comme le flash donc.

=> Court-circuiter la broche de mise au point sur la broche commune équivaut à enfoncer le déclencheur de l'appareil photo à mi-course et entraînera la mise au point de l'appareil photo et Court-circuiter la broche de l'obturateur sur la broche de mise à la terre revient à enfoncer complètement le déclencheur et entraînera la prise de photo de l'appareil photo.

La languette du milieu (fil bleu) doit être le "commun"

J'ai donc démonté les languettes, coupé les fils, soudé un header de 3 pins au bout
photo-7.png
et j'avais un câble de contrôle!

Un test rapide en court-circuitant à la main les fils déclenche bien la mise au point ou l'obturateur comme attendu.

ETAPE 3: GENERATION DE SIGNAUX DE COMMANDE

Bon c'est bien beau d'avoir des câbles mais maintenant il va falloir faire des courts circuits si on veut piloter cela.

Souhaitant avoir une isolation entre mon système Arduino et l'appareil photo (on ne sait jamais) deux solutions me sont venus rapidement à l'esprit.

  • approche avec un Relais Reed
  • approche avec un optocoupleur

Un relais Reed est un petit composant à 4 (parfois doublées) pattes qui est un interrupteur piloté. J'ai des mon tiroir par exemple des "SIP-1A05 DIP4 reed relais 5 V Tension" (5€ les 10 environ quand je les avais achetés). Ils ont un fonctionnement tout simple: les pins 1 et 4 aux extrémités du composant sont connectées à un petit fil métallique mobile dans le composant - qui ne se touchent pas normalement -> Le circuit entre 1 et 4 est donc ouvert par défaut.

Les pin 2 et 3 sont les extrémités d'une bobine. Quand on fait passer un courant dans la bobine, les 2 fils métalliques sont attirés l'un vers l'autre et font contact, le circuit se ferme.

Comme il y a une bobine et un courant à contrôler, on va mettre une diode de roue libre et une résistance de limitation de courant entre les pin 2 et 3.
reed-1.png
En mettant la patte 3 sur une pin de notre arduino, en passant à HIGH on ferme donc le circuit et on obtient notre effet souhaité. C'est pas mal, c'est un petit composant qui supporte pas mal de courant mais il y a une pièce en mouvement et donc ce n'est pas ce qui se fait de plus rapide et il peut y avoir des rebonds --> Je ne retiendrais donc pas cette solution. (il existe des relais reed avec la diode et résistance intégrées il me semble pour simplifier le câblage)

Un Optocoupleur (ou photocoupleur) est aussi un petit circuit intégré capable de transmettre un signal d'un circuit électrique à un autre, sans qu'il y ait de contact galvanique entre eux. Il est formé d'une LED infrarouge et d'un phototransistor ou d'une photodiode. Lorsqu'on allume la LED, le phototransistor devient passant et établi la connexion. L'optocoupleur assure donc une isolation électrique entre les deux parties du système.

C'est tellement utilisé que ça ne coûte pas grand chose, j'ai dans mes tiroirs quelques 4N35, ou PC817 par exemple.

Avec un 4N35 On pourrait donc faire le montage suivant:


On part d'une pin de son arduino, on passe par une Résistance de limitation de courant côté LED (la cathode va au GND Arduino) et on accroche les deux fils à court-circuiter sur le collecteur et émetteur (on laisse la base en l'air) de l'autre côté. Lorsque l'on active la Pin sur l'arduino, on ferme donc le circuit de l'autre côté.

C'est très simple, il n'y a qu'une résistance à rajouter, c'est donc avec l'optocoupleur que je vais partir.


Cela dit, comme j'aurais à connecter le flash et les deux commandes de l'appareil photo, il m'en faudra trois.

Il existe des tas de sortes d'optocoupleurs dont certains à 2 ou 4 connexions.

Je dispose de quelques A847 dans mon tiroir (moins de 0,5€ pièce en Asie) qui sont à base de phototransistor.
A847.png
Ils ont 4 optocoupleurs donc et le composant a 8 pattes de chaque côté: de 1 à 8 ce sont les pattes des LEDs et de 9 à 16 les pattes des émetteurs et collecteurs. Par exemple 1 est l'anode de la première LED, 2 la Cathode et en regard sur 15 et 16 vont se trouver les pins du phototransistor associé. (cf la datassheet).

Pour un optocoupleur le câblage se ferait ainsi

Voilà - comme cela nous sommes parés, il ne reste plus qu'à connecter les câbles fabriqués sur ce composant d'un côté et à une pin de commande Arduino de l'autre, quelques lignes de code et nous devrions pouvoir contrôler l'appareil photo et le flash.

Donc je câble mon petit circuit sur ma breadboard:

(je n'étais pas sûr exactement de la spec de mon A847 pour les LEDs, j'ai mis des R de 220Ω et ça fonctionne correctement et je suis sûr que le courant tiré depuis mon arduino reste dans des limites correctes) mais faut pas trop limiter le courant car moins la LED sera alimentée moins la détection fonctionnera ou sera lente. si vous avez la spec de votre optocoupleur, mettez une résistance adaptée, quitte à avoir un étage de pilotage du courant nécessaire car il ne faut pas dépasser 20/25mA sur vos pins.

et je choisis les pins suivantes pour le contrôle (cf le code):

  • la commande Flash = pin 8
  • la commande Obturateur = pin 9
  • la commande Focus = pin 10

En tâtonnant un peu j'a vu qu'il faut quand même un délai minimum pour que les commandes soient prises en compte, faire le court circuit que quelques microsecondes ne suffit pas.

Donner un coup de flash revient donc à allumer pendant un certain temps (suffisant pour que le flash détecte le front) et on peut faire cette fonction

void flash()
{
  digitalWrite(flashPin, HIGH);
  delay(flashTriggerDelay);
  digitalWrite(flashPin, LOW);
}

Je prévois aussi une fonction qui permet de tenir le bouton à mi course pendant un certain temps

void focus(unsigned long t=0)
{
  digitalWrite(focusPin, HIGH);
  delay(t > focusTriggerDelay ? t : focusTriggerDelay); 
  digitalWrite(focusPin, LOW);
}

Cette fonction a donc un paramètre qui est le temps d'appui mais dans le code je teste si ce temps d'appui est inférieur au seuil approximatif (250ms par exemple pour le focus) alors j'attends le temps minimum requis.

prendre une photo est un peu similaire:

void photo(unsigned long t = 0)
{
  digitalWrite(focusPin, HIGH);
  digitalWrite(shutterPin, HIGH);
  delay(t > shutterMinTriggerDelay ? t : shutterMinTriggerDelay);
  digitalWrite(shutterPin, LOW);
  digitalWrite(focusPin, LOW);
}

On fait le court circuit sur les 2 fils de focus et obturateur, on attend un certain temps (dont un temps minimum) avec le bouton appuyé puis on relâche.

Si votre appareil est en automatique, ça simule simplement l'appui direct sur le bouton, mais si vous avez réglé votre appareil en Pause B, la durée d'appui est importante puisque c'est elle qui va décider de la longueur de l'exposition --> on peut faire de la pause longue !! :slight_smile:

enfin prendre une photo avec flash va prendre le même principe:

void photoWithFlash(unsigned long t = 0)
{
  unsigned long demiT = t / 2;

  digitalWrite(focusPin, HIGH);
  digitalWrite(shutterPin, HIGH);
  if (demiT > shutterMinTriggerDelay) delay(demiT);
  else delay(shutterMinTriggerDelay);
  digitalWrite(flashPin, HIGH);
  delay(flashTriggerDelay);
  if (demiT > shutterMinTriggerDelay + flashTriggerDelay) delay(demiT - shutterMinTriggerDelay - flashTriggerDelay);
  digitalWrite(flashPin, LOW);
  digitalWrite(shutterPin, LOW);
  digitalWrite(focusPin, LOW);
}

la fonction prend un délai d'attente et on donne le coup de flash (arbitrairement) au milieu de ce délai d'attente s'il est suffisant sinon tout s'enchaine avec les délais min.

C'est intéressant si on est en pause B par exemple, puisqu'on peut ouvrir, attendre un peu que les vibrations dues au mouvement du miroir s'arrête, puis déclencher le flash pour figer la scène (et attendre un peu ensuite encore).

voilà on a nos fonctions, reste plus qu'à pouvoir les appeler.

Pour un programme simple, je souhaite pouvoir taper une commande à travers le moniteur Série qui sera ensuite exécutée. J''utilise la technique expliquée dans mon tuto pour écouter le port série (à retrouver ici)

Ma liste de commandes:

C pour un Coup de flash
M pour l'appui sur la Mise au point
P pour Prendre une photo
F pour Prendre une photo avec coup de Flash

le coup de flash est toujours instantané, mais pour les autre commandes comme on l'a vu ci dessus, je souhaite pouvoir dire aussi combien de millisecondes je tiens le bouton (virtuel) appuyé.

Donc je souhaite pouvoir rentrer M1000 pour dire "tenir le bouton de mise au point appuyé pour 1000ms = 1s" par exemple. si je tape juste M, j'aurais le temps mini de mise au point

De même si je dis P, ça prend la photo mais P2000 va tenir le bouton enfoncé 2 secondes. En mode auto, priorité vitesse ou diaphragme ça fait la photo (voire une rafale suivant votre réglage) et en mode Bulb (pause B) ça tient le diaphragme ouvert tout ce temps.

Le code est tout simple, on écoute le port série (115200 bauds) jusqu'à avoir reçu une commande (fin de ligne doit être réglé sur LF ('\n') ou CR+LF (le '\r' est ignoré). On analyse le premier caractère de la commande dans un switch pour appeler la bonne fonction, en passant éventuellement le chiffre qui suivant le code commande.

/* ============================================
  code is placed under the MIT license
  Copyright (c) 2020 J-M-L
  For the Arduino Forum : https://forum.arduino.cc/index.php?topic=672896.msg4530014#msg4530014

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
  ===============================================
*/

const uint8_t flashPin = 8;
const uint8_t shutterPin = 9;
const uint8_t focusPin = 10;

const uint16_t flashTriggerDelay = 1; // ms
const uint16_t focusTriggerDelay = 250; // ms
const uint16_t shutterMinTriggerDelay = 250; // ms
const uint16_t actionBsmallPause = 50; // ms

void flash()
{
  digitalWrite(flashPin, HIGH);
  delay(flashTriggerDelay);
  digitalWrite(flashPin, LOW);
}

void focus(unsigned long t=0)
{
  digitalWrite(focusPin, HIGH);
  delay(t > focusTriggerDelay ? t : focusTriggerDelay);
  digitalWrite(focusPin, LOW);
}

void photo(unsigned long t = 0)
{
  digitalWrite(focusPin, HIGH);
  digitalWrite(shutterPin, HIGH);
  delay(t > shutterMinTriggerDelay ? t : shutterMinTriggerDelay);
  digitalWrite(shutterPin, LOW);
  digitalWrite(focusPin, LOW);
}

void photoWithFlash(unsigned long t = 0)
{
  unsigned long demiT = t / 2;

  digitalWrite(focusPin, HIGH);
  digitalWrite(shutterPin, HIGH);
  if (demiT > shutterMinTriggerDelay) delay(demiT);
  else delay(shutterMinTriggerDelay);
  digitalWrite(flashPin, HIGH);
  delay(flashTriggerDelay);
  if (demiT > shutterMinTriggerDelay + flashTriggerDelay) delay(demiT - shutterMinTriggerDelay - flashTriggerDelay);
  digitalWrite(flashPin, LOW);
  digitalWrite(shutterPin, LOW);
  digitalWrite(focusPin, LOW);
}

// -------- GESTION DES COMMANDES SERIES ------------

const byte tailleMax = 10;
char messageRecu[tailleMax + 1] = ""; // +1 pour stocker un '\0' à la fin de la chaîne
byte index = 0;

boolean recevoirMessage(const char finDeChaine)
{
  boolean fin = false;

  if (Serial.available()) { // si on a au moins un charactère en attente
    int recu = Serial.read(); // -1 si erreur, sinon notre charactère
    if (recu != -1) {
      if (recu == finDeChaine) fin = true;
      else {
        if (recu != '\r') { // on ignore CR
          messageRecu[index++] = (char) recu;
          messageRecu[index] = '\0'; // on marque la fin de chaîne
          if (index >= tailleMax) index = tailleMax - 1; // évite de déborder
        }
      }
    }
  }
  return fin;
}

void toutEteint()
{
  digitalWrite(flashPin, LOW);
  digitalWrite(shutterPin, LOW);
  digitalWrite(focusPin, LOW);
}


void menuGeneral()
{
  toutEteint();
  Serial.println(F("\n(C)\t\tCoup de flash"));
  Serial.println(F("(M/Mxxx)\tMise au point (appui xxx ms)"));
  Serial.println(F("(P/Pxxx)\tPrendre une photo (appui xxx ms)"));
  Serial.println(F("(Fxxx)\t\tPrendre une photo PAUSE B avec coup de Flash au milieu du temps d'attente (appui xxx ms)"));
  Serial.print(F("Entrez une commande:"));
}

void setup()
{
  pinMode(flashPin, OUTPUT);
  pinMode(shutterPin, OUTPUT);
  pinMode(focusPin, OUTPUT);
  toutEteint();
  Serial.begin(115200);
  Serial.println(F("--- PRISE DE PHOTO ---"));
  menuGeneral();
}


void loop()
{

  if (recevoirMessage('\n')) {
    Serial.println(messageRecu);

    switch (messageRecu[0]) {
      case 'C':
        flash();
        break;

      case 'M': // expecting 'M', "Mxxxx" where xxx is the duration of the press in ms
        focus(atol(messageRecu + 1));
        break;

      case 'P': // expecting 'P', "Pxxxx" where xxx is the duration of the press in ms
        photo(atol(messageRecu + 1));
        break;

      case 'F':// expecting F or Fxxxx where xxx is the duration of the press in ms
        photoWithFlash(atol(messageRecu + 1));
        break;

      default: break; // on ne fait rien
    }
    // On re-initalise notre buffer
    index = 0;
    messageRecu[0] = '\0';
    menuGeneral();
  }
}

Voilà. Vous avez la base pour pouvoir bosser. Maintenant au lieu de lire le port Série, il suffit de lire un capteur de détection et appeler la fonction que vous voulez pour que la photo se déclenche

un petit exemple (en Islande) sur mouvement (photos recadrées)

amusez vous bien !

Magnifique ce macareux!

Et au passage: super tuto comme d’hab, bien documenté. C’est toujours du boulot qualité, merci JML.

Et ça servira à ceux qui cherchent à émuler des contacts sec.