Table des matières

Fabriquer une télécommande Arduino pour votre appareil photo

Tout ces documents sont sous licence CC BY-NC-SA : Cette licence permet aux autres de remixer, arranger, et adapter votre œuvre à des fins non commerciales tant qu'on vous crédite en citant votre nom et que les nouvelles œuvres sont diffusées selon les mêmes conditions.

Ce projet a été initié par Victor Lamoine

Objectif

Nous allons créer une télécommande pour appareil photo contrôlée par un Arduino. Cette télécommande permettra de faire la mise au point et de prendre une photo.

Ce tutoriel a été rédigé pour un Panasonic Lumix FZ200, il devrait marcher exactement pareil pour tout appareil photo dont la prise remote shutter est un jack à 4 contacts.

Matériel

Précautions

Description générale

Lorsque l'on appui sur le bouton de la télécommande un contact (interrupteur) se ferme et un jeu de résistance permet de déterminer si on est en focus ou shoot.

On va donc détourner une télécommande (en la gardant utilisable manuellement) pour la commander avec un Arduino. Pour remplacer l'interrupteur manuel nous allons utiliser des optocoupleurs.

Optocoupleur

Un optocoupleur est composé d'une diode et d'un photo-transistor.

C'est un interrupteur électronique qui laisse passer le courant quand il reçoit de la lumière, l'interrupteur est alors “fermé”. Lorsqu'il ne reçoit pas de lumière l’interrupteur est “ouvert” et le courant ne passe pas.

Nous utiliserons un 4N35, on trouve très facilement la datasheet sur le net

Modification de la télécommande

J'ai ouvert la télécommande :

J'ai enlevé le petit jack pour faire de la place pour les fils :

On soude 3 fils sur l’interrupteur : c'est un interrupteur deux positions, à mis-course c'est le focus, en fin de course c'est le shoot.

On referme la boite (les couleurs des fils ne correspondent pas avec la photo précédente car j'ai changé entre temps). J'ai utilisé un connecteur arraché d'un vieux PC : c'est pour ça que c'est marqué POWER LED dessus.

C'est fini pour la télécommande; il suffit de la brancher à l'appareil photo et de le démarrer. Faire toucher deux fils (essayer toutes les combinaisons) pour prendre une photo ou faire la mise au point.

Chez moi : Vert et bleu : Mise au point Vert et noir : Photo

Réalisation du montage Arduino

Réaliser le montage suivant :

Ce qui donne :

On utilise les pins 2 et 3 pour commander les optocoupleurs.

Programmation de l'Arduino

Nous allons maintenant programmer l'Arduino pour qu'il reçoive des commandes par USB, nous avons deux commandes à gérer : focus et shoot. On ajoutera une autre commande en plus shooter en rafale (on choisit alors le temps de la rafale)

int time=100; // 100 millisecondes
int incomingByte = 0;
const int opto_focus = 2; // Optocoupleur
const int opto_shoot = 3; // Optocoupleur
 
void setup() 
{
  Serial.begin(9600); // On démarre la communication (baud-rate=9600)
  pinMode(opto_focus, OUTPUT); // Les pins opto sont en sortie
  pinMode(opto_shoot, OUTPUT); // Les pins opto sont en sortie
}
 
void loop() 
{
 if (Serial.available() > 0) // Si on reçois des données alors...
 {
  incomingByte = Serial.read(); // Lecture des bytes arrivant
  
  switch (incomingByte) // Suivant ce que le message contient
  {
  case 'f': // f comme focus
      digitalWrite(opto_focus, HIGH); // Focus..
      delay(300);
      digitalWrite(opto_focus, LOW);
  break;
  
  case 's': // s comme shoot
      digitalWrite(opto_shoot, HIGH); // Shoot !!
      delay(time); // time est à 100ms par défaut, c'est comme si on appuyait sur le bouton de l'appareil 0,1 seconde
      digitalWrite(opto_shoot, LOW); // On relâche le bouton
      delay(1);
  break;
  
  default:                    // Si le message n'est ni 's' ni 'f' alors on considère que c'est le temps de rafale
    time = incomingByte*100;
  }
 }
}

Compiler le programme et transférez le sur l'Arduino. Allumer et brancher l'appareil photo à la télécommande.

Envoyez le message 's' grâce au terminal Arduino, l'appareil prend une photo !

Programme Qt

On va dans cette partition créer un programme Qt pour prendre faire la mise au point, prendre des photos et régler le temps de rafale.

Installer Qt et Qt creator :

sudo apt-get install -y qtcreator

Télécharger et installer QextSerialPort (lire le README c'est pas compliqué !) http://code.google.com/p/qextserialport/

Démarrer un projet Qt Creator (Application : Qt Gui Application)

usb_fz.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = USB_fz
TEMPLATE = app

CONFIG += extserialport

SOURCES += main.cpp\
	usb_fz.cpp

HEADERS  += usb_fz.h

FORMS    += usb_fz.ui

usb_fz.h

#ifndef USB_fz_H
#define USB_fz_H

#include <QMainWindow>
#include <QtGui>
#include <QMessageBox>
#include <qextserialport.h>

namespace Ui {
class USB_fz;
}

class USB_fz : public QMainWindow
{
    Q_OBJECT

public:
    explicit USB_fz(QWidget *parent = 0);
    void init_port(); // initialisation du port
    ~USB_fz();

public slots:
    void transmitFocus(void); // fonction d'envoi
    void transmitShoot(void);
    void transmitCmd(int cmd);

private:
    Ui::USB_fz *ui;
    QextSerialPort *port;
};

#endif // USB_fz_H

usb_fz.cpp

#include "usb_fz.h"
#include "ui_usb_fz.h"

USB_fz::USB_fz(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::USB_fz)
{
    init_port(); // initialisation du port
    ui->setupUi(this);
    connect(ui->btnFocus, SIGNAL(clicked(bool)), this, SLOT(transmitFocus(void)));
    connect(ui->btnShoot, SIGNAL(clicked(bool)), this, SLOT(transmitShoot(void)));
    connect(ui->slider, SIGNAL(sliderMoved(int)), this, SLOT(transmitCmd(int)));
    transmitCmd(1);
}

USB_fz::~USB_fz()
{
    delete ui;
}

void USB_fz::init_port(void)
{
    QString dev_port = "/dev/ttyUSB0";
    port = new QextSerialPort(dev_port); // On ouvre le port
    // "ls /dev | grep USB" Permet de donner la liste des périphériques USB

     port->open(QIODevice::ReadWrite | QIODevice::Unbuffered);
    if(!port->isOpen())
    {
	QMessageBox::warning(this, "Impossible d'ouvrir le port", dev_port);
    }

    // On parametre la liaison :
    port->setBaudRate(BAUD9600);
    port->setFlowControl(FLOW_OFF);
    port->setParity(PAR_NONE);
    port->setDataBits(DATA_8);
    port->setStopBits(STOP_1);
}

void USB_fz::transmitFocus(void)
{
    QByteArray byte; // Byte a envoyer
    byte.clear(); // On efface le contenu de byte
    byte.append('f'); // On ajoute 'f' dans byte

    if(port != NULL){ // On vérifie que le port existe toujours
	port->write(byte); // On écrit le(s) byte
	qDebug() << "Value sent: f";
	port->flush(); // On attend la fin de la transmission
    }
}

void USB_fz::transmitShoot(void)
{
    QByteArray byte;

    byte.clear();
    byte.append('s');

    if(port != NULL){
	port->write(byte);
	qDebug() << "Value sent: s";
	port->flush();
    }
}

void USB_fz::transmitCmd(int cmd)
{
    ui->lcdNumber->display(cmd*100);
    QByteArray byte;

    byte.clear();
    byte.append(cmd);

    if(port != NULL){
	port->write(byte);
	qDebug() << "Value sent:" << cmd;
	port->flush();
    }
}

usb_fz.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>USB_fz</class>
 <widget class="QMainWindow" name="USB_fz">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>254</width>
    <height>146</height>
   </rect>
  </property>
  <property name="sizePolicy">
   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
    <horstretch>0</horstretch>
    <verstretch>0</verstretch>
   </sizepolicy>
  </property>
  <property name="minimumSize">
   <size>
    <width>254</width>
    <height>146</height>
   </size>
  </property>
  <property name="maximumSize">
   <size>
    <width>254</width>
    <height>146</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>USB FZ200</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="QPushButton" name="btnFocus">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>10</y>
      <width>111</width>
      <height>51</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>14</pointsize>
     </font>
    </property>
    <property name="text">
     <string>Focus</string>
    </property>
   </widget>
   <widget class="QPushButton" name="btnShoot">
    <property name="geometry">
     <rect>
      <x>130</x>
      <y>10</y>
      <width>111</width>
      <height>51</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>14</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="text">
     <string>Shoot</string>
    </property>
   </widget>
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>80</y>
      <width>261</width>
      <height>17</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>14</pointsize>
     </font>
    </property>
    <property name="text">
     <string>Durée rafale :                    ms</string>
    </property>
   </widget>
   <widget class="QLCDNumber" name="lcdNumber">
    <property name="geometry">
     <rect>
      <x>130</x>
      <y>70</y>
      <width>81</width>
      <height>31</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>14</pointsize>
     </font>
    </property>
    <property name="segmentStyle">
     <enum>QLCDNumber::Flat</enum>
    </property>
    <property name="intValue" stdset="0">
     <number>100</number>
    </property>
   </widget>
   <widget class="QSlider" name="slider">
    <property name="geometry">
     <rect>
      <x>40</x>
      <y>110</y>
      <width>160</width>
      <height>29</height>
     </rect>
    </property>
    <property name="minimum">
     <number>1</number>
    </property>
    <property name="maximum">
     <number>20</number>
    </property>
    <property name="orientation">
     <enum>Qt::Horizontal</enum>
    </property>
   </widget>
  </widget>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

Compiler le programme en cliquant sur la flèche verte en bas à gauche. Le programme se lance, si l'Arduino est branché tout devrait marcher comme avec le terminal :-)