Part 1.3 – Joystick control ain’t for the faint of heart.

Now we know how to walk, we can certainly try running. And by running we mean continously adjusting movement speed.

…in the wilds of Borneo and the vineyards of Bordeaux,
Eskimo, Arapaho, move their body to and fro.

1979 © Ian Dury, Hit Me With Your Rhythm Stick

Now we know how to walk, we can certainly try running. And by running we mean continously adjusting movement speed. Of course some chips will get smoked, some fingers burned and we will see our newfound confidence destroyed.

Last time we made the darn thing move. And although that did warm our hearts, this success is only a small step towards making things work. We did, from the get go, decide to build this not only as a replacement for the Bescor remote, but a marked improvement. And since even the original remote has speed control [no matter how rudimentary] that certainly must be the next step. And this is where all that talk about PWM comes in handy.

Reminder: The Bescor uses basic DC motors – their direction, speed and torque is directly proportionate to the DC voltage applied. Utilizing the AnalogWrite() function on PWM-enabled pins would allow for varied voltage, and thus [in theory] continuously variable speed control.

Having the output solved [at least on the level of an idea] only leaves input. For continously variable speed control, one would need an input element that allows for a range of values to be read, as the basic switch used in the previous article only yields a binary read [HIGH/LOW]. And this is where a basic potentiometer comes in – when connected to an analog input on the Moteino, it can read a value ranging from 0 to 1023 [hint, hint].

How about that joystick?

The Arduino ecosystem includes a number of examples centered around a thumb joystick, similar to the one you would find on a PlayStation controller [“It’s not a game!”] and for the purposes of Arduino sketches, that is certainly usable. However, using a thumb joystick in a production enviroment can get really old, really fast, so that idea was immediately dropped.

Luckily, we can use here a few items from the world of PTZ [pan/tilt/zoom] and security cameras. Most controllers for those systems use what is commonly known as a “3-axis joystick”, or a joystick with three planes of movement. For those among us with no grasp of spatial geometry, that means that the joystick can move left/right, up/down, and clockwise/counterclockwise around the joystick shaft.

A quick search on eBay yields this:

A typical 3-axis joystick for PTZ systems.

This type of joystick features two side mounted potentiometers, as well as a wire loom for the internally mounted potentiometer for the third axis. The one we used comes with standard 10K values for the individual potentiometers, and is connected to the 3.3VDC line on the Moteino. We have tried both 5K and 10K and wired them to both 3.3VDC and 5VDC lines – makes little difference in value resolution for this particular application.


As the 3-axis joystick is based around three limited turn potentiometers, wiring it to the Moteino is identical to wiring a typical potentiometer. A typical potentiometer has three pins, with the outer two connected to VDC and Ground, and the middle [center] pin connected to the input pin on the Moteino. The potentiometer is not directional, so it does not matter to which outside pin you wire the VDC and/or Ground [as long as you wire both of them individually :)]. For the purposes of an exercise, the wiring diagram below has the VDC and Ground connections swapped between the two potentiometers.

For the purposes of this article, the third potentiometer [accessible by the separate wire bundle] will not be wired.

No matter the location of the pins, it is always is a good idea to use a multimeter to correctly identify the signal pin. Although not much risk is present on the circuit and the related parts should you wire the pot incorrectly – it can save you a lot of grief when troubleshooting both the circuit and the code.

Reading Input

While I will not go in the details of how to read a potentiometer input, there are a few pointers as to the specifics of the hardware we are using here. In the meantime, for the basics of connecting standard potentiometers to Arduino, check this out:

A typical potentiometer will turn from point A to point B, denoting the minimum and maximum values it returns when read from a microcontroller. As such, when turned, it will remain at the position it has been moved [turned] to. The joystick we show above uses three spring-loaded potentiometers, meaning that once you let go of the joystick, the springs in the potentiometers will return the joystick, and thus the potentiometer[s] to a preset position.

The potentiometers still return values from 0 to 1023, but the preset position is somewhere in the middle of that range. Reading this parameter will allow us to determine both speed and direction using a single value, thus saving precious pin space on the Moteino. Pushing the joystick to the left will move the read value closer to 0, and pushing the joystick to the right will move the read value closer to 1023. The middle [neutral] position hovers typically between 500 and 550, so provisions need to be made to allow for some leeway. (*)

(*) For the joystick we use, we found that safe values are below 470 and above 560. Meaning, anything below 470 means the joystick was moved to the left, and anything above 560 means the joystick was moved to the right. Also, for the purpose of this example, I am only looking at one axis, responsible for the pan motion. Same applies for the tilt axis.

Having [provisionally] read the value, we need to get two bits of information from that singular value – direction and speed. We could use two different variables, or use a single struct which allows for multiple variables grouped as a packet, easier to handle, and easier to transmit [for the future].

Now, the value will be in the range 0-470 for direction left, and 560-1023 for direction right. Those values need to be translated to the 0-255 range that can then be used with the AnalogWrite() function:

And since we have the values for direction [PTZData.DirPan] and for speed [PTZData.SpeedPan], we can go ahead and move the motors, following the basics of DC motor actuation – write a varying pulse to one pin and ground the other for one direction, and do the opposite for the other direction:

All said and done, we arrive at the [very rudimentary, un-optimized] code for this session:

The clean files, as usual, located in the GitHub repository.

Does it work?

Sort of. Moving the joystick moves the Bescor head, in both directions if so needed / wanted. But direct control of the DC motors while powered from the Moteino is very limiting. Due to the maximum voltage being 3.3VDC and the minimum voltage to get those motors moving hovering somewhere above 2.2VDC, there is very little room for incremental and continuous speed control.

Next time, we increase power to the motors.

An avid tinkerer, Marjan has dabbled with software, hardware and the occasional guitar (he is not very good at the latter). Could hardly wait on the emergence of IoT, and now will simply not let it go...

...burns fingers regularly on soldering irons.

Leave a Reply

Your email address will not be published. Required fields are marked *