Modifying a library (multiCameraIRcontrol)

I am trying to modify a library that controls an IR LED to trigger a camera shutter: https://github.com/dharmapurikar/Arduino/tree/master/libraries/multiCameraIrControl. Currently you select the camera model in the header area of the sketch and that is working and I have tested with two different camera brands. The following is an example sketch showing how the camera brand and LED pin are defined:

#include <multiCameraIrControl.h>

Sony A900(13);

void setup(){
}

void loop(){
A900.shotNow();
delay(5000);
A900.shotDelayed();
delay(5000);
}

I would like modify the library so that I can select model while the program is running ( i.e. receiving a serial command) but I have no experience with how libraries actually function and how the variable like "Sony A900(13);" are defined and interact with the library. Any help would be appreciated.

Thanks,

Matt

Hello Matt,
High level concept:
Libraries are like normal code but they are located at a special location.
C:\documents<user>\Arduino\Libaries\name\src.
There you can find CPP and H. files.
CPP contains code H contains header.
Most of the code is organized as C++ object files.
You can modify this code in a standard text editor and then compile your sketch,
it will modify.
As an alternative you can move the .CPP and .H to your sketch directory, add them to your project as separate files and modify them. In those cases it is a good idea to rename or delete the code in the library section to eliminate mixups.
Best regards,
Johi.

Sony A900(13); creates an object of type Sony with a name of A900 which uses pin 13
The library header contains definitions for several classes including this one

class Sony{
public:
  Sony(int pin);
  void shotNow();
  void shotDelayed();
private:
  int _pin;
  int _freq;
};

This class has 2 functions, shotNow() and shotDelayed() which I imagine you have used or are at least aware of

In order to do what you want you would need to read user input of the class to be used and the pin to be used then declare an instance of that class to be used in the sketch. I foresee problems with the scope of where the class instance can be used due to its scope but there may be ways round this that others can suggest

The library is rather primitive. A more sophisticated implementation would have created a base class called Camera (for example). It would have virtual functions for shotNow() and shotDelayed(). Then, specific camera classes would be created by inheriting from the main Camera class. Each of these would overload those functions with the required specific implementation for that model. This would allow the user to call the functions for any camera model using a reference or pointer to the base class .... the magic of polymorphism.

Also, the library code calls pinMode() from the classes' constructors. That’s a red flag.

something like this. Note: your code will have to call begin() to make the pinMode() call happen at the proper time
.h file

/*******************************************

   Name.......:  cameraIrControl Library
   Description:  A powerful Library to control easy various cameras via IR. Please check the project page and leave a comment.
   Author.....:  Sebastian Setz
   Version....:  1.2
   Date.......:  2010-12-16
   Project....:  http://sebastian.setz.name/arduino/my-libraries/multi-camera-ir-control
   Contact....:  http://Sebastian.Setz.name
   License....:  This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
                 To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
                 Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
   Keywords...:  arduino, library, camera, ir, control, canon, nikon, olympus, minolta, sony, pentax, interval, timelapse

 ********************************************/

#ifndef multiCameraIrControl_h
#define multiCameraIrControl_h

#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

// base class for all cameras
class Camera
{
  public:
    Camera(uint8_t pin, uint8_t freq) : _pin(pin), _freq(freq) {};
    virtual void shotNow() = 0;   // pure virtual, must be defined in derived classes
    virtual void shotDelayed();   // not all camera models have this
    virtual void begin();
  protected:
    void wait(unsigned int);
    void high(unsigned int);

    uint8_t _pin;
    uint8_t _freq;
};

class Nikon : public Camera
{
  public:
    Nikon(uint8_t pin) : Camera(pin, 40) {};
    void shotNow();
    //void shotDelayed();
};

class Pentax : public Camera
{
  public:
    Pentax(uint8_t pin) : Camera(pin, 38) {};
    void shotNow();
    //void shotDelayed();
};

class Olympus : public Camera
{
  public:
    Olympus(uint8_t pin) : Camera(pin, 40) {};
    void shotNow();
    //void shotDelayed();
};

class Minolta : public Camera
{
  public:
    Minolta(uint8_t pin) : Camera(pin, 38) {};
    void shotNow();
    void shotDelayed();
};

class Sony : public Camera
{
  public:
    Sony(uint8_t pin) : Camera(pin, 40) {};
    void shotNow();
    void shotDelayed();
};

class Canon : public Camera
{
  public:
    Canon(uint8_t pin) : Camera(pin, 33) {};
    void shotNow();
    void shotDelayed();
};

#endif

.cpp file

/*******************************************

   Name.......:  cameraIrControl Library
   Description:  A powerful Library to control easy various cameras via IR. Please check the project page and leave a comment.
   Author.....:  Sebastian Setz
   Version....:  1.2
   Date.......:  2010-12-16
   Project....:  http://sebastian.setz.name/arduino/my-libraries/multi-camera-ir-control
   Contact....:  http://Sebastian.Setz.name
   License....:  This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
                 To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
                 Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
   Keywords...:  arduino, library, camera, ir, control, canon, nikon, olympus, minolta, sony, pentax, interval, timelapse

 ********************************************/

#include "multiCameraIrControl.h"

void Camera::wait(unsigned int time) {
  unsigned long start = micros();
  while (micros() - start <= time) {
  }
}

void Camera::high(unsigned int time) {
  int pause = (1000 / _freq / 2) - 4;
  unsigned long start = micros();
  while (micros() - start <= time) {
    digitalWrite(_pin, HIGH);
    delayMicroseconds(pause);
    digitalWrite(_pin, LOW);
    delayMicroseconds(pause);
  }
}

void Camera::begin()
{
  pinMode(_pin, OUTPUT);
}

void Camera::shotDelayed()
{
  // generic stub
}


void Nikon::shotNow()
{
  high(2000);
  wait(27830);
  high(390);
  wait(1580);
  high(410);
  wait(3580);
  high(400);
}

void Pentax::shotNow()
{
  high(13000);
  wait(3000);
  for (int i = 0; i < 7; i++) {
    high(1000);
    wait(1000);
  };
}


void Olympus::shotNow()
{
  const byte seq[] = { 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 };
  const byte count = sizeof(seq) / sizeof(seq[0]);
  high(3800);
  wait(4000);
  high(550);
  for (int i = 0; i < count; i++) {
    if (seq[i]) {
      wait(1500);
      high(500);
    }
    else {
      wait(500);
      high(500);
    }
  }
}


void Minolta::shotNow()
{
  const byte seq[] = { 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1 };
  const byte count = sizeof(seq) / sizeof(seq[0]);
  high(3750);
  wait(1890);
  for (int i = 0; i < count; i++) {
    if (seq[i]) {
      high(456);
      wait(1430);
    }
    else {
      high(456);
      wait(487);
    }
  }
}

void Minolta::shotDelayed()
{
  const byte seq[] = { 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
  const byte count = sizeof(seq) / sizeof(seq[0]);
  high(3750);
  wait(1890);
  for (int i = 0; i < count; i++) {
    if (seq[i]) {
      high(456);
      wait(1430);
    }
    else {
      high(456);
      wait(487);
    }
  }
}


void Sony::shotNow()
{
  const byte seq[] = { 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1 };
  const byte count = sizeof(seq) / sizeof(seq[0]);
  high(2320);
  for (int i = 0; i < count; i++) {
    if (seq[i]) {
      high(1175);
      wait(650);
    }
    else {
      high(575);
      wait(650);
    }
  }
}

void Sony::shotDelayed()
{
  const byte seq[] = { 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1 };
  const byte count = sizeof(seq) / sizeof(seq[0]);
  high(2320);
  for (int i = 0; i < count; i++) {
    if (seq[i]) {
      high(1175);
      wait(650);
    }
    else {
      high(575);
      wait(650);
    }
  }
}

void Canon::shotNow()
{
  high(480);
  wait(7330);
  high(480);
}

void Canon::shotDelayed()
{
  high(488);
  wait(5360);
  high(488);
}

Example

#include "multiCameraIrControl.h"

Nikon XXX(12);
Pentax pen(10);
Olympus oly(9);
Sony  slr(11);
Canon A900(13);

Camera *camera;

void setup() {
  A900.begin();
  XXX.begin();
  slr.begin();

  camera = &A900;
  camera->shotNow();
  camera->shotDelayed();
}

void loop() {

}
1 Like

WOW! @blh64 went above and beyond. Perhaps a little too much free time?

If you wanted to create the Camera object at runtime (say in response to user input), then the main code would look like:

#include "multiCameraIrControl.h"

Camera *camera;

void setup() {
  camera = new Canon(13);
  camera->begin();
  camera->shotNow();
  camera->shotDelayed();
}

void loop() {
}

Nailed it! :slight_smile:

If it is useful: GitHub - bhelterline/multiCameraIrControl

You could also statically create all your choices and then just choose

#include "multiCameraIrControl.h"

#define TRIG_PIN  12
Nikon nik(TRIG_PIN);
Pentax pen(TRIG_PIN);
Olympus oly(TRIG_PIN);
Sony  slr(TRIG_PIN);
Canon A900(TRIG_PIN);

Camera *camera;

void setup() {
}

void loop() {

  // if user input is recieved here
  if ( recievedInput == true ) {
    if ( strcmp(input, "Canon") == 0 ) {
      camera = &A900;
    }
    else if ( strcmp(input, "Nikon") == 0 ) {
      camera = &nik;
    }
    else if ... {
    ...
    }
    camera->begin();
  }

  camera->shotNow();
  delay(5000);
  camera->shotDelayed();
}
1 Like

Wow! thanks so much for all the effort for an answer for a random stranger. Sadly I am not having any luck with your new library. First I integrated it directly into my code and when that didn't work I went back to try to the example code. The example builds in both the arduino IDE and using VSCode with platformio on my esp32 but when I try the camera I don't get any shutter trigger. I went back to the old library and it triggers the shutter using the same hardware. Any ideas on where I can start troubleshooting your new library? Here is the code that that I used:

/*******************************************

multiCameraIrControl Library - Example
Description: A small example of the improved library based on Seastian Setz
Author.....: Brian Helterline
Version....: 2.0
Date.......: 07-Jul-2021
Project....: GitHub - bhelterline/multiCameraIrControl
*******************************************/

#include <multiCameraIrControl.h>

#define TRIGGER_PIN 4

// uncomment the camera of choice
// NOTE: Not all models have shotDelayed(). If they do not, nothing will happen

//Canon camera(TRIGGER_PIN);
Sony camera(TRIGGER_PIN);
//Nikon camera(TRIGGER_PIN);
//Pentax cameraam(TRIGGER_PIN);
//Olympus camera(TRIGGER_PIN9);
//Sony camera(TRIGGER_PIN);
//Canon camera(TRIGGER_PIN);

void setup() {
camera.begin();
}

void loop() {
camera.shotNow();
delay(5000);
camera.shotDelayed();
delay(5000);
}

I don't have an esp32 so I used a Mega and ran this test using both the old and new libraries. The only difference being camera.begin(). I changed the pin to 13 so the LED would light up a bit.

// new library

#include "multiCameraIrControl.h"

#define TRIGGER_PIN 13

// uncomment the camera of choice
// NOTE: Not all models have shotDelayed(). If they do not, nothing will happen

//Canon camera(TRIGGER_PIN);
Sony camera(TRIGGER_PIN);
//Nikon camera(TRIGGER_PIN);
//Pentax cameraam(TRIGGER_PIN);
//Olympus camera(TRIGGER_PIN9);
//Sony camera(TRIGGER_PIN);
//Canon camera(TRIGGER_PIN);

void setup() {
  Serial.begin(115200);
  delay(2000);
  camera.begin();
  Serial.println("New Library test");
}

void loop() {
  unsigned long t1, t2, t3, t4;

  t1 = micros();
  camera.shotNow();
  t2 = micros();
  delay(5000);
  t3 = micros();
  camera.shotDelayed();
  t4 = micros();

  Serial.print(t1);
  Serial.print(','); Serial.print(t2);
  Serial.print(','); Serial.print(t3);
  Serial.print(','); Serial.println(t4);
  delay(5000);
}

Based on the timings, it appears the new library takes about ~350 usec longer to do the same job. That might be enough to throw off the timings. I'm guessing that the original author adjusted his waits/highs a bit to get close enough to work.

Ideally, you would have the mfg spec and an oscilloscope on the output pin to verify timings, but I have neither


Old Library test									shotNow		shotDelay			
 2000164	 2034896	 7034908	 7070200	 	 34,732 	 35,292 			
12071660	12106364	17106372	17141692		 34,704 	 35,320 			
22143360	22178040	27178052	27213336		 34,680 	 35,284 			
32215000	32249736	37249748	37285088		 34,736 	 35,340 			
42286752	42321440	47321452	47356768		 34,688 	 35,316 			
52358436	52393196	57393208	57428496		 34,760 	 35,288 			
62430168	62464900	67464908	67500208		 34,732 	 35,300 			
72501872	72536552	77536560	77571840		 34,680 	 35,280 			
82573512	82608256	87608272	87643568		 34,744 	 35,296 			

New Library test									shotNow		shotDelay
 2000168	 2035228	 7035240	 7070876		 35,060 	 35,636
12072336	12107424	17107436	17143080		 35,088 	 35,644
22144740	22179768	27179776	27215440		 35,028 	 35,664
32217104	32252160	37252168	37287816		 35,056 	 35,648
42289484	42324560	47324572	47360212		 35,076 	 35,640
52361872	52396936	57396948	57432612		 35,064 	 35,664
62434284	62469344	67469352	67505016		 35,060 	 35,664
72506684	72541768	77541776	77577416		 35,084 	 35,640

Delta

Delta 	
shotNow	shotDelay
 328 	 344 
 384 	 324 
 348 	 380 
 320 	 308 
 388 	 324 
 304 	 376 
 328 	 364 
 404 	 360 

I feel a bit sheepish but I figured out that I linked an older version of the multiCameraIRControl library. Really sorry I wasted your time!

I found the latest version of the library (last updated 2013) through a hackaday project link and uploaded it to my Github: https://github.com/MATT-ER-HORN/multiCameraIrControl.

I modified the Sony section in the .cpp file in your new library in order to match the pulse sequence from the newer version of the library and the example is working for the Sony camera. I have the morning off tomorrow and will see if I can add all the additional functions to your version of the library and integrate it into my project. If you are interested I am trying to integrate the library into this project: https://github.com/MATT-ER-HORN/TrackStar_firmware

Thanks again for your help!

Matt

Update: new library updated and the camera is selectable by sending a command from a bluetooth app while the arduino sketch is running! Uploaded the library to my Github: GitHub - MATT-ER-HORN/multiCameraIrControl. There is one function in the original library that I haven't figured out how to add because it takes another argument and I am not sure how to add it correctly to the library so left it commented out. Thanks to blh64 for his help!

Matt

Cool. I'm going to take mine down since it doesn't work and you've fixed/improved yours!