Gearing up (3)

Okay the automated photo booth is now 100% functional and here’show I did it:

The heart of this project is an arduino. I’m not very proficient in arduino stuff but I know enough about programming to be able to copy paste bits and pieces and make adjustments to existing code.

The second part is obviously the choice of the camera. I did my previous tests with a goPro, but after some research it turns out you cannot hack the shutter release of the newer models without opening the case and voiding the warranty. Hacking the wifi remote is an option, but I’d rather stay away from wireless solutions, because I feel that is overcomplicating things and might introduce timing issues depending on the quality of the signal.

Speaking of timing issues, the first thing that came to mind when brainstorming for this project was the obvious solution: have the camera set in timelapse modus, for example with a 5 second interval, and then time the arduino sketch to match this timing. I decided to not even try it, because the two systems would work completely isolated and would almost certainly end up in timing misalignment after a while. I feel that I really need to program the shutter release from within the arduino sketch in order to reduce the number of variables.

So back to the drawing board, and I found a rather elegant solution for the camera: my smartphone.

At first sight a smartphone seems even more difficult to hack, but it turns out I don’t need to do anything to it because everything I need is already present. I’m actually making use of 2 somewhat ‘hidden’ features that most modern smartphones support.

The first feature is easy to test: open up the camera app and press the ‘volume up’-button on the side of your phone. It should take a picture. Most manufacturers have added this feature in order to give you a hardware button to take pictures, which is conveniently located roughly where the shutter button would be on a regular camera (if held in landscape orientation off course).

Second is TRRS support. Every phone has a 3.5mm headphone jack, but not every 3.5mm mini-jack is the same. You have mono jacks (TS), stereo jacks (TRS), and then there is TRRS, which has another extra ring for miscellaneous use.

trrs-diagram1

People who own an iPod/iPhone will be familiar with earbuds with ‘remote controls’ on them. The interesting thing about this is that there is a ‘volume up’-button. You’ll notice that the earbuds have a TRRS jack, with the extra ring used to feed your volume button presses back to the phone. When the camera app is open, pressing the ‘volume up’-button on your earbud remote will effectively trigger the camera.

Now I don’t personally have iPhone earbuds (in fact it doesn’t need to be Apple brand, any headphone with digital volume buttons will do). But I found an even better solution: a selfie stick.

Some selfie sticks nowadays exploit the TRRS functionality. They feature a button on the handle that gives a ‘volume-up’-pulse to your smartphone via the minijack. So I picked up one of these selfie sticks on eBay for a couple of bucks, and immediately took it apart. What a waste of a perfectly good selfie stick… I ended up with just the wire and a small control board. I did have to re-solder all connections, because they had done a rather flimsy job.

2016-06-06 15.20.46 2016-06-06 16.09.10

Just to make sure it works, I hooked it up to a test board with a button, and as you can see, the button press triggered my phone camera!

2016-06-06 16.34.35

Next thing to do is replace that button with a relay, triggered by the arduino. I don’t have pictures of that, but it is pretty basic stuff so google it if you need to. After that, it was time to clean up the wiring a bit. I milled some pockets in the base, and inserted the electronics. This was done in intervals throughout the duration of this build, so it isn’t very clean, but at least it hides most of the mess. Who cares anyway… It works and i’ll probably revise it anyway in the near future.

2016-05-30 17.43.52 2016-06-06 17.36.29

2016-06-06 17.36.48 2016-06-06 17.38.47

Now that all of that is is out of the way, time to test this thing:

Seems to work.

 

I’m going to fine-tune the code over the next couple of days, but here’s the current version. The loop-function is very straightforward and easy to understand.

// turn motor 1 full rotation
// press shutter
// wait 0.1s
//  release shutter
// wait 1s to take picture

So here’s the code:

// DEFINE PINS & VARIABLES ---------------------------------------------

#define IN1 4
#define IN2 5
#define IN3 6
#define IN4 7
#define CYCLES_PER_ROTATION 512

void setup() 
{
 Serial.begin(9600);
 pinMode(IN1, OUTPUT); 
 pinMode(IN2, OUTPUT); 
 pinMode(IN3, OUTPUT); 
 pinMode(IN4, OUTPUT);
 pinMode(11, OUTPUT); //relay IN pin 
}

// MAIN PROGRAM ---------------------------------------------------------

void loop() 
{
 turns(1); // turn motor 1 full rotation
 digitalWrite(11, HIGH); // press shutter 
 delay(100); // wait 0.1s
 digitalWrite(11, LOW); // release shutter
 delay(1000); // wait 1s to take picture
}

// STEPPER DRIVER (DO NOT EDIT BELOW THIS LINE) ------------------------

void turns(float rotations)
{
 // if the rotation count is -ve then it is CCW
 Serial.println();
 Serial.print("Turning : ");
 Serial.print(rotations);
 Serial.println(" rotations");
 bool clockwise = rotations > 0;
 Serial.print("Clockwise = ");
 Serial.println(clockwise);
 // calculate how many cycles the stepper will have to make
 int cycles = rotations * CYCLES_PER_ROTATION;
 // force the cycle count to be positive
 cycles = abs(cycles);
 Serial.print("That is ");
 Serial.print(cycles);
 Serial.print(" Cycles ");
 // only move if the user specifed an actual movement
 if(rotations != 0)
 {
 if (clockwise)
 {
 Serial.println("Clockwise");
 // for each cycle
 for (int x=0; x<cycles; x++)
 {
 // for each phase
 for(int y=0; y<8; y++)
 {
 // go to phase y
 phaseSelect(y);
 // pause so the stepper has time to react
 delay(1);
 }
 }
 } else {
 Serial.println("Counter Clockwise");
 // for each cycle
 for (int x=0; x<cycles; x++)
 {
 // for each phase (backwards for CCW rotation)
 for(int y=7; y>=0; y--)
 {
 // go to phase y
 phaseSelect(y);
 // pause so the stepper has time to react
 delay(1);
 }
 }
 }
 }
 // go to the default state (all poles off) when finished
 phaseSelect(8);
 Serial.println("Done");
}

void phaseSelect(int phase)
{
 switch(phase){
 case 0:
 digitalWrite(IN1, LOW); 
 digitalWrite(IN2, LOW);
 digitalWrite(IN3, LOW);
 digitalWrite(IN4, HIGH);
 break; 
 case 1:
 digitalWrite(IN1, LOW); 
 digitalWrite(IN2, LOW);
 digitalWrite(IN3, HIGH);
 digitalWrite(IN4, HIGH);
 break; 
 case 2:
 digitalWrite(IN1, LOW); 
 digitalWrite(IN2, LOW);
 digitalWrite(IN3, HIGH);
 digitalWrite(IN4, LOW);
 break; 
 case 3:
 digitalWrite(IN1, LOW); 
 digitalWrite(IN2, HIGH);
 digitalWrite(IN3, HIGH);
 digitalWrite(IN4, LOW);
 break; 
 case 4:
 digitalWrite(IN1, LOW); 
 digitalWrite(IN2, HIGH);
 digitalWrite(IN3, LOW);
 digitalWrite(IN4, LOW);
 break; 
 case 5:
 digitalWrite(IN1, HIGH); 
 digitalWrite(IN2, HIGH);
 digitalWrite(IN3, LOW);
 digitalWrite(IN4, LOW);
 break; 
 case 6:
 digitalWrite(IN1, HIGH); 
 digitalWrite(IN2, LOW);
 digitalWrite(IN3, LOW);
 digitalWrite(IN4, LOW);
 break; 
 case 7:
 digitalWrite(IN1, HIGH); 
 digitalWrite(IN2, LOW);
 digitalWrite(IN3, LOW);
 digitalWrite(IN4, HIGH);
 break; 
 default:
 digitalWrite(IN1, LOW); 
 digitalWrite(IN2, LOW);
 digitalWrite(IN3, LOW);
 digitalWrite(IN4, LOW);
 break; 
 }
}

One thought on “Gearing up (3)

Leave a Reply

Your email address will not be published. Required fields are marked *