An automated camera head for detailed landscape panoramas - with encoder-controlled positioning, Android and Windows clients, and position data for your stitching workflow.
Explore the panorama gallery · Software and documentation · Hardware designs
A long lens can reveal remarkable detail in a landscape, but covering a wide view takes many overlapping photographs. This project automates the positioning and triggering needed to capture those image sequences.
The camera head moves through a planned grid or a sequence of spherical bands. Absolute encoders measure the pan and tilt positions, while the controller handles movement, settling checks and shutter timing. The photographs remain on the camera and are stitched separately.
I develop the mechanics, electronics and software together, using landscape photography as the practical test. The design files, firmware and applications are available on GitHub for anyone interested in building, adapting or improving the system.
I started panorama photography with my first digital camera in 2003 and soon discovered the limitations of shooting handheld. Capturing a large panorama is tedious, and at longer focal lengths it is easy to miss a frame and leave gaps. A panoramic tripod head makes the process much more reliable. Manual operation works well for smaller sequences, but for multi-row gigapixel panoramas containing hundreds or thousands of images, automation becomes increasingly useful.
In 2008, I built my first RC-servo-based platform. Controlled by a Conrad C-Control board, it was reasonably fast at about four seconds per image. Its main weakness was mechanical stability. Large overlaps helped compensate for positioning errors, but mechanical problems still occasionally caused entire columns to be missed.
Looking for a sturdier solution, I bought an Orion/Merlin tracking mount, which other panorama photographers were also using. It was very stable and could be controlled over Bluetooth from a phone or netbook. On mountain hikes, however, its weight became a drawback. It had also been designed for astronomical tracking, where precision matters more than speed. The fastest acquisition rate I could achieve was about seven seconds per image. I tried writing custom control software to improve this, but eventually found that the speed restrictions were embedded too deeply in the controller firmware.
My next experiment used a stepper motor to drive the pan axis directly. The concept worked, but the motor consumed considerable power and had to remain energized to hold its position. Without microstepping, positioning was also rather coarse. The weight of the motor and the batteries it required prompted another rethink.
I returned to RC servos for their low weight, modest power consumption and fast movement. Their geared drives also offered some resistance to movement when unpowered. Around the same time, I was experimenting with Arduino boards and discovered Phil Warner’s PanoDuino, an Arduino-controlled panoramic head. Phil’s design used ServoCity gearboxes to create a stable pan/tilt platform. I adopted this mechanical approach for my own setup.
To improve both positioning and the stitching workflow, I added absolute rotary encoders to the pan and tilt axes. At each shutter release, the measured yaw and pitch angles are recorded in a Papywizard file. PTGui can use these positions for the initial image arrangement, giving the stitching process a useful starting point.
The encoders also provide 14-bit position feedback for closed-loop motor control. I disconnected the servo motors from their internal controllers and connected them to an external H-bridge driver. A PID control loop in the Arduino firmware then adjusts motor output using the measured axis positions.
To simplify the wiring and reduce the size of the controller enclosure, I brought the electronics together on a custom PCB: PanoBoard. It integrates the Arduino controller, H-bridge motor driver, Bluetooth interface and camera-trigger circuitry.
On this site, you will find:
Hardware designs and control software for an automated pan/tilt head capable of carrying a Sony A7R V with a 400 mm telephoto lens.
A practical acquisition and stitching workflow developed for high-resolution landscape panoramas.
The current software development target combines an Arduino Nano R4, absolute angle encoders (AS5048B) and the PanoBoard electronics with a compatible motorized pan/tilt mechanism. An Android phone or a Windows computer (e.g. a Surface Go) provides planning and control over Bluetooth.
After a plan has been transferred and explicitly started, the firmware runs the movement and capture sequence on the head. The client displays progress and records capture information.
Plan the coverage before shooting. Choose a camera/lens profile, focal length, overlap and timing, then inspect a graphical preview.
Capture grids or spherical bands. Use columns and rows for landscape panoramas, or bands with different numbers of pan positions. Available coverage depends on the head's actual movement limits.
Measure the position. Encoder feedback supports closed-loop motion control and records measured capture positions for the stitching workflow.
Run the sequence on the controller. Movement, settling checks and triggering are handled by the firmware after loading and starting the plan.
Recover interrupted acquisitions on Android. Prepare a continuation from a selected grid column or an original spherical band, with the option to repeat coverage.
Retain position records during acquisition on Android. A persistent capture archive and complete Papywizard XML snapshots support export after an interruption or app restart.
Keep manual control available. Target moves, held-arrow jogging, pause/resume, column navigation and timelapse complement the planned acquisition modes.
Prepare the head and camera. Balance the camera/lens combination, check the reference and movement limits, and select camera settings and capture timing appropriate for the scene.
Connect one client. Pair the Bluetooth connection and use either the Android app or the Windows application.
Frame and plan. Set the coverage, camera profile, overlap and timing. Review the preview before moving through the sequence.
Load, then start. Wait for the head to confirm the loaded plan. Start the acquisition separately and monitor progress, measured positions and warnings.
Export and stitch. Transfer the camera images to the stitching computer and export the position records. Use them in your external stitching workflow, such as PTGui.
The short English manual explains connection, planning, capture, recovery and export.
Both clients support panorama planning, manual movement and acquisition control. They are alternative controllers for the same head; use one at a time.
Android currently has the more complete interruption-recovery workflow. After resolving a fault, you can prepare a remaining job from the affected or an earlier grid column. Spherical recovery retains the original bands and can repeat an earlier band. Load and start the continuation explicitly; earlier captures remain in the linked archive.
An unresolved sensor fault, changed reference or other invalid device state can still prevent movement. Recovery resumes work after the cause has been addressed.
The Windows client supports normal pause/resume, but does not yet offer the same recovery workflow or continuous complete-XML output as Android. See the feature matrix for the current differences.
Android requires Android 8.0 or newer. The Windows application requires .NET Framework 4.8. Source code and build instructions are linked below.
The Android app archives capture information in SQLite and updates complete Papywizard XML snapshots in the background during acquisition. Each published snapshot is a closed XML document; a new snapshot replaces the previous file atomically. After restarting the app, the XML can also be rebuilt from the capture archive.
You can therefore export useful position data from a partial run. Check the backup status or export again after an interruption, then copy the result to the stitching computer. Background snapshots can lag the most recent archived capture, and files stored only on the phone are not an independent backup.
On Windows, use the journal-snapshot export for interrupted runs; the classic live XML writer closes its document at normal completion.
The recorded events describe electrical shutter triggers and capture positions. They do not confirm that the camera saved an image or that the photograph is sharp. When repeating a column or band, account for the additional camera files when preparing the stitching project.
PanoBoard brings the controller, motor drivers, Bluetooth connection and camera-trigger circuitry together. Match the wiring, supply and camera interface to the board revision you actually build.
For an existing PanoBoard V5, the Nano R4 conversion guide documents the required resistor changes, encoder-bus pull-ups, power connections and firmware considerations.
The V5 KiCad files still describe the original assembly. The Nano R4 guide documents the changes to apply to that board. Read it before assembling or converting an R4 controller. Camera-trigger compatibility depends on the circuit and camera; older examples on this site do not establish compatibility with every PanoBoard revision.
Start with PanoramaSoftware for an overview, the Android app and the system documentation. Firmware, Windows software and hardware remain in their own repositories.
PanoramaSoftware
Project overview, Android app, system documentation and links to the other components
PanoDuinoControl
Controller firmware and motion/acquisition logic
PanoramaControl
Windows planning and control application
PanoBoard
Electronics designs and Nano R4 conversion guide
Gigapixel-Tools
Separate utilities for vignetting correction and arranging image tiles in PTGui projects
Short English manual · Deutscher Einstieg · Ausführliche deutsche Dokumentation
GitHub contains the maintained build instructions, component versions, feature status and known limitations. License information is provided in each repository; license coverage and third-party notices explain the software components.
Work continues on recovery under real field conditions and on bringing the newer Android recovery and export behavior to Windows. Camera balance, mechanical play, supply conditions and wind affect the physical result. No universal acquisition-speed or field-failure-rate guarantee is claimed.
Spherical planning remains limited by the head's mechanical travel; it does not guarantee complete zenith and nadir coverage. Image transfer, stitching and verification of saved camera files are separate steps.
See the known limitations and roadmap for details and the latest development status.
The earlier builds explain how the current system developed. They remain useful background, but their component lists and operating instructions belong to those specific versions.
The first designs explored different ways to automate a lightweight camera platform. The early PanoDuino setup used an Arduino Mega and a Pololu servo controller.
Later builds introduced absolute encoders, external motor drivers and closed-loop positioning. The electronics subsequently moved onto custom PanoBoard revisions.
Explore the panorama gallery to see the photographic results.
The separate acquisition and stitching workflow describes my photographic processing approach. It includes examples from earlier setups and software versions; use the GitHub manual for current head-control instructions.
Closed Loop Servo position control using 14-bit rotary encoders
Output of positional data (papywizard format) for use in PTGUI or Autopano Giga
Added support for the Sony A7R V full-frame mirrorless camera
Camera mounted on an adjustable Macro Focusing Rail
Open-source software for gigapixel panorama acquisition - PanoramaControl https://github.com/TomNaiser/PanoramaControl/
Arduino code driving the panorama hardware - PanoduinoControl https://github.com/TomNaiser/PanoDuinoControl
Electronics cleanup - everything is now mounted on an integrated PCB - github.com/TomNaiser/PanoBoard
Angle Piece (3D printed)
Terminal Block (2x) (3D printed)
Aluminum Tube 12mmx225 mm (2x) - horizontal beams
Aluminum Tube 12mmx198 mm (2x) - vertical beams
ServoCity Top-Mount Servo Gearbox (5:1) (2x)
RC-Servo HiTec HS-785HB (2x) - Hacked: control via external H-Bridge & PID position control on Arduino
Rotary Encoder AMS5048B (14 bit) on TSSOP-14 Board (2x) + adapter-boards for I2C cable connection
Bubble Level
Camera Mounting Plate
Macro Focusing Rail (for adjustment of camera position)
Tripod Adapter (3D printed)
Controller Box (3D printed)
Arduino Mega 2560 + Velleman Shield KA03 (Motor and Power)
Various 3D printed parts for camera alignment, vibration damping etc.
If you don't want to build the mechanics you possibly can use a commercial approach:
ServoCity is offering ready-made Pan&Tilt Kits. I have neither seen nor tested such a setup, but I guess they should work fine.
You can add your own servo-controller and write a more or less advanced software for panorama acquisition, or you can do that based on my controller hardware and software. Of course you would have to do a few adaptions (e.g. disable the servos internal position control) to get the system running fine.
Depending on how precise the mechanics is, you possibly don't have to implement an encoder-based PID control. This will make things a lot easier.
I must admit, the previous electronics was a mess. An Arduino Mega board with a Motor Shield on top, voltage converters boards, a long range bluetooth module, several small boards (for remote shutter control) and a lot of wires. Everything in a box that was much larger than necessary.
Recently I learned that AISLER makes very affordable custom circuit boards for hobbyists, and so I created the PanoBoard, which integrates most of the above components on one board.
Features of the PanoBoard:
Arduino Nano
SparkFun BlueSMiRF Gold modem for wireless communication with notebook
Integrated H-Bridge motor driver
Remote shutter for Sony A7r II and Panasonic FZ200 (with some basics electronics knowledge you should be able to extend this to other remote shutter capable cameras)
Design files (in Eagle format) can be downloaded from my PanoBoard Github repository: github.com/TomNaiser/PanoBoard
PanoBoardV4 (April 2019) - Eagle Schematics. A parts list can be downloaded from GitHub. Warning! The provided circuit design may contain unintentional mistakes. I don't take any responsibility for damages caused by using the above circuit design . Please use the provided information at your own risk!
PanoBoardV4 (April 2019) Board Layout
Actually there is the newer CarrierBoardV5. A patch allows using an Arduino Nano R4
PanoBoardV3 in the controller box. With an arduino nano clone, a BlueSMiRF Gold module, and a voltage converter (12V -> 7.5 V) at the bottom.
Soon to come: The latest version of the PanoBoard got more compact.
Above I have given a description of my motorized panorama head. Just as important is the software!
Over the last ten years I have developed hardware and software in parallel. When I go to the mountains for panorama photography, I often come back with new ideas for improved panorama acquisition and processing.
The source code of PanoramaControl can be downloaded from Github: https://github.com/TomNaiser/PanoramaControl
PanoramaControl is tailored for ease of use, with a focus on the acquisition of gigapixel panoramas comprising thousands of single shots
configuration of stitching parameters for various cameras and camera/lens-combinations (e.g. Sony A7 with various lenses, Lumix FZ200, Lumix FZ28)
adjustable timing, overlap parameters
configuration (new cameras etc.) can be set in PanoControlConfig.xml
enter start- and end-positions for panorama acquisition
automated remote trigger via the Sony multi-terminal (works for the A7 RII and more recent cameras like the A7 RV)
start/stop/pause acquisition
timelapse mode
recording of exact shoot positions (based on position encoder readings) for import to professional stitching software
wireless communication with microcontroller-based panorama head
can be extended to various acquisition modes (default: flat panorama for large gigapixel panoramas) . I didn't care much about spherical panoramas (not very well implemented yet), but a proper implementation shouldn't be too difficult.
Continue with the Gigapixel Acquisition and Stitching Workflow
Inspired by Phil's Panoduino concept and by the possibilities offered by my (then) new Thing-o-Matic 3D printer, I started the construction of my own Panoduino platform.
An Arduino Mega 2560 is mainly used as a communications relay. It connects the bluetooth-to-serial module with the Pololu micro serial servo controller and it provides the remote shutter signal for operating my Canon Power Shot G9 (via USB - CHDK remote shutter). Actually, using the Mega2560 is overkill (a small Arduino Nano is powerful enough), but its comfortable as it fits the standard arduino shields. The system can easily be extended - e.g. with a motor controller, blue tooth, encoders, camera remote triggers.
My panorama acquisition software PanoramaControl is written in C#. It features the selection of camera parameters (focal length etc.), number of rows/columns, navigation via mouse click, setting of start and end point. It sends commands (e.g. the raw commands for the pololu servo controller , or command for the remote shutter) the arduino controller. Communication between the netbook and the arduino is achieved via bluetooth - which is basically handled as a normal COM-Port.
With Panoduino #1 I use a Canon Powershot G9 with a 2x teleconverter. The remote shutter is operated via the cameras USB port. For this purpose the camera has to be run with CHDK (the Canon Hack Development Kit).
For panorama acquisition I use the Manual Mode of the camera. The focus is normally adjusted manually to infinity (in this case I use only one trigger pulse with a length of about 40 ms).
Another option is to use the manual mode and the with the safety focus enabled (in the cameras main menu). In this case the camera can adjust the focus within a small range around the manual setting. This requires two pulses - one for focusing and one for triggering the shutter.
Electronics of Panoduino #1: RC-Servos controlled by a Pololu Maestro servo driver.
A minigorilla mobile power supply is light, has a high battery capacity of 9000 mAh, provides large enough currents 3A max. and displays the battery status.
A UBEC (Battery Elimination Circuit) provides enough power (at 5V) for the servos (thus preventing jitter at large loads), and prevents unnecessary power consumption.
The pololu micro maestro servo controller provides smooth (accelerated) servo motion, serial communication via one of the Arduino Megas UARTs.
An accelerometer (LSM303) continuously measures the motion state of the platform. It is directly mounted on the camera support, thus sensing any motion, vibration etc. The sensor tells when the camera has completely finished the motion - only then the shutter is released. This is faster than fixed settling times. So far I have achieved to take about 40 to 45 images per minute, higher rates might well be feasible. Communication is via I2C.
Bluetooth module: I use an extented range bluetooth module F2M03GXA (which I previously used on my quadcopter for telemetry purposes). However, a standard Arduino bluetooth shield should do equally well. Using the interface is simple: On the Arduinos side it is connected to a serial ports and the Netbook also sees a serial port (which can easily be accessed from .NET programs).
New camera: The Lumix FZ200 superzoom camera provides a (35 mm equiv. ) focal length of 600 mm (at f/2.8), and has 12fps (continuous shooting).
Remote shutter control circuit:
For the Lumix FZ200 (and some other Lumixes) this works well:
http://www.robotroom.com/Macro-Photography-2.html
Instead of mechanical switches I use optocouplers as described here: http://authenticinvention.com/authentic/?p=69
If you want to use a Canon Powershot you can install the CHDK firmware (it is installed on the SD-Card and thus considered to be reversible) and use the cameras USB-Port for triggering the shutter:
http://chdk.wikia.com/wiki/USB_Remote
Control-Software - new features: "Pause" - if somebody is walking by right in front of the camera, "one column back" to repeat the previous column.
The following photos show the outdated setup with the Canon Powershot G9, and a heavy NiMH battery pack.