Archiv der Kategorie: Sony Camera
Sony Camera Remote Control mit ESP8266
Einleitung
Seit kurzem bin ich begeisterter Besitzer einer Sony DSC-HX90V. Für die Fernsteuerung dieser Kamera hat Sony eine WiFi Schnittstelle eingebaut und bietet eine App für Smartphones an, siehe PlayMemories. Leider gibt es keine weitere Schnittstelle (IR, elektrisch, Funk) um die Kamera remote zu bedienen.
Die Idee
Warum also sollte man die Kamera nicht über die WiFi Schnittstelle fernsteuern und damit gleichzeitig eine Schnittstelle per Mikrocontroller schaffen. Eine Realisierung einer WiFi Remote für eine GoPro wurde vor kurzem auf Hackaday vorgestellt. Eine Suche nach entsprechenden Programmen für Sony Kameras war ohne Erfolg. Auch die Sony Dokumentation der API brachte mich nicht weiter, da ich kein Android programmiere.
Über das ESP8266 Forum, fand ich zumindest Interessierte mit der gleichen Idee, aber keine Lösung.
Reverse Engineering zur Lösung
Durch Zufall stieß ich auf die TimeLapse App von Thibaud Michel.
Mit Hilfe eines WiFi PacketAnalysers habe ich mir auf dem Tablett das Protokoll näher angeschaut und dann mit der Sony Doku der APK verglichen.
Nach einiger Recherche fand ich heraus, dass es sich um ein einfaches HTTP POST Verfahren handelt mit der Übergabe der Parameter in einem json Format. Das nachzubilden mit dem ESP8266 war nur noch Fleißarbeit.
Proof of Concept
Die hier vorgestellte Lösung ist ein erster „Proof of Concept“ ohne jegliches Fehlerhandling und soll zunächst nur die Funktion des Schnittstelle darstellen. An einem ESP8266-01 ist lediglich ein Pushbutton zur Auslösung der Kamera angeschlossen der Rest ist Programm. Als Test wurde das Programm auf meinem Prototyp Board entwickelt. Auf diesem Board ist die 3,3V Stromversorgung und der FTDI zur Programmierung und zur Ausgabe von Debug Informationen fest verbunden. Der ESP8266 ist steckbar. Einzige zusätzliche Komponente ist der Pushbutton zur Fernauslösung der Kamera. Eine Beschreibung des Protoboards und die Einbindung der ESP8266 Libraries in die Arduino IDE findet sich hier. Die prinzipielle Verschaltung hier. Der Code ist ausführlich kommentiert und weicht nicht erheblich von den bekannten WiFiClient Codes ab, sollte also leicht verständlich sein. Auf eine Auswertung der json Antworten der Kamera wurde verzichtet.
//---------------------------------------------------------------------------------------------------------------------- // This program is based on: WiFiClient from ESP libraries // // Camera handling by Reinhard Nickels https://glaskugelsehen.wordpress.com/ // tested with DSC-HX90V, more about protocol in documentation of CameraRemoteAPI https://developer.sony.com/develop/cameras/ // // Licenced under the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) licence: // http://creativecommons.org/licenses/by-sa/3.0/ // // Requires Arduino IDE with esp8266 core: https://github.com/esp8266/Arduino install by boardmanager //---------------------------------------------------------------------------------------------------------------------- #include <ESP8266WiFi.h> #define DEBUG 1 #define BUTTON 2 // pushbutoon on GPIO2 volatile int counter; const char* ssid = "DIRECT-GKC2:DSC-HX90V"; const char* password = "5uv2LSwj"; // your WPA2 password const char* host = "192.168.122.1"; // fixed IP of camera const int httpPort = 8080; char JSON_1[] = "{\"version\":\"1.0\",\"id\":1,\"method\":\"getVersions\",\"params\":[]}"; char JSON_2[] = "{\"version\":\"1.0\",\"id\":1,\"method\":\"startRecMode\",\"params\":[]}"; char JSON_3[] = "{\"version\":\"1.0\",\"id\":1,\"method\":\"startLiveview\",\"params\":[]}"; char JSON_4[] = "{\"version\":\"1.0\",\"id\":1,\"method\":\"stopLiveview\",\"params\":[]}"; char JSON_5[] = "{\"version\":\"1.0\",\"id\":1,\"method\":\"actTakePicture\",\"params\":[]}"; // char JSON_6[]="{\"method\":\"getEvent\",\"params\":[true],\"id\":1,\"version\":\"1.0\"}"; unsigned long lastmillis; WiFiClient client; void setup() { Serial.begin(115200); delay(10); pinMode(BUTTON, INPUT_PULLUP); attachInterrupt(2, pulleddown, FALLING); // handled by interrupt to debounce // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { // wait for WiFi connection delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); delay(1000); httpPost(JSON_1); // initial connect to camera httpPost(JSON_2); // startRecMode httpPost(JSON_3); //startLiveview - in this mode change camera settings (skip to speedup operation) } void loop() { if (buttonpressed()){ Serial.println("pressed.."); httpPost(JSON_4); //stopLiveview (skip to speedup operation) httpPost(JSON_5); //actTakePicture httpPost(JSON_3); //startLiveview (skip to speedup operation) } } void httpPost(char* jString) { if (DEBUG) {Serial.print("Msg send: ");Serial.println(jString);} Serial.print("connecting to "); Serial.println(host); if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } else { Serial.print("connected to "); Serial.print(host); Serial.print(":"); Serial.println(httpPort); } // We now create a URI for the request String url = "/sony/camera/"; Serial.print("Requesting URL: "); Serial.println(url); // This will send the request to the server client.print(String("POST " + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n")); client.println("Content-Type: application/json"); client.print("Content-Length: "); client.println(strlen(jString)); // End of headers client.println(); // Request body client.println(jString); Serial.println("wait for data"); lastmillis = millis(); while (!client.available() && millis() - lastmillis < 8000) {} // wait 8s max for answer // Read all the lines of the reply from server and print them to Serial while (client.available()) { String line = client.readStringUntil('\r'); Serial.print(line); } Serial.println(); Serial.println("----closing connection----"); Serial.println(); client.stop(); } void pulleddown() // Interrupt handler { counter++; } boolean buttonpressed() { // function to check if pressed if (counter!=0) { counter=0; delay(10); // je nach Schalter if (counter==0 && !digitalRead(BUTTON)) return true; } return false; }
Bedienung
Für die Funktion muss auf der Kamera die aktuelle Version der Smart-Fernbedienung (das Gegenstück für die PlayMemories App) installiert sein.
Im Programm muss die SSID und das Passwort der benutzten Kamera eingetragen werden. Die Kamera wird nach dem Einschalten über das Menue in den Fernsteuermodus gebracht. Nach dem Einschalten des ESP8266 wird die Verbindung zur Kamera hergestellt und die Kamera wird in einen Modus versetzt, wo Einstellungen (Zoom, Blende, Zeit, …) möglich sind.
Ein Druck auf den Pushbutton löst die Kamera aus und die Kamera kehrt in den vorhergehenden Modus zurück.
Über die serielle Schnittstelle werden Debug Informationen ausgegeben, hier ein Beispiel nach dem Einschalten des ESP bis nach der ersten Fernauslösung der Kamera.
Connecting to DIRECT-GKC2:DSC-HX90V ....... WiFi connected IP address: 192.168.122.115 Msg send: {"version":"1.0","id":1,"method":"getVersions","params":[]} connecting to 192.168.122.1 connected to 192.168.122.1:8080 Requesting URL: /sony/camera/ wait for data HTTP/1.1 200 OK Connection: close Content-Length: 51 Content-Type: application/json {"result":[["1.0","1.1","1.2","1.3","1.4"]],"id":1} ----closing connection---- Msg send: {"version":"1.0","id":1,"method":"startRecMode","params":[]} connecting to 192.168.122.1 connected to 192.168.122.1:8080 Requesting URL: /sony/camera/ wait for data HTTP/1.1 200 OK Connection: close Content-Length: 21 Content-Type: application/json {"result":[0],"id":1} ----closing connection---- Msg send: {"version":"1.0","id":1,"method":"startLiveview","params":[]} connecting to 192.168.122.1 connected to 192.168.122.1:8080 Requesting URL: /sony/camera/ wait for data HTTP/1.1 200 OK Connection: close Content-Length: 75 Content-Type: application/json {"result":["http:\/\/192.168.122.1:8080\/liveview\/liveviewstream"],"id":1} ----closing connection---- pressed.. Msg send: {"version":"1.0","id":1,"method":"stopLiveview","params":[]} connecting to 192.168.122.1 connected to 192.168.122.1:8080 Requesting URL: /sony/camera/ wait for data HTTP/1.1 200 OK Connection: close Content-Length: 21 Content-Type: application/json {"result":[0],"id":1} ----closing connection---- Msg send: {"version":"1.0","id":1,"method":"actTakePicture","params":[]} connecting to 192.168.122.1 connected to 192.168.122.1:8080 Requesting URL: /sony/camera/ wait for data HTTP/1.1 200 OK Connection: close Content-Length: 108 Content-Type: application/json {"result":[["http:\/\/192.168.122.1:8080\/postview\/memory\/DCIM\/100MSDCF\/DSC01272.JPG?size=Scn"]],"id":1} ----closing connection---- Msg send: {"version":"1.0","id":1,"method":"startLiveview","params":[]} connecting to 192.168.122.1 connected to 192.168.122.1:8080 Requesting URL: /sony/camera/ wait for data HTTP/1.1 200 OK Connection: close Content-Length: 75 Content-Type: application/json {"result":["http:\/\/192.168.122.1:8080\/liveview\/liveviewstream"],"id":1} ----closing connection----
Video
Fazit und Ausblick
Dieser Blogeintrag beschreibt in einfacher Weise die grundsätzliche Funktion der WiFi Fernsteuerung einer Sony Kamera. Die Funktionsweise lässt sich zumindest auf die Kameras übertragen, die PlayMemories kompatibel sind. Möglicherweise ist dann die Serveradresse der Kamera zu modifizieren. Der Schritt zu komplexeren Lösungen ist reine Programmierarbeit. Ersetzt man den Pushbutton mit einer Zeitschleife kann man sehr einfach die Einzelbilder für TimeLapse Videos (Zeitraffer) aufnehmen. Die Auslösung kann natürlich auch durch Sensoren (Annäherung, Bewegung, …) erfolgen. Prinzipiell ist auch der Start und Stop einer Videoaufnahme (Kamera im Videomodus) möglich. Die entsprechenden json Kommandos sind in der Doku der APK enthalten. Wenn man auf den Modus „Liveview“ verzichtet ist die Auslöseverzögerung nur minimal (siehe Kommentar im Code, diese Zeilen dann auskommentieren), allerdings verliert man dann die Möglichkeit Kameraeinstellungen zu ändern. Für einen Batteriebetrieb ist der ESP8266 bekanntermaßen nicht so gut geeignet, aber für einen einzelnen Shot braucht es nicht viel Zeit. Für Timelapse Projekte wäre es sicher sinnvoll den Sleep Mode des ESP zu nutzen (was bei der Bauform ESP-01 nicht funktioniert ohne Modifikation). Ich würde hier das Modell ESP-12 empfehlen, das außerdem CE und FCC zertifiziert ist.