Introduction: Angular Positional Control of 28BYJ-48 Stepper Motor With Arduino & Analogue Joystick

This is a control scheme for the 28BYJ-48 stepper motor that I have developed to use as part of my final year dissertation project. I have not seen this done before so thought I would upload what I discovered. Hopefully this will help someone else out there!

The code basically allows a stepper motor to "copy" the angular position of an analogue joystick, that is to say if you push the joystick forward, the motor points towards "north". push the joystick towards west, the motor rotates to point in the same direction.

For my implementation I required that if the joystick is let go, i.e. has no angular position, the motor returns to the "home" direction. The home direction is facing east, and the motor (or at lease whatever pointer / device you have attached to the output shaft!) must also be facing this direction when powered on.


Arduino Uno or similar

breadboard & selection of jumper wires (male to male, male to female)

5V power supply

Analogue joystick module (ideally with a momentary push button feature, this makes for easier resting of the "home" position

28BYJ-48 stepper motor and ULN2003 stepper driver

Pen, paper and blu-tac (or any other pointer device to attach to the motor!)

Step 1: Step 1: Setting Up

Connect the stepper motor to the stepper driver, and connect the pins as follows:

IN1 - Arduino pin 8

IN2 - Arduino pin 9

IN3 - Arduino pin 10

IN4 - Arduino pin 11

Connect your 5v power supply to the supply rails on your breadboard, and connect the ULN2003 5v inputs to the supply rails. connect the ground rail to the ground on your Arduino.

for the joystick, connect as follows:

Switch pin - Arduino pin 2

X axis - Arduino A0 (Analogue in 0)

Y axis - Arduino A1

+5V - Arduino 5V output

GND - Arduino GND

Finally connect the ground of your breadboard to the other Arduino GND pin

Step 2: Step 2: Explaining the Code

I have included the full Arduino code for you to download and use. But will do my best to explain the pertinent parts here.

The theory behind this code is that the space occupied by the joystick is split into a graph, with 0,0 at the centre. however the joystick inputs rest at (approx) 512 in the centre, so to overcome this two functions are used to "zero" the value read from the X and Y axis. depending on the power supply you use you may need to alter the values in the functions ZeroX and ZeroY so that your joystick gives out a reliable reading of 0 when resting.

When the X,Y values are read, they are first converted to radians using the function atan2() in the math.h library. Explaining this function is outside of the scope of this instructable, but please do go look it up - it is a rather simple trick of geometry!

Finally, to make life easier for those of us who used to working in degrees rather than rads, the rad value calculated by atan2() is converted to degrees.

At the top of the loop is a small snippet of code that allows you to click in the momentary button on the joystick to move the "home" location. This was incredibly useful while testing the code, but I've left it in as I can see how it could be useful in some instances.

Now onto the main bulk of the code! we begin by reading the joystick X,Y coordinates twice separated by a 10ms delay and then checking if they are the same - I found that the joystick would occasionally output sporadic readings, and this slight delay was enough to stop the motor turning based on these. It's also a short enough delay that it doesn't seem to interfere with intentional inputs.

The rest of the code is rather self explanatory and I've done my best to document it; A series of IF statements compare the current joystick angle to the motor angle, and move the motor to that angle. The 28BYJ-48 has 5.689 steps per degree, so that's why we multiply the required movement by this seemingly odd number!

The one part of the code that requires the most explaining is what I have dubbed the "wraparound case". In the even that the joystick & motor were at e.g. +175°, and the joystick subsequently moved to -175° (a movement of only 10° on the joystick, from just north of west to just south of west), the motor would move IN THE WRONG DIRECTION by 350°! to account for this the special case was written.

The wraparound case begins by checking that the motor and joystick have opposite signs, i.e. the motor is positive and the joystick negative, or vice versa. It also checks that the sum of the absolute (that is, positive values) of the joystick and motor are above 180°.

If both these statements are true, the function then checks whether the motor needs to move clockwise (the motor value is negative) or anticlockwise (if the motor value is positive).

The absolute values of the motor angle and joystick angle are totalled, and subtracted from 360° to determine the distance to move. Finally, the motor angle (which now reflects the joystick angle) is updated as such.


So, all that's left to do is upload the code to your Arduino and run it! See the video above for a good idea of how the project functions. This would be useful for camera gimbals, robotic arms and many other applications!

If you use the code, please let me know, and if you see any where the code can be improved, I'd love to hear your feedback.