MAKER:randofo/译:趣无尽 Cherry(转载请注明出处)
在本项目中,我将向你展示如何使用 Arduino 板控制GoPro Hero 4和GoPro Hero Session 5。掌握这些技能后,就可以轻松用于任何型号的GoPro,这将非常实用。你可以通过Arduino直接使用一些基本的网络命令与其进行通信,而不是侵入现有的控制器。你不仅可以控制GoPro上的功能,还可以接收有关相机状态的更新。这将成为不同类型项目的通用解决方案,包括自定义机器人和无人机。
材料清单
1、GoPro Hero 4和GoPro Hero Session 5(也适用于最新型号GoPro Hero 6。Hero Session模型与其它型号的控制略有不同,但我们将在稍后介绍。)
2、Arduino MKR1000或Arduino MKR ZeroX1 (你也可以使用另一种兼容Arduino的无线微控制器板,例如:Feather,但这款我没有进行个人测试。)
3、与Arduino相连的USB连接线X1
4、一台运行Arduino开发软件的计算机X1
5、安装GoPro应用程序的智能手机X1
如果你没有这些东西,或者之前从未使用过Arduino,建议你在开始这个项目之前,先阅读Arduino的基础教程!
设置相机的Wifi
打开相机并配置好相机的wifi连接。
型号GoPro Hero4,最简单的wifi连接方法是按照应用程序中的说明将相机连接到手机。手机与相机配对后,使用应用程序打开相机设置,并为wifi网络设置新名称和密码。同样方法适用于GoPro Hero Session 5。
要在相机上查看wifi网络名称,查看“连接设置”菜单下的“相机信息”。
找到你的GoPro的MAC地址
启用wifi后,你需要确定相机的MAC(media access control,媒体访问地址)。在处理传统的Hero系列GoPros时,这个地址是提供信息一个很好的途径。如果你使用的是GoPro Hero Session,这个地址是必备的。
首先使用上一步中的网络名称和密码将计算机连接到相机的wifi网络。
其次,登录相机的wifi网络后,打开计算机上的任何浏览器,然后访问以下网址:
http://10.5.5.9/gp/gpControl/info
此网址应在你的Web浏览器中显示一串信息,如下所示:
{"model_number"21,"model_name":"HERO5Session","firmware_version":"HD5.03.02.51.00","serial_number":"C3212365684485","board_type":"0x05","ap_mac":"0641631510c4","ap_ssid":"GP54688615","ap_has_default_credentials":"0","capabilities":"16"}
如果没有,请确保你的相机打开,并检查wifi连接。
字符中我们感兴趣的是“ap_mac:”后面的数字字符。这个12位数字串是MAC地址,即:0641631510c4。
确定地址后,每隔两个字符将其分开,并按如下格式进行格式化:
0x06, 0x41, 0x63, 0x15, 0x10, 0xC4
将Arduino连接到GoPro Hero
为了让Arduino与GoPro Hero系列相机相连,需要使用识别码进行配对。要获取识别码,请在手机菜单中导航将相机与应用程序配对。所有后期型号相机上将生成4位数的识别码(Hero 3及更早版本是6位数的识别码)。
识别码只持续3分钟,所以时间至关重要。
你需要在下面的代码中手动输入识别码两次:
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //ENTER YOUR PIN HERE WHERE IT SAYS XXXX //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
输入识别码后,你只需不到三分钟的时间将其上传到Arduino并与相机建立连接。
注意,不要忘记输入GoPro的wifi凭证,如下:
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //ENTER YOUR WIFI NAME AND PASSWORD HERE //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
所有的操作都是以成功上传代码为目的,一旦成功,不会发生任何事情。即便如此,你可以进行以下操作。如果你从GoPro的设置菜单导航回视频屏幕,你现在应该能够发送命令(我们将在稍后介绍)。
如果在接下来的步骤中你无法向相机发送命令,请返回并重复此步骤。
使用识别码码将GoPro与Arduino配对的代码:
#include <SPI.h> #include <WiFi101.h> #include <WiFiUdp.h> int status = WL_IDLE_STATUS; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //ENTER YOUR WIFI NAME AND PASSWORD HERE //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! char ssid[] = "XXXXXXXXXXXX"; // your network SSID (name) char pass[] = "XXXXXXXXXXXX"; // your network password (use for WPA, or use as key for WEP) WiFiClient client; const char* host = "10.5.5.9"; const int httpPort = 80; void setup(){ //Initialize serial and wait for port to open: Serial.begin(115200); // check for the presence of the wifi module: if (WiFi.status() == WL_NO_SHIELD) { Serial.println("WiFi not present"); // don't continue: while (true); } // attempt to connect to Wifi network: while ( status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: status = WiFi.begin(ssid, pass); // wait 8 seconds for connection: delay(8000); } Serial.println("Connected to wifi"); printWifiStatus(); // START PIN StartPin(); delay(10000); // FINISH PIN FinishPin(); } void loop(){ //Nothing to do here! delay(1000); } void StartPin(){ Serial.print("connecting to "); Serial.println(host); if (!client.connect("10.5.5.9", httpPort)) { Serial.println("connection failed"); return; } //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //ENTER YOUR PIN HERE WHERE IT SAYS XXXX //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! String StartUrl = "/gpPair?c=start&pin;=XXXX&mode;=0"; Serial.print("Requesting URL: "); Serial.println(StartUrl); client.print(String("GET ") + StartUrl + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); Serial.println("Started"); } void FinishPin(){ Serial.print("connecting to "); Serial.println(host); if (!client.connect("10.5.5.9", httpPort)) { Serial.println("connection failed"); return; } //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //ENTER YOUR PIN HERE WHERE IT SAYS XXXX //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! String StopUrl = "10.5.5.9/gpPair?c=finish&pin;=XXXX&mode;=0"; Serial.print("Requesting URL: "); Serial.println(StopUrl); client.print(String("GET ") + StopUrl + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); Serial.println("Finished"); } void printWifiStatus() { // print the SSID of the network you're attached to: Serial.print("SSID: "); Serial.println(WiFi.SSID()); // print your WiFi shield's IP address: IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip); // print the received signal strength: long rssi = WiFi.RSSI(); Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm"); }
将Arduino连接到GoPro Hero Session
GoPro Session没有可供使用的识别码。它的连接方式有些麻烦。正如你注意到的那样,只要你完成录制,或者只要你完成对相机的大部分操作,它就会关闭并进入睡眠模式。
在你发送任何命令到GoPro Hero之前,你需要将其唤醒。最简单的方法是手动按下摄像机背面的菜单按钮,并在它醒来的几秒窗口内发送命令。然而,令人厌烦的是,这个方法并不是特别实用。
唤醒GoPro的更好方法是使用WOL数据包或“魔术数据包”。这个首字母缩写词代表Wake-on-Lan,是一种远程唤醒计算机从睡眠模式的协议。它需要使用UDP协议,从Arduino发送字节到GoPro以唤醒它。有点让人抓狂的是,它与你发送所有其他控制命令的协议不同。如果你不熟悉编程,代码也不那么棒,处理起来有点复杂。
然而,当它起作用时,它真的像魔术一样神奇。通过向Arduino发送命令,看着我的相机醒来,这种感叹从未停止过!
WOL命令(代码中的相机启动()功能)需要在大多数其他命令之前发送,并且通常会延迟1-2秒。基本上,在你需要唤醒相机时(大多数时间)发送它。发送命令后,暂停片刻才能让相机实际唤醒。
请看下面示例,WOL功能设置中调试使用,因此它只能在你第一次运行时唤醒相机。
不要忘记在提示输入代码的地方输入GoPro的wifi凭证和MAC地址!
以下是唤醒相机的代码:
#include <SPI.h> #include <WiFi101.h> #include <WiFiUdp.h> int status = WL_IDLE_STATUS; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //ENTER YOUR WIFI NAME AND PASSWORD HERE //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! char ssid[] = "XXXXXXXXXXXX"; // your network SSID (name) char pass[] = "XXXXXXXXXXXX"; // your network password (use for WPA, or use as key for WEP) int localPort = 7; byte broadCastIp[] = { 10,5,5,9 }; //!!!!!!!!!!!!!!!!!!!!!!!!!!! //ENTER YOUR MAC ADDRESS HERE //!!!!!!!!!!!!!!!!!!!!!!!!!!! byte remote_MAC_ADD[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; int wolPort = 9; WiFiUDP Udp; WiFiClient client; const char* host = "10.5.5.9"; const int httpPort = 80; void setup(){ //Initialize serial and wait for port to open: Serial.begin(115200); // check for the presence of the wifi module: if (WiFi.status() == WL_NO_SHIELD) { Serial.println("WiFi not present"); // don't continue: while (true); } // attempt to connect to Wifi network: while ( status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: status = WiFi.begin(ssid, pass); // wait 8 seconds for connection: delay(8000); } Serial.println("Connected to wifi"); printWifiStatus(); delay(1000); // WAKE UP YOUR SLEEPY CAMERA! CameraInitiate(){ // NOTE: If this does not seem to be working, // turn your camera on and off and try again. } void loop(){ //Nothing to do here! delay(1000); } // FUNCTION TO WAKE UP THE CAMERA void CameraInitiate(){ //Begin UDP communication Udp.begin(localPort); //Send the magic packet to wake up the GoPro out of sleep delay(2000); SendMagicPacket(); delay(5000); // Absolutely necessary to flush port of UDP junk for Wifi client communication Udp.flush(); delay(1000); //Stop UDP communication Udp.stop(); delay(1000); } // Function to create and send magic packet // Taken and translated from here: // https://www.logicaprogrammabile.it/wol-accendere-computer-arduino-wake-on-lan/ void SendMagicPacket(){ //Create a 102 byte array byte magicPacket[102]; // Variables for cycling through the array int Cycle = 0, CycleMacAdd = 0, IndexArray = 0; // This for loop cycles through the array for( Cycle = 0; Cycle < 6; Cycle++){ // The first 6 bytes of the array are set to the value 0xFF magicPacket[IndexArray] = 0xFF; // Increment the array index IndexArray++; } // Now we cycle through the array to add the GoPro address for( Cycle = 0; Cycle < 16; Cycle++ ){ //eseguo un Cycle per memorizzare i 6 byte del //mac address for( CycleMacAdd = 0; CycleMacAdd < 6; CycleMacAdd++){ magicPacket[IndexArray] = remote_MAC_ADD[CycleMacAdd]; // Increment the array index IndexArray++; } } //The magic packet is now broadcast to the GoPro IP address and port Udp.beginPacket(broadCastIp, wolPort); Udp.write(magicPacket, sizeof magicPacket); Udp.endPacket(); } void printWifiStatus() { // print the SSID of the network you're attached to: Serial.print("SSID: "); Serial.println(WiFi.SSID()); // print your WiFi shield's IP address: IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip); // print the received signal strength: long rssi = WiFi.RSSI(); Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm"); }
发送GoPro命令
在这个例子中,我将展示如何发送命令来启动和停止视频录制。
此处将使用相同方法来演示,你能够将相机中的每个功能发送命令。 GoPro Hero 4命令似乎是所有后续相机型号的标准设置。然而,一些较新的相机具有值得研究的新功能和特定于摄像头的命令。你可以通过单击特定相机型号的链接,在Unofficial GoPro WiFi API github页面上找到特定于摄像头的命令。
请看以下示例,录制持续5秒,停止录制,等待5秒钟后,然后重新开始。如果你使用的是Hero Session,请务必取消唤醒GoPro的代码行。
再次注意,不要忘记输入你的GoPro的WiFi凭证和MAC地址!
用于发送开始和停止录制命令的代码:
#include <SPI.h> #include <WiFi101.h> #include <WiFiUdp.h> int status = WL_IDLE_STATUS; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //ENTER YOUR WIFI NAME AND PASSWORD HERE //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! char ssid[] = "XXXXXXXXXXXX"; // your network SSID (name) char pass[] = "XXXXXXXXXXXX"; // your network password (use for WPA, or use as key for WEP) int localPort = 7; byte broadCastIp[] = { 10,5,5,9 }; //!!!!!!!!!!!!!!!!!!!!!!!!!!! //ENTER YOUR MAC ADDRESS HERE //!!!!!!!!!!!!!!!!!!!!!!!!!!! byte remote_MAC_ADD[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; int wolPort = 9; WiFiUDP Udp; WiFiClient client; const char* host = "10.5.5.9"; const int httpPort = 80; void setup(){ //Initialize serial and wait for port to open: Serial.begin(115200); // check for the presence of the wifi module: if (WiFi.status() == WL_NO_SHIELD) { Serial.println("WiFi not present"); // don't continue: while (true); } // ADD THIS TO LOOP?????????????? // MAKE ITS OWN FUNCTION??????? // attempt to connect to Wifi network: while ( status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: status = WiFi.begin(ssid, pass); // wait 8 seconds for connection: delay(8000); } Serial.println("Connected to wifi"); printWifiStatus(); } void loop(){ // Add code to check to see if wifi is still on. If not, stop and keep trying to connect // WAKE UP CAMERA FROM SLEEP AND CONNECT CameraInitiate(); // Add code to make sure that camera recognized (status 31) // START RECORDING StartRecording(); delay(5000); // STOP RECORDING StopRecording(); delay(5000); } void StartRecording(){ Serial.print("connecting to "); Serial.println(host); if (!client.connect("10.5.5.9", httpPort)) { Serial.println("connection failed"); return; } //Command for starting recording String StartUrl = "/gp/gpControl/command/shutter?p=1"; Serial.print("Requesting URL: "); Serial.println(StartUrl); client.print(String("GET ") + StartUrl + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); Serial.println("Recording"); } void StopRecording(){ Serial.print("connecting to "); Serial.println(host); if (!client.connect("10.5.5.9", httpPort)) { Serial.println("connection failed"); return; } //Command for stopping recording String StopUrl = "/gp/gpControl/command/shutter?p=0"; Serial.print("Requesting URL: "); Serial.println(StopUrl); client.print(String("GET ") + StopUrl + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); Serial.println("Stopped"); } // FUNCTION TO WAKE UP THE CAMERA void CameraInitiate(){ //Begin UDP communication Udp.begin(localPort); //Send the magic packet to wake up the GoPro out of sleep delay(2000); SendMagicPacket(); delay(5000); // Absolutely necessary to flush port of UDP junk for Wifi client communication Udp.flush(); delay(1000); //Stop UDP communication Udp.stop(); delay(1000); } // Function to create and send magic packet // Taken and translated from here: // https://www.logicaprogrammabile.it/wol-accendere-computer-arduino-wake-on-lan/ void SendMagicPacket(){ //Create a 102 byte array byte magicPacket[102]; // Variables for cycling through the array int Cycle = 0, CycleMacAdd = 0, IndexArray = 0; // This for loop cycles through the array for( Cycle = 0; Cycle < 6; Cycle++){ // The first 6 bytes of the array are set to the value 0xFF magicPacket[IndexArray] = 0xFF; // Increment the array index IndexArray++; } // Now we cycle through the array to add the GoPro address for( Cycle = 0; Cycle < 16; Cycle++ ){ //eseguo un Cycle per memorizzare i 6 byte del //mac address for( CycleMacAdd = 0; CycleMacAdd < 6; CycleMacAdd++){ magicPacket[IndexArray] = remote_MAC_ADD[CycleMacAdd]; // Increment the array index IndexArray++; } } //The magic packet is now broadcast to the GoPro IP address and port Udp.beginPacket(broadCastIp, wolPort); Udp.write(magicPacket, sizeof magicPacket); Udp.endPacket(); } void printWifiStatus() { // print the SSID of the network you're attached to: Serial.print("SSID: "); Serial.println(WiFi.SSID()); // print your WiFi shield's IP address: IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip); // print the received signal strength: long rssi = WiFi.RSSI(); Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm"); }
接收GoPro状态更新
可以使用以下链接从GoPro接收状态更新:
http://10.5.5.9/gp/gpControl/status
使用此链接时,它会提供一个JSON对象,可以对摄像头状态指南对其进行分析。
最简单的方法是使用计算机连接到GoPro的wifi网络,并使用网络浏览器加载上述链接。
它的反馈信息是:
{"status"{"1":1,"2":2,"3":0,"4":0,"6":0,"8":0,"9":0,"10":0,"13":0,"14":0,"15":0,"16":0,"17":1,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"26":0,"27":0,"28":82,"29":"","30":"","31":0,"32":0,"33":0,"34":2796,"35":1917,"36":0,"37":1,"38":0,"39":1,"40":"%12%05%13%0C%04%0E","41":0,"42":0,"43":0,"44":0,"45":0,"46":1,"47":1,"48":1,"49":0,"54":15476384,"55":1,"56":0,"57":3927,"58":0,"59":0,"60":500,"61":2,"62":0,"63":0,"64":0,"69":1,"71":12,"72":19,"73":20,"74":0}, "settings":{"1":0,"2":1,"3":8,"4":0,"5":0,"6":1,"7":1,"8":1,"9":0,"10":0,"11":0,"12":0,"13":1,"14":0,"15":4,"16":0,"17":4,"18":1,"19":0,"20":0,"21":1,"22":0,"23":0,"24":0,"25":0,"26":4,"27":0,"28":4,"29":5,"30":0,"31":0,"32":3601,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":4,"40":0,"41":13,"42":8,"43":0,"44":8,"45":8,"46":0,"47":0,"48":0,"52":1,"54":1,"57":0,"58":1,"59":6,"60":8,"61":1,"62":2500000,"63":7,"64":4,"65":0,"66":0,"67":0,"68":0,"69":1,"70":0,"71":0,"73":0,"74":0,"75":3,"76":3,"78":1,"84":0,"85":0,"86":1,"87":40,"89":12,"91":0,"92":12,"95":1,"96":0}}
恕我直言,每次我使用Arduino时,它都会以某种方式让我的GoPro系统崩溃。还好我不是真正需要这个功能所以就说这么多了。
MAKER 趣无尽项目页面:http://make.quwj.com/project/65
via
发表评论