Arduino-based Camera Slider project

                        The Camera Slider Chronicles of 2020

Using the Rational Unified Process (RUP) project methodology, my challenge is to
design and create an Arduino-based multi-axis camera slider ultimately using Blynk.

Project Milestones -
Inception :heavy_check_mark:, Elaboration :heavy_check_mark:, Construction :heavy_check_mark:, Software Transition (in progress),
and Support. Check back now-and-then. Project iterations follow below.

No deadline - Ongoing low-priority project during the quarantine.
Low budget: - Arduino Zero board $38, Blynk App widgets $7, and HelTec ESP8266 OLED display $12.
                      Does not include any costs for the camera rail slider.


Looks good but I won’t vote on the concept alone… :wink:

Inception - Fresh off the completion of our last Arduino project, I decided to create an Arduino-based camera slider for our “quarentainment” (quarantine entertainment). I looked at all the $$$ ready-made solutions, some slider kits, DIY construction posts, and lots of videos. I found plenty of breadcrumbs leading down the rabbit hole; apparently I’m following in the footsteps of a lot of other people who have already done this before me. My own twist (or undoing!) will be to see if I can use Blynk to interface to it, like I did with my Arduino-based digital salt lamp remote control using Infrared, BlueTooth, and Wifi.

Elaboration - Would it be an expensive, ready-made unit, or a DIY (do it yourself) solution using off-the-shelf components readily sourced on the internet? Would it use servos, stepper-motors, or DC brushless motors? Would it use 3-D printed plastic parts, CNC routed parts, or just simple bolts, nuts, rails, and mounting plates? Would its motion be X-axis movement down the rail, or pan and tilt (Y and Z-axis) movement as well? Should I use an inexpensive off-the-shelf rail slider to speed up construction and add my own motors and electronics, or start from scratch and design that just for the experience?

X-axis control could be a heavy-duty stepper motor, and the Y & Z-axis (pan and tilt) could be two lighter-weight servo motors that draw less current. This first schematic is a starting point; Maybe I’m going to hack this to what I want to do ultimately with either IR, BlueTooth, or WiFi remote control via an iPhone App and ultimately Blynk. It’s designed to shoot 35mm stop-motion, 35mm slow-motion, or full-motion video. The first cut will be a single X-axis stepper on a Neewer slide rail just to get my feet wet.

Here is another schematic of a single-stepper unit already using an IR remote control:

Both have open-source Arduino sketches available to download.

Construction -
Iteration 1.0 - Meade telescope motor mounted to 100 cm length Neewer camera slider. Take an old Meade DS-60 telescope, cannibalize the azimuth motor, the handheld control, 12-volt cable plug-panel, and mount the motor to the Neewer frame at one end with duct-tape, and use parachute cord or clothesline rope as a timing belt to connect them. When running, the motor was very noisy, and the cord would fall off the rotating drive bolt sometimes, but it worked. Clumsy to use with the Meade handheld remote control. Inspired by this YouTube video: New Amsterdam Audio/Video


Iteration 1.1 - Neewer non-motorized camera slider with a TurnsPro time-lapse camera mount on a bracket (mounting kit supplied by them) on one end, and a pulley and bracket on the other end. The timing belt threads thru slots already cut in the slider leg mounts. Normally a TurnsPro is mounted on a tripod to do time-lapse, slow-motion, or stop-motion photography, but with their kit it mounts on a slider frame. This is a simple non-Arduino solution that provides for X-axis camera movement down the slider rail. Works great; powered by 4 AA batteries. Highly portable solution with no dangling wires to mess with. Turnspro is based in Plymouth, UK. See the website.
This video shows how to assemble their slider bracket kit: Turnspro Adapter Kit Setup.

Iteration 1.2 - Add two robotic servo motors to the trolley platform to provide Y and Z-axis rotation (pan and tilt). The TurnsPro moves the trolley down the slider, and the servos will pan and tilt controlled by an Arduino. The hobby servos and 3D-printed mounting bracket kit are sold many places on the Internet; cheap and easy to assemble. Typical usage is for robotics remote control. Unfortunately, they are not rigid enough to keep them from shaking while riding down the slider rail mounted to the trolley. Disadvantages include separate power required for the Turnspro and Arduino, and manually sequenced startup and stopping. I decided I won’t be using this configuration.

The 3 stepper-motor schematic configuration above uses a joystick, some push-buttons, and potentiometers. I didn’t want a whole lot of wires attached to the Arduino, so I ordered and received this Keyestudio JoyStick gaming shield that has most of what I need: Arduino Joystick Shield. Cheap, it’s only $5 US; this is just for testing and evaluation, not necessarily my final configuration. I have two slider rails here; this will be the electronics used with an Arduino to drive one of them:

If the Arduino sketch keeps track of the slider platform position properly, the movement limit switches are another item (and associated wires) that can be eliminated. NEMA17’s seem to be the stepper-motor of choice for most projects; they are easily sourced. I wanted to use lighter-weight servo-motors, but changed my mind after testing the plastic mountings. People also use brushless DC motors if they want to send position information back to the Arduino, but the sketch code has to be able to accept it. Final decision - NEMA17 motors.

This is the board I’m going to use for the second slider rail, a Devia Robotics control board. It can handle 4 servo-motors or 3 stepper-motors from the 12V power supply, has built-in ESP8266 Wifi, and looks like an Arduino Zero with a USB interface. Like all my hobbyist projects, I usually complete two different configurations to learn how they work and then give one to my brother for parallel testing:

There are plenty of DIY camera sliders that use custom 3D-printed or CNC-routed plastic parts; another design goal is to use as much off-the-shelf stuff as much as possible. The gears, pulleys, and timing belts are in abundant supply on the Internet because they are used for 3D-printers. Servos and steppers plug directly onto this board, and there are headers for the stepper-motor drivers already soldered on the board.

Construction -
Iteration 2.0 - X-axis (rail) motion. Removed the TurnsPro Time Lapse camera mount and bracket from the Neewer trolley, and left the pulley and bracket attached to the other end. Using a new separate NEMA17 mounting bracket, I attached it to the slider base plate, then attached the motor to the bracket using 4 supplied bracket screws. Next I dropped a pulley from an Amazon 3D-printer pulley kit onto the NEMA17 motor shaft, and secured the hex “grub” screws using the supplied Allen wrench. Finally, plugged the stepper-motor cable into the Arduino Zero header and plugged in the 12V 2A power plug. Pretty much a bare-naked slider and trolley now with an Arduino Zero in a crystal project case hanging out the rear, but it worked perfectly.

It’s really quiet with the timing belt almost free-floating. This is not a finished product by any longshot; it’s just for testing. The NEMA17 stepper motor pulled the slider trolley easily with my 35mm Canon PowerShot screwed into a Neewer camera mount. Finally, I shot test videos showing X-axis-only movement down the rail. That yellow sticky “flag” on the pulley is so I can see the pulley turning; the black timing belt blends with the slider frame 100% and renders it almost invisible.
Here are some video clips; right-click and hit start.
PowerShot SX260HS X-axis Demo, Camera Slider Hardware, and iPhone 5 X-axis Demo

1 Like

Construction -
Iteration 2.1 - Y-axis (pan) motion. Invert the pulley bracket 180 degrees on the slider rail end so the pulley is on top now for the timing belt. The belt has a straight shot to the trolley instead of going thru the slots in the end bracket for the TurnsPro camera mount. It’s even quieter with the timing belt not passing thru the bracket.
I removed the Neewer camera mount from the trolley. When I searched the Internet for NEMA17 pan/tilt mounts, the prices were so astronomical, I gave up for now. I cannibalized a pan mount from another slider and will figure out how to secure it to the Neewer slider; the bolts and holes don’t line up. I used two 1/4"-20 hex standoffs to raise the pan mount so the stepper would clear the camera mount on the trolley beneath it; see picture #2. The 3rd and 4th pictures show the slider trolley with its one big roving camera eye. “Cyclops” is ready.

The first video shows the trolley moving 400mm down the rail with the camera panning to keep the wine bottle (at 250mm down the rail and about 500mm away) in center-focus. It was carefully positioned to give a total solar eclipse of the wine stopper passing thru the sunlight. Success. The second video shows the clay pots again, but with a Y-axis camera pan this time.
See Camera Slider X-axis and Y-axis video - world globe map bottle.
See Camera Slider X-axis and Y-axis video - blue pot with stars

1 Like

Construction -
Iteration 2.2 - Z-axis (tilt) motion. Rather than just add a clone tilt mount on top of the pan mount, I want to spend some time cruising the Internet in the quest for a cheap pan/tilt mount that handles NEMA17 stepper-motors. I will revisit the Z-axis step at a later date. I’m going to jump ahead to the Software Iteration phase of the project and get started using Blynk to control everything.

Software Transition -
Iteration 3.0 - First, design a Blynk App to control the stepper-motor controller.
Here is my short-list of desirable features that would be great to implement:

App parameters :
Total rail length 20-1,023 mm start to stop.
X-axis length 20-1,023 mm (base to object)
Y-axis length 20-1,023 mm (rail-to-object)
Z-axis tilt 0-180 degrees
App sliders :
Delay time (15-1,023 seconds)
Rail speed (15-1,023 seconds)
App switches :
Object tracking (OFF/ON)
Delayed start (OFF/ON)
App controls :
Stepper data displayed :
Object Tracking – Arctangent of the object height to X-axis length ratio, in degrees.
Axis Tracking – stepper-motor X-Y-Z axis telemetry displayed on OLED readout.

Software Transition -
Iteration 3.1 - App completed, now finalize the conceptual breadboard design.

All the short-list desirable features were implemented in the Blynk App layout shown above running on my iPhone. The App transmits to the Blynk cloud server, and then back down to the HelTec ESP8266 Blynk message broker, and then ultimately to the Arduino Zero stepper-motor controller. The camera slider will in-turn respond to the command(s) and transmit positional axis location telemetry back to the OLED display in real-time.

Work in progress: testing to see if SPI can run on an Arduino Zero board that doesn’t have the usual SPI SS signal line used on other ESP8266 class Arduino boards like the NodeMCU, Wemos, and Adafruit Huzzah. Pin D12 is the only unused digital output pin, but it appears to be disabled, so I can’t use it as the SS line.

Next milestone: have succeeded in sending the positional telemetry information back to the HelTec ESP8266 executing Blynk. Final step will be to show the X & Y slider coordinates on the blue OLED display. Can the refresh rate on the display can keep up with the speed of the incoming telemetry data? If not, I may have to display every other line, every other forth line, or something else.

Telemetry data below shows a timestamp, X-position along the rail, Y-position from the rail to the tracking object, the arctangent angle of the Y & X coordinates, stepper Motor 1 speed, stepper Motor 2 speed, stepper Motor 3 speed and PAN angle.
You can see M1 is constant, while M2 is continually adjusted as the motor rides down the rail.
M3 and PAN angle will be zero until the 3rd stepper-motor is mounted to the trolley.

10:46:34.574 -> 
10:46:34.574 -> Blynk Online Message Broker (the BOMB)
10:46:34.608 -> Oasis Drive router
10:46:34.608 -> [261] Connecting to ATnT
10:46:37.635 -> [3304] Connected to WiFi
10:46:37.635 -> [3304] IP:
10:46:37.668 -> [3304] 
10:46:37.668 ->     ___  __          __
10:46:37.701 ->    / _ )/ /_ _____  / /__
10:46:37.735 ->   / _  / / // / _ \/  '_/
10:46:37.769 ->  /____/_/\_, /_//_/_/\_\
10:46:37.802 ->         /___/ v0.6.1 on NodeMCU
10:46:37.836 -> 
10:46:37.836 -> [3380] Connecting to
10:46:37.869 -> [3566] <[1D|00|01|00]
10:46:37.972 -> [3665] >[00|00|01|00|C8]
10:46:37.972 -> [3665] Ready (ping: 98ms).
10:46:38.007 -> [3665] Free RAM: 48568
10:46:38.041 -> [3732] <[11|00|02|00]Hver[00]0.6.1[00]h-beat[00]30[00]
10:46:38.176 -> [3845] >[00|00|02|00|C8]
10:46:38.210 -> [3846] <[14|00|03|00|09]vw[00]19[00]clr
10:46:38.243 -> [3913] <[14|00|04|00]Fvw[00]19[00]
10:46:38.344 -> [3990] <[14|00|05|00|1A]vw[00]19[00]2020-0524[0D|0A|0D|0A]
10:47:08.147 -> [33846] <[06|00|06|00|00]
(telemetry starts here ---)
10:47:26.717 -> PX:0.03 PY:30.94 A:30.96  M1:1590.50 M2:0.00 M3:0.00 PAN:0.00
10:47:26.784 -> PX:1.01 PY:30.91 A:30.88  M1:1590.50 M2:-59.36 M3:0.00 PAN:0.00
10:47:26.851 -> PX:1.99 PY:30.83 A:30.80  M1:1590.50 M2:-58.74 M3:0.00 PAN:0.00
10:47:26.918 -> PX:2.96 PY:30.77 A:30.72  M1:1590.50 M2:-58.83 M3:0.00 PAN:0.00
10:47:26.986 -> PX:3.94 PY:30.68 A:30.63  M1:1590.50 M2:-58.93 M3:0.00 PAN:0.00
10:47:27.053 -> PX:4.91 PY:30.60 A:30.55  M1:1590.50 M2:-59.01 M3:0.00 PAN:0.00
10:47:27.121 -> PX:5.89 PY:30.52 A:30.47  M1:1590.50 M2:-59.11 M3:0.00 PAN:0.00
10:47:27.188 -> PX:6.87 PY:30.43 A:30.38  M1:1590.50 M2:-59.97 M3:0.00 PAN:0.00
10:47:27.258 -> PX:7.85 PY:30.35 A:30.30  M1:1590.50 M2:-59.30 M3:0.00 PAN:0.00
10:47:27.326 -> PX:8.82 PY:30.26 A:30.22  M1:1590.50 M2:-59.40 M3:0.00 PAN:0.00
10:47:27.395 -> PX:9.80 PY:30.18 A:30.13  M1:1590.50 M2:-59.50 M3:0.00 PAN:0.00
10:47:27.462 -> PX:10.77 PY:30.09 A:30.05  M1:1590.50 M2:-59.60 M3:0.00 PAN:0.00
10:47:27.532 -> PX:11.76 PY:30.01 A:29.97  M1:1590.50 M2:-59.70 M3:0.00 PAN:0.00
10:47:27.599 -> PX:12.74 PY:29.93 A:29.88  M1:1590.50 M2:-60.60 M3:0.00 PAN:0.00
10:47:27.668 -> PX:13.71 PY:29.84 A:29.80  M1:1590.50 M2:-59.93 M3:0.00 PAN:0.00
10:47:27.734 -> PX:14.74 PY:29.73 A:29.71  M1:1590.50 M2:-59.59 M3:0.00 PAN:0.00
10:47:27.802 -> PX:16.09 PY:29.62 A:29.59  M1:1590.50 M2:-60.60 M3:0.00 PAN:0.00
10:47:27.870 -> PX:17.42 PY:29.50 A:29.48  M1:1590.50 M2:-60.19 M3:0.00 PAN:0.00
10:47:27.937 -> PX:18.76 PY:29.39 A:29.36  M1:1590.50 M2:-60.80 M3:0.00 PAN:0.00
10:47:28.004 -> PX:20.11 PY:29.28 A:29.24  M1:1590.50 M2:-60.40 M3:0.00 PAN:0.00

Sample 3-line output on the OLED display:

When I add the statement #include “heltec.h” to the Arduino “BOMB” sketch, it still
starts up and executes fine. But when I attempt to execute an OLED call to
Heltec.display->clear();, the serial monitor log contains “gibberish” endlessly repeating this exception error sequence over and over again:

08:40:32.661 -> Exception (29):
08:40:32.694 -> epc1=0x4000e1b2 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
08:40:32.763 -> 
08:40:32.763 -> >>>stack>>>
08:40:32.797 -> 
08:40:32.797 -> ctx: cont
08:40:32.797 -> sp: 3ffffd90 end: 3fffffc0 offset: 01a0
08:40:32.831 -> 3fffff30:  3fffdad0 3ffeef8c 00002580 402029c9  
08:40:32.898 -> 3fffff40:  00000040 00000000 feefeffe feefeffe  
08:40:32.932 -> 3fffff50:  feefeffe feefeffe feefeffe feefeffe  
08:40:33.000 -> 3fffff60:  feefeffe feefeffe feefeffe feefeffe  
08:40:33.034 -> 3fffff70:  feefeffe feefeffe feefeffe feefeffe  
08:40:33.100 -> 3fffff80:  feefeffe feefeffe feefeffe feefeffe  
08:40:33.134 -> 3fffff90:  feefeffe feefeffe feefeffe 3ffef0b8  
08:40:33.203 -> 3fffffa0:  3fffdad0 00000000 3ffef078 40206198  
08:40:33.237 -> 3fffffb0:  feefeffe feefeffe 3ffe84fc 40101591  
08:40:33.306 -> <<<stack<<<

There is some apparent code collision between the Blynk code and the HelTec OLED code. HelTec responded to my inquiry immediately; I will let them see what they can find, and will just concentrate on finishing off the App.

What does your exception decoder say?
Is there any chance that it’s a power supply issue?


Hey, Pete, thanks for looking. The HelTec board runs fine running my Blynk code, and the OLED display runs fine standalone using the standard ESP8266 library instead of the BlynkESP8266 library, so I am not suspecting a power supply issue right now. I really like their OLED display over the standard Arduino 16X2 LCD display and want to try it. HelTec gave me a direct contact to work with at their factory; they were extremely responsive to my inquiry.

Exception 29 is well-documented on the Internet: ESP8266 Exception 29.
Exception 29 is ‘storeprohibitedcause,’ meaning that code tried to write to a protected area in memory. The value given for excvaddr shows the virtual memory address that caused the exception.
I also saw suggestions that it was caused by unstable power. I’m not suspecting this.

Update: appears to be fixed now. Changed the order of initialization of the OLED code libraries and Blynk code libraries in memory, and downloaded the latest version of <heltec.h>.
Back on track again …

1 Like