Arduino UNO not triggering Canon Camera

Hey there,

I'm currently in process of building my own photobooth using this plan here: https://github.com/kitesurfer1404/photobooth/tree/master/arduino

My problem is that the camera is not triggering at all. I tried a Canon EOS 1300D and a EOS R6, both with the 2.5 mm TRS plug for the external trigger.

My circuit diagram looks like this here:

Triggering the camera then is done with the arduino like this:

int pin_focus = 15;   // camera: focus (using analog pin A1 as digital output)
int pin_shutter = 16; // camera: shutter (using analog pin A2 as digital output)


  digitalWrite(pin_focus, HIGH);
  delay(1000);

  digitalWrite(pin_shutter, HIGH);
  delay(400);

  digitalWrite(pin_focus, LOW);
  digitalWrite(pin_shutter, LOW);

Can anybody help me to get the camera working.
Thanks in advance

Harrinfinity

Hello,

I guess the posted section is not your whole code.
Did you set pin_focus and pin_shutter pins to OUTPUT?

Hello amazed,

thanks for you fast reply!

No, I thought the whole code might be to much since there is a lot of stuff going on for LED etc.
Yes, the pins are set to output.

The whole code is that here (it's not my own code - just copied from github and modified slightly):

/*
  Arduino Photobooth
  Harm Aldick - 2015
  http://www.kitesurfer1404.de/tech/photobooth/en
  https://github.com/kitesurfer1404/photobooth
  FEATURES
    * 7-segment-display for countdown
    * LED-speedlights
    * Pushbutton-support
    * "breathing" pushbutton-LED
    * Standalone or remote controlled operation (USB-serial)
  NOTES
    * Pushbutton-pins are configured to use internal pullup resistors 
      of the Arduino for less external parts. If you want to use external 
      pullup resistors change INPUT_PULLUP to INPUT in setup().
    * Set your camera to continuous focus for best results.
    * Use exposure compensation to compensate the dimmed focusing light. 
      Values arround -1 EV work best for me in low light situations.
    * You might also need to adjust values in takePhoto() to your needs.
      Brightness and delays might be different with different LED-bulbs.
    * Serial speed is 9600 Baud. See processCommand() for a complete 
      list of supported commands.
    * There is support for multiple pushbuttons - although only one is used
      by now. When connecting to a Raspberry Pi a second pushbutton might be
      used to shut the Pi down due to its lack of a power-down-button. 
    * analogWrite() works only on Pins 3, 5, 6, 9, 10, 11 - that's why the LED-spots
      are connected to pins 10, 11, 5, 6 so we can get dimmed focusing light.
    * Make sure to connect all pushbutton LEDs to PWM outputs so the breathing
      will work.
    * Read the datasheet of your 7-segment-display for pin-layout. 
      Connect this way:
    
       Segment     Pin (Arduino)
          A         2
          B         3
          C         4
          D         7
          E         8
          F        12
          G        13
      Use darlington array and and current limiting resistors as appropriate.
    * See repository for example circuit.
    
    * This software is free and provided "as is" - but I appreciate a donation when
      you make money off it (e.g. as a commercial photographer).
  LICENSE
  
  The MIT License (MIT)
  Copyright (c) 2015  Harm Aldick 
  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.
  CHANGELOG
  2016-01-16   Initial beta release
*/


/* This is where you might define different IO-pins */

/*int segment_pins[] = { 2, 3, 4, 7, 8, 12, 13 }; // pins segments A-G of the display are connected to*/
int segment_pins[] = { 2, 3, 4, 7, 8, 12, 13 }; // pins segments A-G of the display are connected to
int spot_pins[] = { 10, 11, 5, 6 };             // pins the spot-lights are connected to, use PWM-pins here

int pin_focus = 15;   // camera: focus (using analog pin A1 as digital output)
int pin_shutter = 16; // camera: shutter (using analog pin A2 as digital output)

int pushbutton_leds[] = { 9 };  // pin(s) on which the LED(s) of the pushbutton-switch(es) is/are connected to. Use PWM-pins here.
int pushbutton_pins[] = { 14 }; // pin(s) on which the pushbutton(s) is/are connected to. Using analog pin A0 as digital input
int lastButtonState[] = { 1 };  // saving the last state(s) of the button(s)


/* Some magic configuration happening below. */

byte segment_digits[10][7] = { // segments to light up on the corresponding index
  { 1,1,1,1,1,1,0 },    // 0
  { 0,1,1,0,0,0,0 },    // 1
  { 1,1,0,1,1,0,1 },    // 2
  { 1,1,1,1,0,0,1 },    // 3
  { 0,1,1,0,0,1,1 },    // 4
  { 1,0,1,1,0,1,1 },    // 5
  { 1,0,1,1,1,1,1 },    // 6
  { 1,1,1,0,0,0,0 },    // 7 
  { 1,1,1,1,1,1,1 },    // 8
  { 1,1,1,1,0,1,1 }     // 9
};

int breath_delay_steps[] =       {   7,   9,  13, 15, 16, 17, 18, 930, 19, 18, 15, 13,   9,   7,   4,   5 }; // magic numbers for breathing LED
int breath_brightness_steps[] =  { 150, 125, 100, 75, 50, 25, 16,  15, 16, 25, 50, 75, 100, 125, 150, 220 }; // even more magic numbers!

// initial/default values for breathing LED
#define breath_initial_brightness 15
#define breath_initial_direction 1
#define breath_initial_index 8
#define breath_initial_delay 1

int breath_brightness; // initial brightness of breathing LED
int breath_direction;  // increase brightness
int breath_index;      // start at index 8 of our magic numbers
int breath_delay;      // no delay at startup, load values imidiately
boolean breathing_enabled = true;  // enables/disables breathing LED at all.

String inputCommand = "";         // a string to hold incoming data from serial
boolean commandComplete = false;  // whether the command string is complete

boolean mode_auto = true; // default is running in standalone-mode



// The setup function runs once when you press reset or power the board.
void setup() {
  // Set all 7-segment-pins as output and turn LEDs off
  for(int i = 0; i < sizeof(segment_pins)/sizeof(int); i++) {
    pinMode(segment_pins[i], OUTPUT);
    digitalWrite(segment_pins[i], LOW);
  }
  
  // Turn all spots off.
  for(int i = 0; i < sizeof(spot_pins)/sizeof(int); i++) {
    digitalWrite(spot_pins[i], 0);
  }
  
  // Set all pushbutton-LED-pins as output and turn LEDs off
  for(int i = 0; i < sizeof(pushbutton_leds)/sizeof(int); i++) {
    pinMode(pushbutton_leds[i], OUTPUT);
    digitalWrite(pushbutton_leds[i], LOW);
  }
  
  // Set all pushbutton-pins as input and enable pullup resistor
  for(int i = 0; i < sizeof(pushbutton_pins)/sizeof(int); i++) {
    pinMode(pushbutton_pins[i], INPUT_PULLUP); // change INPUT_PULLUP to INPUT when there is an external pullup-resistor attached
  }
  
  // setup focus and shutter pins
  pinMode(pin_focus, OUTPUT);
  digitalWrite(pin_focus, LOW);
  pinMode(pin_shutter, OUTPUT);
  digitalWrite(pin_shutter, LOW);
  
  
  Serial.begin(9600); // initialize serial

  inputCommand.reserve(100); // reserve 100 bytes for the inputCommand

  breathing_reset(); // reset breathing LEDs
  
  Serial.println("ready"); // we're ready to rock!
}


/* turns all breathing LEDs gently on and resets everything for restart breathing */
void breathing_reset() {
  for(int i = 0; i <= 15; i++) {
    for(int p = 0; p < sizeof(pushbutton_leds)/sizeof(int); p++) {
      analogWrite(pushbutton_leds[p], i);
    }
    delay(10);
  }

  breathing_enabled = true;
  breath_brightness = breath_initial_brightness;
  breath_direction = breath_initial_direction;
  breath_index = breath_initial_index;
  breath_delay = breath_initial_delay;
}


/* turns all breathing LEDs off and disables breathing at all */
void breathing_stop() {
  for(int i = 0; i < sizeof(pushbutton_leds)/sizeof(int); i++) {
    analogWrite(pushbutton_leds[i], 0);
  }
  breathing_enabled = false;
}


/* does one step in "breathing", so we don't block anything else too long. */
void breathing_do_step() {
  if(!breathing_enabled) {
    return;  // nothing to do if disabled
  }
  
  breath_delay--;
  
  // update brightness and delays when waited long enough
  if(breath_delay == 0) {
    // increase or decrese brightness
    breath_brightness = breath_brightness + breath_direction;

    // change direction when LED is fully lit or very dimm
    if(breath_brightness == 255 || breath_brightness == 15) {
      breath_direction *= -1; 
    }
  
    // update index of current delay when target brightness is reached
    if(breath_brightness == breath_brightness_steps[breath_index]) {
      breath_index++;
      
      // start over when the end is reached
      if(breath_index == sizeof(breath_brightness_steps)/sizeof(int)) {
        breath_index = 0;
      }
    }
 
    // get new delay
    breath_delay = breath_delay_steps[breath_index];
  
    // set new brightness to all pushbutton leds
    for(int i = 0; i < sizeof(pushbutton_leds)/sizeof(int); i++) {
      analogWrite(pushbutton_leds[i], breath_brightness);
    }

  } else {
    delay(1); // if we have still some rounds to go, wait 1ms and return
  }
}


/* flashes the 7-segment-display in a fancy way */
void animation_one(int wait) {
  for (int i = 0; i < sizeof(segment_pins)/sizeof(int); i++) {
    digitalWrite(segment_pins[i], LOW);
  }
  
  for(int n = 0; n < 5; n++) {
    for (int i = 0; i < 6; i++) {
      digitalWrite(segment_pins[i], HIGH);
      delay(wait);
      digitalWrite(segment_pins[i], LOW);
    }
  }
}


/* flashes the 7-segment-display in another fancy way */
void animation_two(int wait) {
  int animation[] = { 1, 2, 7, 5, 4, 3, 7, 6 };
  
  for (int i = 0; i < sizeof(segment_pins)/sizeof(int); i++) {
    digitalWrite(segment_pins[i], LOW);
  }
  
  for(int n = 0; n < 5; n++) {
    for(int i = 0; i < 8; i++) {
      int segment = animation[i] - 1;
      digitalWrite(segment_pins[segment], HIGH);
      delay(wait);
      digitalWrite(segment_pins[segment], LOW);
    }
  }
}


/* flashes the spots in a fancy way */
void animation_spots(int wait) {
  for (int i = 0; i < sizeof(spot_pins)/sizeof(int); i++) {
    spot_off(i);
  }
  
  for (int i = 0; i < sizeof(spot_pins)/sizeof(int); i++) {
    spot_on(i);
    delay(wait);
    spot_off(i);
  }    
}


/* turns a single spot on */
void spot_on(int i) {
  analogWrite(spot_pins[i], 255);
}


/* turns a single spot off */
void spot_off(int i) {
  analogWrite(spot_pins[i], 0);
}


/* turns all spots on ("speedlight") */
void spots_on() {
  for (int i = 0; i < sizeof(spot_pins)/sizeof(int); i++) {
    spot_on(i);
  }
}


/* turns all spots off */
void spots_off() {
  for (int i = 0; i < sizeof(spot_pins)/sizeof(int); i++) {
    spot_off(i);
  }
}


/* turns all spots on (dimmed) for fucusing the camera in low light */
void spots_dimm(int value) {
  for (int i = 0; i < sizeof(spot_pins)/sizeof(int); i++) {
    analogWrite(spot_pins[i], value);
  }
}


/* displays a number on the 7-segment-display */
void displayNumber(int n) {
  for (int i = 0; i < sizeof(segment_pins)/sizeof(int); i++) {
    digitalWrite(segment_pins[i], segment_digits[n][i]);
  }
}


/* turns the 7-segment-display off */
void display_off() {
  for (int i = 0; i < sizeof(segment_pins)/sizeof(int); i++) {
    digitalWrite(segment_pins[i], LOW);
  }
}


/* turns every light off */
void clearAll() {
  spots_off();
  display_off();
  breathing_stop();
}


/* starts countdown and focusing, than takes picture */
void takePhoto() {

  Serial.println("Taking photo.");

  spots_dimm(25);
  digitalWrite(pin_focus, HIGH);

  animation_one(50);

  displayNumber(5);
  delay(1000);
  displayNumber(4);
  delay(1000);
  displayNumber(3);
  delay(1000);
  displayNumber(2);
  delay(1000);
  displayNumber(1);
  delay(1000);
  
  display_off();

  //spots_on();
  spots_dimm(100);
  delay(75);
  digitalWrite(pin_shutter, HIGH);

  
  delay(400);
  
  clearAll();

  digitalWrite(pin_focus, LOW);
  digitalWrite(pin_shutter, LOW);
  
  Serial.println("Photo taken.");
  
}


/* checks received command and calls corresponding function */
void processCommand(String cmd) {
  if(cmd == "1") displayNumber(1);
  if(cmd == "2") displayNumber(2);
  if(cmd == "3") displayNumber(3);
  if(cmd == "4") displayNumber(4);
  if(cmd == "5") displayNumber(5);
  if(cmd == "6") displayNumber(6);
  if(cmd == "7") displayNumber(7);
  if(cmd == "8") displayNumber(8);
  if(cmd == "9") displayNumber(9);
  if(cmd == "0") displayNumber(0);
  
  if(cmd == "display off") display_off();

  if(cmd == "spots on") spots_on();
  if(cmd == "spots off") spots_off();
  if(cmd == "spots dimm") spots_dimm(1);
  
  if(cmd == "S1 on") spot_on(0);
  if(cmd == "S1 off") spot_off(0);
  if(cmd == "S2 on") spot_on(1);
  if(cmd == "S2 off") spot_off(1);
  if(cmd == "S3 on") spot_on(2);
  if(cmd == "S3 off") spot_off(2);
  if(cmd == "S4 on") spot_on(3);
  if(cmd == "S4 off") spot_off(3);  
  
  if(cmd == "animation 1") animation_one(50);
  if(cmd == "animation 2") animation_two(50);
  if(cmd == "animation spots") animation_spots(100);
  
  if(cmd == "clear") clearAll();
 
  if(cmd == "mode auto") mode_auto = true;
  if(cmd == "mode manual") mode_auto = false;
  
  if(cmd == "take photo") takePhoto();
}


/* reads new input from serial to commandstring. Command is complete on \n */
void serialEvent() {
  while(Serial.available()) {
    char inChar = (char)Serial.read(); 
    if(inChar == '\n') {
      commandComplete = true;
    } else {
      inputCommand += inChar; 
    }
  }
}

// This loop function runs over and over again. Forever. Poor little thing.
void loop() {

  breathing_do_step(); // do one step in "breathing"

  // check all pushbuttons for changes
  for(int i = 0; i < sizeof(pushbutton_pins)/sizeof(int); i++) {
    if(digitalRead(pushbutton_pins[i]) == LOW) {  // if button is pressed
      if (lastButtonState[i] == HIGH) {             // and was not pressed before
        lastButtonState[i] = LOW;                     // save current state (pressed)
        if(mode_auto) {                               // in standalone-mode...
          inputCommand = "take photo";                  // set command
          commandComplete = true;
        } else {                                      // in remote-controlled mode...
          Serial.print("P");                            // notify computer which button was pressed
          Serial.println(i);
        }
      }
      delay(250);                                  // poor mans debouncing
    } else {                                     // if button is not pressed
      lastButtonState[i] = HIGH;                   // save state (released)
    }
  }


  if(commandComplete) {
    breathing_stop();             // stop breathing (turn LED off)
    processCommand(inputCommand); // process command
    breathing_reset();            // enable breathing again

    inputCommand = "";            // reset the commandstring
    commandComplete = false;      // reset command complete
    
    Serial.println("ready");      // notify computer
  }
}

I guess we can only forlornly hope that the eventual results will be in better focus than the diagramme you posted above..

I'm not a trained electrician, so obviously it is not accurate as per ISO whatever ... at least it works for me to keep track of which pin I connected to where.

But I am always willing to learn new things.
So instead of just telling me that my diagramm is shit, let me know whats the problem so I can improve it :wink:

1 Like

While still experimenting I found out how the remote input of my camera works.

As soon as the shutter pin is connected to GND of the TRS plug the camera shutter is triggered. Same for focus.

So what I need to do with the arduino is to short circuit those two pins (I'm not sure if this is the proper word - but hopefully you know what I mean). I also understood that the octos are in the circuit to split the shutter from the focus signal.

But how can I now do this?

I'm sure you mean to say the focus pin engages autofocus.

Some work:

Temporarily replace the optos on the shutter pin and the focus pin outputs with LEDs and appropriate series current limiting resistors (1K is fine for modern LEDs).

Cconfirm that you are still getting the correct sequence of events when a picture is invoked.

More work, and maybe above your pay grade:

Reconnect the optos, but instead of feeding the TRS, connect to the each opto output an LED and series current limiting resistor connected to 5 volts.

Confirm that the event sequence is being transferred through the optos.

Third test, you may already have, use switches or jumpers and confirm that shirting to ground the focus, and then the shutter takes a picture.

Having passed all those experiments, it should work end to end as designed.

After a certain amount of failing at this approach, it seems that small signal relays would definitely work instead of using the optos.

I'll look later when I am in the lab and see if you need anyone to draw the schematic of how my various experiments and the work-around woukd be wired.

HTH

a7

What is connected to A3?

A3 is not referred to in the code, as far as I can see.

It would then be an input, and the curious fact that it is connected to ground is curious.

@harrinfinity I know you didn't write the code, but this

int pin_focus = 15;      // camera: focus (using analog pin A1 as digital output)
int pin_shutter = 16;    // camera: shutter (using analog pin A2 as digital output)

Slows down people of medium expertise. There is no need to use those numbers just because the link is being used for digital signals.

This

const int pin_focus = A1;      // camera: focus (using analog pin A1 as digital output)
const int pin_shutter = A2;    // camera: shutter (using analog pin A2 as digital output)

would not slow anyone down. I've added const as these are numbers that should not change during program execution. So the compiler can catch some mistakes stuff.

a7

Hi alto777

Of course, the focus pin engages the autofocus and not the shutter.

But what I actually meant was (maybe this is obvious for you guys, but for me it was new):
I fought, that for triggering focus or shutter, the arduino has to apply voltage to the camera TRS pins. But that is not the case.

Instead the camera provides roundabout 3 V on the TRS focus and shutter pin itself. To trigger one of the functions you only have to connect one of the camera pins from from the TRS plug with the GND pin of the TRS plug.

I guess this (connecting focus/shutter pin to GND) is what is done by the optos.

I will do this for trouble shooting. Just need to order some LEDs, so It will take a few days until I can start with the testing

I will try this as well as soon as I have got LEDs

This is what I already have done.
Shorting the TRS pins does trigger the camera as desired.

would have probably been the easier solution with relays. Now I already have the optos so I will try to get them work.
But I can keep it in mind as backup if everything else fails ...

Thank you for your help!

have a good day
Harrinfinity

good to know. I will definitely change it in the code!
Thanks

I don't understand what's not working. Is pin 5 of the 4N35 not going low relative to the camera's ground when you try to take a picture?

Short Update: Even I had no LEDs to test the board as described from alto777 I did get much futher in the issue investigating.

I used my multimeter to check the current step by step and I could find out that sometimes the optos get the required input signal to work properly (and in this case the camera was also triggering) and sometimes they do not.
But I could also find out that the arduino IS giving the proper output signal every time.

This means the signal gets lost somewhere between the arduino and the optos - but only in some cases.
So the board is definitely not working well. Could be a cold soldering joint... But unfortunately I was not able to find the error causing soldering joint.

Long story short: I will rebuild the circuit board newly and then try again.

What is the value of the resistor connected to pin 1 of the 4N35?

it is a 1k Ohm resistor

To high
Use 470 or 390 ohms

as per datasheet the 4N35 need 1 to 1.3 V input signal.
I measured with the multimeter 1.1 - 1.15 V coming from the arduino after the 1k Resistor. Should I try it with less resistant anyway?

Yes.
It's not the voltage but the current that is important.
1K is limiting the current too much and the opto may not fully turn on

1 Like

You can try smaller resistors.

But please tell us you are testing this with a small sketch meant just to exercise the Arduino-opto-camera link.

What you describe sounds like it could well be a software problem. If you aren't 100 pernect sure the code is working, it is wrong to focus on only the harwdware.

So a small sketch, simple as can be. If you aren't using one, say. I or someone can write that in no time.

I'd have a sketch like that handy even if the hardware worked with, say, new resistors. Mostly because I would have had one in the first place, to prove outside the context of 100s of lines of code, even code I did write myself, that I had my wiring and other details correct.

a7

Or I can waste use the time I have waiting here. If this moves too fast for any other testing, just make the delays longer.

const int pin_focus = A1;      // camera: focus (using analog pin A1 as digital output)
const int pin_shutter = A2;    // camera: shutter (using analog pin A2 as digital output)

const int LED = LED_BUILTIN;

void setup() {
  Serial.begin(115200);
  Serial.println("focus shutter test world!\n");

  pinMode(pin_focus, OUTPUT);
  pinMode(pin_shutter, OUTPUT);

  pinMode(LED, OUTPUT);
}

void loop() {

  digitalWrite(LED, HIGH);
  Serial.println("focus");
  digitalWrite(pin_focus, HIGH);

  delay(300);

  Serial.println("    shutter");
  digitalWrite(pin_shutter, HIGH);

  Serial.println("              picture!");

  delay(777);
  Serial.println("rinsing.");

  digitalWrite(pin_shutter, LOW);
  digitalWrite(pin_focus, LOW);
  digitalWrite(LED, LOW);

  delay(777);
  Serial.println("repeat...");
}

HTH

a7