A question we receive quite frequently is how to interface control of the GoPro camera with a microcontroller such as an Arduino or ESP8266 (and many others).
This blog post provides a quick guide on how to do that using the CamDo Blink GoPro time lapse controller. You might also be interested in our post here onHow to interface your GoPro to a Radio Control which uses our Bullet product to interface to an RC controller. We will also be publishing a follow-up post onHow to interface your GoPro to a Raspberry Pi.
The use cases for this project are varied - some of the interesting examples we have seen include underwater ROV’s, robotics, to trigger lights, power wifi dongles and more.
Parts required:
- GoPro camera (HERO4 or HERO3+Black/HERO3+Silver)
- 1 x CamDo Blink with firmware version v2.01 (coming soon!) or later
- 2.5mm stereo cable
- 3.5mm stereo cable
- Arduino Uno (or similar but the pin-outs and voltages might change) plus the following parts:
- Momentary Button or Switch
- 10k ohm Resistor
- Hook-Up Wires
- Breadboard
The first thing we need to understand are the waveforms that the CamDo Blink accepts and the resultant camera action.
Blink Signal Interface
Blink has two audio jack style ports through which you can trigger the camera (3.5mm connector) and also receive back status information (2.5mm connector). These connections are usually used to interface to other CamDo products such as the X-band Motion Detector or the CamDo Wired Remote. But we can leverage these connections to interface it to some external hardware such as a microcontroller.
The connections are as follows:
2.5mm Port
The 2.5mm audio jack style port (TRS) is usually used to turn on Blink WiFi through a wired remote. We however can also retrieve ‘camera on’ status through this port. Connections are as follows:
- Tip : Camera On Status
- Ring : Blink WiFi control (turn on/off)
- Sleeve : Ground
Camera Status
This pin remains high only when the camera is on. It will also toggle state when Blink WiFi is switched on or off as further described below. This allows you to receive feedback through the Tip connection on the 2.5mm port to validate the camera is on.
WiFi Ctrl
Connecting this pin to GND for more than three seconds will cause Blink WiFi to be cycled (ie. if WiFi is OFF, it will turn ON). When WiFi turns on, the Camera Status pin will toggle three times, and when WiFi turns off the Camera Status pin will toggle two times.
NOTE:
- All connections on this port are logic level 3v3
- Only dry contacts should be used to interface such as relays or switches. No voltage should be induced on this line as it may damage your Blink!
3.5mm Port (PIR/External Input)
The 3.5mm audio jack style port (TRS) is designed to power an external peripheral/sensor and react to signals generated by that peripheral/sensor. CamDo has an X-band Motion Detector for example that uses this port.
Connections are as follows:
- Tip : +5V power supply
- Ring : External Signal
- Sleeve : Ground
NOTE:
- +5V @ 350mA can be drawn from this port to power the peripheral only if USB power is supplied to Blink via the mini USB port on the side. If USB power is not supplied, 10mA max can be supplied.
- This port only supplies power when a Motion Detection schedule is active (a setting within the Blink web UI). This is to conserve power during sleep.
- Signal is internally protected but care must still be used to prevent damage to the input transistor. Acceptable range is +3.3V to +5V to the signal pin (ring connection).
External Signal Inputs
Now that we know what the connections are doing, how do we use them?
Blink can be setup to accept two types of motion detection triggers: X-Band (detecting edge transitions) and PIR (constant high or low input signal).
We will explain both of these below so that you can make the best choice for your particular peripheral. We’ll start with the easy one first.
PIR Motion Detector Profile
The simplest one is the PIR motion detector profile on Blink as this just accepts a constant high or low input signal and the GoPro camera reacts accordingly.
PIR motion detectors work by sensing infrared light and sending a solid pulse when the sensor deems an event to have occurred. To prevent false detections, Blink samples the signal continuously over a given time frame. The signal must stay high for >0.25 seconds before Blink accepts the detection and executes the action for that schedule.
The waveform that you must generate using the microcontroller (or other peripheral) thus looks like the following:
If the schedule “Action” is set to Photo, the camera will turn on, take an image, and turn off. If the signal is still high when it turns off, the schedule will trigger again. This works slightly different if the “Action” is set to Video. In that case the camera will turn on, start recording, an continue to record until the input signal goes low.
X-Band Motion Detector Profile
The X-band profile is more complicated due to the nature of the X-Band motion detectors, which work on the Doppler effect and send pulses related to the speed of the object in it’s operating view.
The beauty is that they can detect motion through walls and windows, something that a PIR cannot do. This allows these style detectors to be mounted inside our weatherproof enclosures and remain protected from the critters you are trying to video.
Blink will read the pulses and determine if an object is in view based on how many pulses it sees per unit time. See the waveform image below. In this case, Blink discards the first pulse as an anomaly but then detects something later and executes the action for that schedule. While the camera is recording video and Blink continues to detect motion, video will keep recording. Note that this is not the case for photo or burst mode.
Blink will trigger if more than 10 edges are detected within 250 milliseconds.
This is obviously more complicated than a simple high or low signal as per the PIR, but we would be very interested to hear the applications that you come up with.
So you can see, you have two options. When designing a custom trigger, be sure to select the appropriate detection scheme for your application.
Camera Feedback
As noted above, using the 2.5mm port you can validate the camera is On via the Tip connection which will go high. Note this signal only confirms the camera is on, not that it is actually recording.
So now we understand the signals required, let’s get to the microcontroller part.
Interfacing to a Microcontroller (Arduino)
Arduinos are fantastically cheap and common so we will use them for this example.
The following sketch reads the input from an external pushbutton and activates the GoPro whilst that external button/switch is turned on. At the same time, we read the status back from the camera and and flash the onboard Arduino LED (0.5 second period) whilst the camera is on as visual feedback.
The Arduino’s onboard LED is connected to pin 13 on most models - so you don’t have to worry, the constantLED_BUILTIN
is automatically set to the correct pin. If you want to connect an external LED, then you will need to check your model and change theledPin
value below to an alternate pin if necessary.
Schematic & Breadboard views
The following schematic and breadboard views outline the connections required:
The main connections are as follows (based on the Arduino Uno):
- Connection between the Arduino (pin 2) and the Ring connection on the 3.5mm port to act as the input to Blink.
- Camera status is read back on pin 3 on the Arduino which needs to be connected to the Tip connection on the 2.5mm Blink port.
- The pushbutton connection is set to Pin 7. Note you will need to connect a pulldown resistor (10k or similar) to keep the signal LOW when the button is not being pressed so that a spurious state is not read as per the schematic above.
Arduino Sketch
Now that we have the breadboard setup, you can load the following sketch up onto your Arduino. There are many tutorials out there on how to do this, so I won’t go into detail here.
/*
7th February 2017
CamDo Solutions Inc.
Arduino sketch to activate the GoPro camera using Blink via an external pushbutton/switch, receive feedback and flash the on-board Arduino LED accordingly.
*/
// constants used here to set pin numbers
const int ledPin = LED_BUILTIN; // the number of the LED pin (pre-defined)
const int cameraTriggerPin = 2; // connected to digital pin 2
const int cameraStatusPin = 3; // connected to digital pin 3
const int buttonPin = 7; // pushbutton connected to digital pin 7
const long interval = 500; // LED flash interval (milliseconds)
//variables
int ledState = LOW; // ledState used to set the LED
int cameraState = LOW; // cameraState used to store camera status (on/off)
int buttonState = LOW; // for reading the pushbutton status
unsigned long previousMillis = 0; // will store last time LED was updated
void setup()
{
pinMode(cameraTriggerPin, OUTPUT); // set cameraTriggerPin as an output
pinMode(cameraStatusPin, INPUT); // sets cameraStatusPin as an input
pinMode(ledPin, OUTPUT); // sets ledPin as an output
pinMode(buttonPin, INPUT); // sets buttonPin as an input
Serial.begin(9600); // open the serial port at 9600 bps:
}
/*
The main loop reads the status of the pushButton and writes the value
to Blink to trigger the camera. It then checks the camera feedback
and flashes the onboard Arduino LED
accordingly.
*/
void loop()
{
buttonState = digitalRead(buttonPin); // read the status of the pushbutton
Serial.print("Button state:");
Serial.print("\t"); // prints a tab
Serial.println(buttonState); // print buttonState
digitalWrite(cameraTriggerPin, buttonState); // send the button status to Blink
cameraState = digitalRead(cameraStatusPin); // read the status of the camera from Blink
Serial.print("Camera state:");
Serial.print("\t"); // prints a tab
Serial.println(cameraState); // print buttonState
//check if we are going to flash the LED. ie Blink is reporting back that the camera is on.
if (cameraState == HIGH) {
// check if it's time to flash the LED; ie if the difference between the current time
// and last time the LED flashed is bigger than the interval set above.
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time the LED flashed
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
// write the ledState to the LED.
digitalWrite(ledPin, ledState);
}
}
else {
digitalWrite (ledPin, LOW); // make sure the LED is off if camera state is LOW.
}
}
Bringing It All Together
- Update Blink to the latest firmware version from theCamDo support centre here. (requires at least v2.01 - coming soon!)
- Connect Blink to your GoPro
- Set Blink into the PIR motion detector mode for a schedule.Refer to the Blink manual if you are unsure.
- Connect the 3.5mm ‘Ring’ connection to Arduino digital pin 2 and the Sleeve to the ground rail on your breadboard.You can purchase an audio extension cable and just cut it in half and strip back the wires. Use a multi-meter continuity test to check which wires are connected to the Tip, Ring and Sleeve of the audio jack.
- Connect the 2.5mm ‘Tip’ connection to Arduino digital pin 3 and the Sleeve to the ground rail on your breadboard. You could just cut a 3.5mm audio extension cable (from Step 4) in half and then use the other end with a cheap 3.5mm to 2.5mm audio jack converter.
- Setup the remainder of the circuit as per the diagram above with the pull down resistor and switch.
- Upload the sketch as above.
Now when you hold down the external switch for more than 0.25 seconds, the camera should turn on and take the action you set in the Blink UI. The Arduino onboard LED should flash as long as the camera is on.
That’s it - you now know how to interface your GoPro to a microcontroller using Blink.
Appendix
The schematic and breadboard views were generated withFritzing.
All timing diagrams were generated using the very handy tool at Wavedrom. We have included the parameters below, which you can paste into the tool to play around with different waveforms and to form up your own.
X-Band Detection Diagram
{ "signal" : [
{ "name": "Signal", "wave": "Lpl...p...x.|.0..", node: '.a..b.c..d' },
{ "name": "Schedule", "wave": "l........3..|.0..", "data": ["Active"] },
],
edge: [
'ab 0.25 s',
'cd 0.25 s'
],
head:{
text:'X-Band Detection',
}
}
PIR Detection Diagram
{ "signal" : [
{ "name": "Signal", "wave": "lP...l..H.X..|x0.", node: '.a.b....c.d'},
{ "name": "Schedule", "wave": "l.........3..|.0.", "data": ["Active"] },
],
edge: [
'ab 0.25 s',
'cd 0.25 s',
],
head:{
text:'PIR Detection',
}
}