360°–Fotos setzen deinen Ort in ein neues Licht. Ich zeige dir, eine 360°-Kamerahalterung für deine GoPro selber baust und damit Rundumaufnahmen von deinem Lieblingsort macht. Du benötigst hierfür keine professionelle 360°–Kamera.
Inhalt
360°-Fotografie
Auch mit einer normalen GoPro und letzlich jeder anderen Kamera kann man eine 360°-Aufnahme erstellen. Um eine Aufnahme zu erstellen werden Fotos in alle Himmelrichtungen gemacht und anschließend zu einem 360°-Foto zusammengesetzt. Eine GoPro bietet hier den Vorteil einer Fischaugenlinse. Durch den starken Weitwinkel müssen weniger Fotos für eine 360°-Aufnahme gemacht werden. Das spart Zeit.
Da das Fotografieren sehr aufwendig ist, habe ich inspiriert durch Pixelmagic und seiner Full automatic 360° panorama V2 GoPro Halterung eine eigene Version seiner 360°–Kamerahalterung für die GoPro Hero 7 designed und programmiert.
Anleitung
!!Die Folgenden Links sind die Shops bei denen ich die Materialien gekauft habe oder dienen als Beispiel für die verwendeten Produkte. Ich erhalte keinerlei Provision oder sonstigen Gegenwert!!
Materialien
- 3D-Druck Teile von Printables: Die Stativhalterung ist optional. Sie kann bei Bedarf einfach an die Elektronikbox gesteckt werden. Achtung: Offenbar variieren die Abmessungen der Platinen bei NodeMCU und Treiberplatine. Bearbeitbare .step-Dateien der Box sind daher ebenfalls auf Printables verfügbar.
- NodeMCU ESP8266 WiFi-Modul
- Schrittmotor 28BYJ-48 mit ULN2003 Treiberplatine
- Microservo
- einige Kabel zum Beispiel Breadboardkabel
- Microtaster
- USB to Micro USB Kabel
- 3x Schraube 3mm Durchmesser
Funktion der 360 Grad Kamerahalterung
Die Kamerahalterung wird von einem von einem ESP8266 Mikrocontroller auf einem NodeMCU-Board gesteuert. Der Mikrocontroller steuert zum Einen Schrittmotor und Servo, zum Anderen sendet der ESP8266 Befehle per WLAN an die Kamera.
Die Fotos der Kamera werden dann in einem zweiten Arbeitsschritt gestitcht, also zusammengesetzt.

Leider verliert die GoPro oder der Mikrocontroller nach einem 360°-Foto die WLAN-Verbindung und der Akku muss aus der GoPro entfernt und wieder eingesetzt werden. Ich konnte diesen Fehler bisher nicht lösen. Wenn ihr wisst, wo das Problem liegt, schreibt es gerne in die Kommentare!
Zusammenbau
Der Anschluss des Steppermoduls und des Servos erfolgt nach den Anschlusstabellen. Außerdem habe ich an Pin D7 und GND der Taster angeschlossen. Dieser kann im Gehäuse zum Beispiel mit Heißkleber verklebt werden. Er dient zum Starten einer 360°-Aufnahme. Abschließend wird die Elektronik in das Gehäuse eingesetzt und Servo und Schrittmotor können in den Halterungen montiert werden. Den Schrittmotor habe ich mit zwei der Schrauben befestigt. Eine weitere Schraube wird gegenüber des Servos als Befestigung der GoPro Halterung eingedreht (siehe Fotos).
Pin (NodeMcu) | Pin (Steppermodul) |
D5 | IN1 |
D3 | IN2 |
D2 | IN3 |
D1 | IN4 |
GND | GND |
3V3 | VCC |
Pin (NodeMcu) | Kabel (Servo) |
D4 | oranges Kabel |
3V3 | rotes Kabel |
GND | braunes Kabel |
Fotos
Kommunikation zwischen ESP8266 und GoPro
Die GoPro und der ESP8266 kommunizieren über WLAN miteinander. Der Microcontroller versucht sich nach dem Einschalten mit dem WLAN der GoPro zu verbinden.
Dazu habe ich zuvor die SSID, also den Namen des Netzwerks und das Password aus dem GoPro Menü ausgelesen. SSID und Password müssen im Programmcode für YOURSSID und YOURPASSWORD eingesetzt werden.
//USER BEGIN
const char *ssid = "YOURSSID"; //GoPro Wifi name (SSID)
const char *password = "YOURPASSWORD"; //GoPro WiFi password
const int photosPerTurn = 10; //Fotos pro Umdrehung
const int turnsPerPhoto = 3; //Anzahl der Fotos in Y-Richtung
//USEREND
Ist die Verbindung mit der GoPro erfolgreich erlischt die eingebaute Led des Boards und mit Betätgung des Tasters and Pin D7 wird eine Aufnahme gestartet.
Wenn SSID und Password auf deine GoPro angepasst sind, kann jetzt der Code mit der Arduino IDE oder PlatformIO auf den Arduino geflasht werden.
Denke daran, das verwendete Board in der Arduino IDE, als auch in PlatformIO auf NodeMCU mit ESP8266 anpassen musst. Ansonst kann der Code nicht geflashed werden. In der Arduino IDE kannst du über Werkzeuge->Board->ESP8266 Board das NodeMCU auswählen.
Code
Dieses Skript habe ich mit einer GoPro Hero 7 Black getested. Bei anderen GoPro-Modellen muss unter Umständen das Protokoll zum Ansprechen der GoPro über WLAN abgeändert werden. Das Protokoll zur Kommunikation mit vielen GoPro-Modellen über WLAN findet sich im Github-Repository von KonradIT.
#include <Arduino.h>
#include <Servo.h>
#include <Stepper.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <WakeOnLan.h>
//USER BEGIN
const char *ssid = "YOURSSID"; //GoPro Wifi name (SSID)
const char *password = "YOURPASSWORD"; //GoPro WiFi password
const int photosPerTurn = 10; //Fotos pro Umdrehung
const int turnsPerPhoto = 3; //Anzahl der Fotos in Y-Richtung
//USEREND
WiFiClient client;
const char *host = "10.5.5.9";
const int httpPort = 80;
//Wake on Lan
WiFiUDP UDP;
WakeOnLan WOL(UDP);
IPAddress broadcastAdress = IPAddress(255, 255, 255, 0);
//Konstanten
const int delaylonger = 1200; //Zeit, die auf das Ausführen der Einstellung gewartet werden soll
const int delaypos = 1000; //Zeit für die neue Position
const int delayPhoto = 3100;
const int stepperSpeed = 10; //wichtig zur Berechnung der Wartezeit
//Servo
Servo servo1;
//Stepper
const int SPU = 2048;
Stepper step(SPU, D1, D3, D2, D5);
//Leds_Taster
const int led = D0;
const int start = D7;
//methods
void trigger();
void setPhotoMode();
void setPhotoWide();
void wakeUp();
void setup()
{
Serial.begin(9600);
pinMode(led, OUTPUT);
pinMode(start, INPUT_PULLUP);
servo1.attach(D4);
servo1.write(150); //fahre in Grundposition
step.setSpeed(stepperSpeed);
//wifi
WOL.setBroadcastAddress(broadcastAdress); //Wake on Lan
delay(100);
bool ledStatus = true;
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// wait for wifi to connect
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
digitalWrite(led, ledStatus);
ledStatus = !ledStatus;
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
//settings
setPhotoMode();
setPhotoWide();
ledStatus = true;
digitalWrite(led, ledStatus); //schalte status led aus
}
void loop()
{
if (!digitalRead(start))
{
digitalWrite(led, LOW);
delay(1000);
digitalWrite(led, HIGH);
for (int j = 0; j < turnsPerPhoto; j++)
{
int servoPos = 180 - (j * 180 / (turnsPerPhoto - 1));
servo1.write(servoPos); //teilt die Schritte des Servos in die Lagen auf
delay(delaypos); //warte auf den Servo
for (int i = 0; i < photosPerTurn; i++)
{
if (j % 2 == 0)
step.step(SPU / photosPerTurn);
else
step.step(-(SPU / photosPerTurn));
delay(60 / stepperSpeed / photosPerTurn + 100);
trigger();
delay(delayPhoto);
}
}
if (turnsPerPhoto % 2 == 1)
{
for (int i = 0; i < 3; i++)
{
//step.step(-682); //wenn ungerade anzahl fotos drehe zurück
step.step(-SPU/4); //wenn ungerade anzahl fotos drehe zurück
delay(60 / stepperSpeed / photosPerTurn + 100);
}
}
}
}
void trigger()//make a photo
{
if (!client.connect(host, httpPort))
{
Serial.println("connection failed");
return;
}
String url = "/gp/gpControl/command/shutter?p=1";
Serial.println(" Click !");
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
delay(delaylonger);
}
void setPhotoMode()
{
if (!client.connect(host, httpPort))
{
Serial.println("connection failed");
return;
}
String url = "/gp/gpControl/command/mode?p=1";
Serial.println(" Click !");
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
delay(delaylonger);
}
void setPhotoWide()
{
if (!client.connect(host, httpPort))
{
Serial.println("connection failed");
return;
}
String url = "/gp/gpControl/setting/17/0";
Serial.println(" Click !");
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
delay(delaylonger);
}
void wakeUp()
{
const char *MACAddress = "06:41:69:B4:47:F1";
WOL.sendMagicPacket(MACAddress); // Send Wake On Lan packet with the above MAC address. Default to port 9.
// WOL.sendMagicPacket(MACAddress, 7); // Change the port number
}
Zusammenfassung
Du kannst nun mit der 360°-Kamerahalterung einfach Aufnahmen in alle Himmelsrichtungen machen. Diese Bilder können anschließend mit einem Stichingprogramm zum Beispiel Hugin zu einer eigenen 360°-Aufnahme zusammengefügt werden.
Wenn dir all das zu kompliziert ist, dann könnte die Google Street View App etwas für dich sein. Mit dieser kannst du ganz bequem mit deinem Handy 360°-Aufnahmen machen und herunterladen. Du findest den Beitrag dazu hier.
Weitere Projekte
- Let it snow – Winterlandschaft in einer LaterneBegonnen hat dieses Projekt in einem Dekomarkt. Die Laterne, die es hier zu kaufen gab, inspirierte mich: In dieser Laterne sollte eine Winterlandschaft entstehen sodass man selbst liebend gern in den Schnee springt.
- Solax X3 Hybrid G4 API in Home Assistant einbindenDie Integration der PV-Anlage in Home Assistant bringt neue Möglichkeiten.… Solax X3 Hybrid G4 API in Home Assistant einbinden weiterlesen
Ich bin auf der Suche nach Beispielen für die Ansteuerung der Gopro7 auf diese Seite gestoßen. Da ich alle Teile in meiner Grabbelkiste habe, habe ich die kleine Maschine gedruckt und zusammengebaut. Leider passen die gedruckten Teile mit meiner NodeMCU und ULN2003 nicht zusammen, ein paar Millimeter zu wenig für die MCU und ein Millimeter zu viel für die ULN2003.
Aber ich habe den Fehler in deinem Programm gefunden:
Beim Zurückdrehen des Steppers wird zu viel gedreht.
Folgende Änderung funktioniert:
step.step(-SPU/4); //wenn ungerade anzahl fotos drehe zurück
delay(60 / stepperSpeed / photosPerTurn + 100);
Viele Grüße
Hallo Matrin,
vielen Dank für das Feedback. Ich habe die stl-Dateien für die Box jetzt auch als step-Dateien auf Printables veröffentlicht. Ich hoffe, das hilft dir die Box auf dein Boardformat anzupassen und Danke für die Tipps zum Code:)
Viele Grüße
Lennart