Servo Motor Control With Raspberry Pi

110,162

55

37

Introduction: Servo Motor Control With Raspberry Pi

Use a Raspberry Pi 3 and Python Scripts to control a servo motor.

Step 1: Materials and Tools

Materials:

  • Raspberry Pi 3 (RPi)
  • Jumper Wires, Male to Female (M/F)
  • Servo Motor

**In this project, it is necessary to access the Raspberry Pi desktop. This can be done by plugging a monitor, keyboard and mouse into the RPi or by using an SSH connection.**

No tools are necessary for this project as none of the connections are permanent and use jumper wires and a breadboard. If you want to make a permanent, more durable version, simply make the same connections with a soldering iron and some wire.

Step 2: Background Info.

**This step is all background info. If you don't care about how this is done and just want to do it without learning, skip to Step 3.**

This project uses Python scripts run on a Raspberry Pi microcontroller to send GPIO PWM outputs to a servo motor to set its angle. If all that sounds confusing, don't worry, I'm about to explain it.

First things first; a Raspberry Pi is an open-source credit card sized computer with 40 open GPIO pins. GPIO stands for "General Purpose Input/Output", which means these pins can either send electrical signals to drive hardware or receive them and read sensor data. We're using them as outputs, to send signals to a servo motor. Nothing special.

Python is a computer programming language, comparable to Javascript or C++. We'll be using very simple python commands, and no prior computer programming knowledge will be necessary.

A servo motor is a type of DC motor that, upon receiving a signal of a certain frequency, can rotate itself to any angle from 0-180 degrees. Its 90 degree position is generally referred to as 'neutral' position, because it can rotate equally in either direction from that point.

The way a servo motor reads the information it's being sent is by using an electrical signal called PWM. PWM stands for "Pulse Width Modulation". That just means sending ON electrical signals for a certain amount of time, followed by an OFF period, repeated hundreds of times a second. The amount of time the signal is on sets the angle the servo motor will rotate to. In most servos, the expected frequency is 50Hz, or 3000 cycles per minute. Servos will set to 0 degrees if given a signal of .5 ms, 90 when given 1.5 ms, and 180 when given 2.5ms pulses. This translates to about 2.5-12.5% duty in a 50Hz PWM cycle.

We'll be sending PWM signals from one GPIO pin on the RPi, and powering it from the GPIO board, so three wires will run from the servo to the RPi.

Now that we know what's going on, it's time to wire it up.

Step 3: Hardware Setup

The hardware for this project is very simple.

I recommend creating something to go on the end of the servo to better show its rotation, but that's totally unnecessary.

The only thing that you have to do is plug the three wires from the servo into the GPIO board. Refer to the diagram above for the pin numbers.

Plug a M/F jumper into each of the holes on the end of the servo cord, then plug the one coming off the red wire into pin #2, the one coming off of the brown into pin #6, and the one coming out of the yellow wire into pin #3. That's all there is to it, and if those instructions aren't clear enough, just look above at the pictures.

Step 4: Software Setup

First, we need to open a program on the Pi to write our code. We're going to use IDLE 2, so go to the top left of your desktop, click Menu, click Programming, and click Python 2(IDLE). You should see a blank text editor with an untitled document. You should not see a console with a shell prompt (ie. '>>>"). IF you do, click File, then New.

The first thing we need to do is import the GPIO module. So, on the first line, type exactly, CaSe sensitive,

import RPi.GPIO as GPIO

this imports the GPIO module
next, we need a command called 'sleep', so write

from time import sleep

next we need to name all of the pins, so set the naming mode by writing

GPIO.setmode(GPIO.BOARD)

this sets the names to board mode, which just names the pins according to the numbers in the middle of the diagram above.

Now we need an output to send our PWM signal on, so write

GPIO.setup(03, GPIO.OUT)

Now setup PWM on pin #3 at 50Hz

pwm=GPIO.PWM(03, 50)

Then start it with 0 duty cycle so it doesn't set any angles on startup

pwm.start(0)

Now, to set the angle of the servo, we need to send a specific signal to it. This can differ from servo to servo, as normally it's from 2.5-12.5%, and on the ones I'm using it's 2-12%. Regardless, it will be a 10% window, so to calculate the duty cycle for your desired angle, divide by 18, then add the lowest available value, in this case 2.

So, for 90 degrees, divide by 18, which is 5, then add 2, and you get 7. So on this servo 7% duty is 90 degrees.

As you can see, this math is not very friendly and would be tedious to do every time you wanted to set an angle, so in order to simplify that we're going to write a function in Python that does the math automatically then sets the angle.

So, first define a function. You can name it whatever you like.

def SetAngle(angle):
	duty = angle / 18 + 2
	GPIO.output(03, True)
	pwm.ChangeDutyCycle(duty)
	sleep(1)
	GPIO.output(03, False)
	pwm.ChangeDutyCycle(0)

Now that probably looks like a lot of confusing code, so let me explain everything I did.

  • The first line sets up a function called 'SetAngle' that we can call later in the code and give our input as an angle.
  • The second line (which needs to be indented inside the function) sets a variable equal to our angle divided by 18 and 2 added like I showed above
  • The third line turns on the pin for output
  • The fourth line changes the duty cycle to match what we calculated
  • The fifth line waits 1 second so the servo has time to make the turn. Depending on the speed of your servo you might need longer, or you might not need this long
  • The sixth line turns off the pin
  • And the seventh line changes the duty back to 0 so we aren't continuously sending inputs to the servo

Now in your code you can call the function, by writing

SetAngle(90) 

to tell the servo to turn to 90 degrees.

So, in your code, call a few angles, and when we run the code we'll see how they run on the servo.

At the end of your code, make sure to write

pwm.stop()
GPIO.cleanup()

And that's it! You now have a code that can set your servo to any angle. Press F5, then save to test your code!


*Note: you may receive an error that says the selected GPIO channels are already in use. This won't affect your project, and you can make the warnings stop appearing by writing "GPIO.setwarnings(False)" to your code.*

Be the First to Share

    Recommendations

    • Recycled Speed Challenge

      Recycled Speed Challenge
    • Make it Move Contest 2020

      Make it Move Contest 2020
    • Build a Tool Contest

      Build a Tool Contest

    37 Discussions

    0
    ward.dejonckheere
    ward.dejonckheere

    Question 2 years ago

    've heard many times that it's recomended to use an external suply to power the servo, altough you don't do this, why? I ask this because i'm currently working on a project. And it would save me a bit of wiring.

    0
    kundan951351
    kundan951351

    Answer 3 months ago

    I'm having the same problem. The coding says its working perfectly but the servo motor just isn't moving. Some say that it's because I need an external supply to power the servo. I am usimg the same servo motor as you are and my Raspberry Pi is version 4 model B.

    0
    ward.dejonckheere
    ward.dejonckheere

    Reply 3 months ago

    Are you sure you connected the servo to the right pins, not all pins support PWM either, so make sure you're using the right pins.
    Also, are you sure the servo is not broken?

    2
    lanc1999
    lanc1999

    Answer 2 years ago

    That is certainly a good idea to avoid overloading and possibly causing damage to your RPi, but I checked the current draw and voltage requirements of the servo I was using and made sure it would be okay to use directly from the Pi’s GPIO board. If you are unsure of how to do that, or are using an excessive amounts of servos or other power requirements it’s definitely a good idea to use an external power supply. Just swap the jumpers from where I hooked them up to the 5V and GND pins on the Pi and connect them to the appropriate power source to power your servos instead. Hope this helped!

    0
    ketanparekh
    ketanparekh

    4 months ago on Step 4

    from the programming screen RUN does nothing.
    When to the prompt - ran python server.py fails
    File Servo.py line 8
    def SetAngle(angle)
    Its failing at the function... what am I doing wrong ?

    0
    kyle590124
    kyle590124

    11 months ago

    what is this
    duty = angle / 18 + 2
    mean?
    is it a correction and why we need to divide 18 with it?(sorry for the poor english

    0
    JurgenN1
    JurgenN1

    Question 1 year ago on Introduction

    Is it possible to let the servo move slow to the setpoint ?

    0
    lanc1999
    lanc1999

    Answer 1 year ago

    The only way to do this with a servo motor would be to write a function that segments your angle and then slowly moves the servo to checkpoints along that angle with time delays in between them. A much easier solution would be to use a stepper motor, which are similar to servo motors in that they can move specific amounts to a desired angle if needed, and the way that is done on a stepper motor not only allows but actually necessitates that you set your own specific time intervals. I hope this helped, good luck with either approach! Please feel free to ask any additional questions

    0
    mohamedghazy
    mohamedghazy

    Question 1 year ago

    please,i need the wiring diagram of AC servo motor and its driver with raspberry pi

    0
    lanc1999
    lanc1999

    Reply 1 year ago

    I'm confused by your wording, what is an AC servo motor? The servo motor used in this instructable was powered by either 5V or 3.3V DC power supply, and modulated with 3.3V DC PWM pulses. I can provide a circuit diagram for this circuit if you need, but it won't include any more information than which pins connect to which, which can also be found in the text of the instructable.

    0
    mohamedghazy
    mohamedghazy

    Reply 1 year ago

    AC servo driver powered by 220 V and the microcontroller control on the driver and the driver send pulses to control the servo motor
    this image may explain

    Capture.PNG
    0
    ward.dejonckheere
    ward.dejonckheere

    Question 2 years ago

    Hey, i have another question regarding the servo.

    I've noticed that my servo twitches a lot when powered on and stationary. Do you happen to know how i could fix this?

    0
    lanc1999
    lanc1999

    Answer 2 years ago

    No, I have noticed the same thing and I’m unsure if it’s fluctuating PWM or main power or some type of mechanical issue, but I’d suggest researching the servo you’re using and whether or not raspberry pi’s typically have stable PWM. Sorry I couldn’t be of more help!

    0
    ward.dejonckheere
    ward.dejonckheere

    Answer 2 years ago

    I've been able to sort it out, to prevent it from twitching i had to send a signal once, and then stop the pwm. Untill i want to change it again.

    0
    Kedj
    Kedj

    Question 2 years ago on Step 4

    Thank you very much for this, everything on this page has been very helpful! However, I'm trying to automatically control the servo motors at definite times for a day (8:00AM, 12:00PM and 4:00PM), would this be possible?

    1
    ward.dejonckheere
    ward.dejonckheere

    Answer 2 years ago

    Note that when you don't connect the RPi to the internet, the clock in your RPi will start shifting, but if it's connected to the internet and can sync up to that. You can use a RTC module to fix this problem if needed. (some of those include an alarm function, wich you can use to start a function.

    0
    rockusbacchus
    rockusbacchus

    Answer 2 years ago

    If I were you, I would look at using the code here along with cron. Cron is a tool used to schedule jobs in unix/linux environments. There are tons of resources online to learn how to use it. I highly recommend adding it to your skill set.

    0
    lanc1999
    lanc1999

    Answer 2 years ago

    I am not sure, but if you were to use my code as a baseline to define some functions and then find out how to check the current time on a RPi, you could create a constantly looping ‘if’ statement that executed my functions when the time input was equal to your desired times. Like I said, I’ve never done anything like that or researched it, but to my knowledge it should be totally possible. Hope this helped!

    0
    pg96
    pg96

    2 years ago

    how would you code it if you're using the Adafruit servo Pihat to control more than one servo. pwm.ChangeDutyCycle(duty) would not work in this case right?