The whole reason I bought a Raspberry Pi was that I want to easily interface with the real world. So much of engineering is theoretical or simulation, very rarely does anyone get the chance to accomplish great things in the physical world.
The Goal of this Guide
This guide will walk you through the basics of controlling servo motors via the Raspberry Pi. Eventually, I’ll write a guide to building the automated laser pointer in the video above, but for now, I’ll just focus on how to control a single motor specifically.
What You’ll Need
Here’s a quick list of the components I am using for this project.
You’ll also need some wire to interface the leads of your power supply into the screw terminals of the WaveShare Servo Motor HAT.
Let’s Get Started
Assuming you have all the gear above, or at least similar items, let’s first install the packages needed to interface the Raspberry Pi to the WaveShare Servo Motor HAT.
1.) Open a terminal on your Raspberry Pi and run the following command:
sudo raspi-config
Within the GUI, enable the I2C interface: Choose Interfacing Options -> I2C ->yes
Then, reboot your Pi for the changes to take effect.
sudo reboot
2.) Next, install the following libraries onto your Raspberry Pi by running these commands in your terminal.
sudo apt-get updata
sudo apt-get install python-pip
sudo pip install RPi.GPIO
sudo apt-get install python-smbus
3.) Once complete, download the driver by using the commands below. Make sure you place the new directory in a place you can find it!
sudo apt-get install p7zip-full
wget http://www.waveshare.net/w/upload/6/6c/Servo_Driver_HAT.7z
7zr x Servo_Driver_HAT.7z -r -o./Servo_Driver_HAT
sudo chmod 777 -R Servo_Driver_HAT
cd Servo_Driver_HAT/Raspberry\ Pi/
Hook Up your Components!
Next, let’s get all the wires set up to power and control our servo motors. First, we need to hook up the power supply to the WaveShare Servo Driver board.
IMPORTANT: The Raspberry Pi can not produce enough power on its own to power the servo motors directly! You must interface to a separate power supply if you want your servo motors to be able to move properly.
To connect the power supply and the WaveShare Servo Driver board, I built a custom cable for easy connections. Check out the picture below to see my over-the-top solution.
I 3D printed a small box to keep my power supply leads separated, then my custom 16 AWG cable has two rolled copper leads for connection. Now my power supply can run on my desk and I don’t need to worry about shorting any of my equipment on accident. For this application, 16 AWG is super overkill, but it is what the auto store had in stock so I ran with it.
On the same custom cable, the other end has two small tinned leads sealed together via heat-shrink tubing. This cable is then inserted into the screw terminal as shown below.
Finally, attach the servo motor cables to the WaveShare Servo Motor board. The number associated with the pinout on the board will refer to the “channel” used to communicate with that servo motor in your code.
Servo motors typically have three inputs: Voltage In, Ground, and Signal. Make sure you don’t put the inputs on backwards when you attach them to the driver board! The color coding is somewhat standardized among different companies, it should be clear which way the servo motor should be plugged in.
Control your Servo Motor with Python Code
WaveShare provides some python code to control the servo motors. It is easy to modify and adapt your applications, and I’ll explain how adapted the code for my project here.
Get WaveShare’s Original Code Here
Servo motors are position-controlled motors. By sending a pulse-width modulated (PWM) signal, you designate for the motor to turn to a specific angular position. Within the original python code, the pulse width is set via the following method:
This method was written to be as general as possible so that it can interface with any servo motor. Some servo motors can only move within a 180 degree limit, others 270 degrees. Some servo motors can even rotate a full 360 degrees, and all these considerations will dictate what value of “pulse” serves as an input to the function above. I suspect this is why the method is written this way, and here is where I begin to modify what is happening.
Get my Modified Version of the Code
For my specific application, the servo motors I use only operate at a 180 degree range. This will limit what “pulses” I can send to the setServoPulse function. I spent some time trying to understand mathematically what is going on with the servo pulse, but I ultimately ended up figuring out the pulse limits via trail-and-error.
Check out my setAngle method below.
Via trial-and-error, I determined that the maximum pulse I could send and get a response from the servo motor was “2710”, and the minimum pulse I could send is “390”. I tested this out by sending different pulses in steps of 5 until I found these limits.
The method then provides a duty-cycle “d” which scales from zero to one and represents the 180-degree range. I choose to build it such that I designate an input from -90 to 90 degrees.
I also built a “center” method for a quick reset in case anything gets hairy.
How did I do?
Give me some feedback! Let me know if you have any questions or comments, or if I just got something plain wrong. You can connect with me on my social media links or here.
If you found this guide extremely helpful, consider buying me a cup of coffee! I would appreciate it so much, and it’ll give me more energy to write guides like this!