element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Raspberry Pi Projects
  • Products
  • Raspberry Pi
  • Raspberry Pi Projects
  • More
  • Cancel
Raspberry Pi Projects
Blog Building a Hobby Servo Controller – Part 1
  • Blog
  • Documents
  • Events
  • Polls
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Raspberry Pi Projects to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: shabaz
  • Date Created: 11 Mar 2018 7:10 PM Date Created
  • Views 12703 views
  • Likes 20 likes
  • Comments 43 comments
  • coding
  • servo board
  • rpiintermediate
  • moversshakersch
  • servo hat
  • servo
  • bbb
  • texas_instruments
  • rpi
  • msp430
  • hobby servo
  • servo motors
  • texas instruments
  • raspberry_pi_projects
  • msp430g2553
  • basic coding
  • ti
Related
Recommended

Building a Hobby Servo Controller – Part 1

shabaz
shabaz
11 Mar 2018

Introduction

Working on a recent Pi project, I needed to use some servo's. This blog post discusses a servo controller project that can be used for toy and model cars, planes, model robots and so on. There are existing controllers out there, but I didn’t have one, and besides some of them seemed expensive – I didn’t want to spend $15+ on something I could make for $2. Also this was an opportunity to try to design something hopefully better (in some ways) than existing off-the-shelf controllers, and also explore how to create a custom hardware peripheral for attaching to the Pi. It isn't hard, anyone can do it : )

 

The aim was to build something that could connect between the Pi (or any other single board computer or micro-controller, such as the Beaglebone, Arduino, and so on), and the servos, as shown in red here. It is explained in more detail below, but in brief, it would allow the Pi, or any micro-controller of choice to communicate using a standard I2C interface, and the servo controller would generate the correct pulse width modulation (PWM) signals to control multiple servos, which would create the motion for the desired task.

image

But first, it is good to understand the Servo, to know how to use it and its strengths and weaknesses.

 

What are Servos'?

When motors are running, it is hard to know how much they have turned, and when to shut off a motor precisely, to do accurate things like robotics. It would also be nice to adjust the voltage so that the motor can accelerate and get stuff done, but slow down as the robot approaches a human! Servo systems are different from standalone AC or DC motors in that they have feedback. The feedback can be used to precisely control the motion (position and speed). In industrial scenarios, servo motors are composed of an AC or DC motor (specially built to have very smooth rotation) and a rotary encoder (a device that generates pulses on a wire as a shaft is turned), and circuitry known as a servo amplifier (an amplifier just generates a voltage based on an input signal). This is connected up to the industrial machine controller or robot brains (using a digital interface) and position and speed commands are sent digitally to the servo amplifier. Much like any amplifier, it will generate a voltage, which drives the motor in either direction depending on the polarity of the voltage. The feedback from the encoder is used as an ‘error signal’; as it approaches the desired settings, then the servo amplifier output voltage is reduced, therefore allowing the motor to slow down and stop as it approaches the correct position. The machine cannot be knocked out of position, because the encoder will generate pulses that produce an error signal into the servo amplifier, which will generate a correction voltage to bring the machine back to where it was specified to be according to the original message sent from the machine controller.

image

 

In hobby territory, a similar system is used but compacted into the space of a few cubic centimetres. Instead of a high-performance motor, often just a brushed DC motor is used, although higher-end hobby servos will have brushless motors. The rotary encoder is expensive so it is swapped out with a cheaper (and lower-performance) alternative: a variable resistance, known as a potentiometer. The servo amplifier is composed of an analog to digital converter (to read the potentiometer resistance) and the amplification occurs using digital pulses and a H-bridge. Instead of a fancy isolated digital interface, the hobby servo uses a PWM input signal where the pulse width determines the position that the motor should move to. Instead of multiple rotations that may be needed to move industrial machines into position, the hobby servo often just rotates through a smaller rotational distance – maybe only 180 degrees for example – to suit hobby requirements such as controlling toy wheel steering or model aeroplane surfaces. Instead of a direct connection from the motor shaft to the industrial machine for the best precision, the hobby servo has to make do with limited power and will have gearing on the output shaft; this will introduce some slack, also known as ‘backlash’, which can reduce accuracy further.

 

If you break open a hobby servo, you'll see all these components. The PCB will contain the circuit that takes the desired motion signal (the PWM input), and the H-bridge circuit which is switched on and off rapidly to generate an average voltage to drive the motor. Instead of the rotary encoder attached to the back of the motor, there will be a potentiometer near the motor, attached via a gear. There will be three wires egressing from the servo; two of them are for the power source, and one of them is for the input PWM signal referenced to the ground wire.

 

How are Hobby Servo Motors Controlled?

Hobby servos come with a three wire connection; the power connections (around +4.8 to 6V DC and 0V connection) and a PWM input connection which can be driven by a 5V logic level signal, but 3.3V seems to work too usually.

 

The PWM rate is about 50Hz, although it is non-critical. The high pulse width is what controls the position of the servo. The actual values vary wildly from one hobby servo type to another. Sometimes a value of between 1000usec to 2000usec (1 to 2msec) is stated to move the servo shaft from its extreme clockwise position to its extreme anti-clockwise position (looking at the servo shaft end-on). A value outside of the range will not cause any additional motion. Other hobby servos may use a different pulse range, such as between 600usec and 2400usec. In most cases the centre position can be assumed to be achieved at about 1500usec pulse width.

 

The PWM pulses (at that 50Hz rate mentioned above) need to produced with little jitter in the pulse width, otherwise the servo will make a chattering noise as the servo amplifier keeps generating a voltage to adjust the motor on every slight change in the generated pulse width. Although PWM pulses can be produced with just timer circuitry (such as with 555 timer chips), a more popular way is to use digital circuits or computers/microcontrollers.

 

Trying to generate PWM pulses in software is not easy, because most computers are not designed for such tasks. They will produce slightly varying pulse widths with lots of jitter! Single board computers such as the Raspberry Pi or BeagleBone Black often have dedicated circuitry inside that can generate pulse trains with accuracy. But often SBCs are not designed to control many servos simultaneously. Furthermore, their dedicated circuitry is for general pulse trains, and so some coding is needed to make it suitable for use with the pulse width sizes required for operation with hobby servos, which is fine, but for quick projects sometimes it is easier to offload the PWM generation to an external chip, and just send instructions from time to time (using a serial interface such as I2C or UART) whenever the position of the servo shaft needs changing. I2C and UART capabilities are present on nearly all SBCs and microcontrollers, so these are handy interfaces to use.

 

What else is out there?

A google search revealed that one way to control it is to use a PCA9865 chip. This generates sixteen PWM outputs for general purposes (primarily to control LED brightness), under I2C control. It isn’t dedicated for servo use, so the developer still needs to do a lot of coding to make it achieve the desired effect. Adafruit has some library code for it.

 

The PCA9685 has only 12-bit resolution, and this means that the granularity of a servo is not being used to its full potential. As an example; my cheap SG-5010 servo (which rotates across its full range with a pulse width between 400 and 2350usec) has at least 500 visibly discernible steps (about 0.35 degrees per step) from its most anti-clockwise to its most clockwise position (to find this out, I varied the pulse width gradually, and counted how many discrete movements I could see).

 

A PCA9685 servo controller set to output pulses every 50Hz, can only resolve 390 steps due to its 12-bit resolution. To improve this, the pulse rate could be increased, but even at 60Hz, the PCA9685 can only resolve 475 steps. A better quality servo than my SG-5010 may well have a resolution in excess of 500 steps. Hobby servos are not accurate devices and so each step will not be identical. Also there be backlash in the end mechanism that the servo is connected to. Nevertheless there could be a requirement to finely trim the servo position as closely as possible, and that is harder to do with just 475 steps available.

 

One other thing that bothered me, was that if I was to use a PCA9685, I’d have to do a lot of calculations in the controlling software. The PCA9685 as a generic PWM device does not understand degrees of rotation, or lengths, or percentages of full travel. These have to be done by the user, or in the library code, to translate into a number that the PCA9685 understands.

 

There are also dedicated, fully built modules but at prices that make no sense (to me anyway).

 

This project was an opportunity to try to address all these problems (and hopefully not introduce too many new ones!).

 

The Design

To make this project nice and easy, I used a 20-pin DIP chip – a Texas Instruments MSP430 microcontroller. It is very low cost, easy to hand-solder, the programmer is cheap at $10 and it doesn’t need a lot of software installed on the PC. The steps to program the chip are described in this other project Cyclops-1000: An Electronic Eye for Rotational Speed Measurement (see the section Working with the Microcontroller).

 

In contrast the PCA9685 supports up to 16 servos, but for my project I was going to aim for just 8. I figured 8 servos is a good quantity to start with, and if the user wishes to add more, then the I2C bus supports adding more ICs. I’d rather control 8 servos more accurately and with more features, than have a board with 16 servos controlled with less accuracy and less features.

 

The MSP430 will be coded up to implement the design shown in the block diagram below. It was fun to plan how it should work; that's the benefit of using a microcontroller instead of someone else's servo controller! The microcontroller datasheet was used to check that each pin could do what was desired.

 

For future flexibility, some pins were allocated to be usable for analog inputs too, since the microcontroller datasheet shows that those pins support that capability.

 

An address pin (A0) was created in the design to allow two of these devices to be connected to the I2C bus.

 

Since there are only 20 pins available with this microcontroller, I reused one of the servo pins to also work as a mode switch. This is a typical trick where the pin can be programmed as an input at power-up, and if it detects a certain voltage level then the code internally switches modes of operation.

image

PinsDescription
SERVO0-SERVO7Wire up the servos here
SDA,SCLI2C interface to the Pi, Arduino, etc. The Arduino will require pull-up resistors to 3.3V. The Pi already has these.
A0Leave disconnected to use I2C address 0x31. Short to ground to use I2C address 0x30.
VDDConnect to 3.3V, and have a capacitor (100nF) to ground
VSSGround connection
*RESETConnect a resistor (47k) and capacitor (1nF) here, to generate a reset pulse when the power is applied.
ANA0-ANA3Optional analog mode. Connect potentiometers here for driving SERVO0-SERVO3
SERVO7/ANASELConnect to +3.3V via a 1k resistor, to have the analog mode enabled. It is not possible to use all 8 servos in analog mode
25HERTZConnect a resistor and LED here to have a flashing indicator

 

 

I2C Commands

The block diagram above shows that there are about 12 different parameters (registers) that can be sent to the controller from the Pi/Arduino. This is just an initial design to get things progressing, and more capabilities could be added later.

 

I2C commands will be used to set the position of each servo, but there are also commands to set the min/max width of the pulses that the servo expects, and also the user-friendly number range that is desired. So, if I had a 180 degree servo where the datasheet specified that it needed pulses between 800 and 2200usec, and for my application I wanted to specify the motion as a percentage between 0 and 100 (100 representing 180 degrees) then I’d want to configure the controller with these parameter values using I2C:

 

WidthMin = 800
WidthMax = 2200
UserMin = 0
UserMax = 100

 

Then, to move the fourth servo (SERVO3, since the numbering starts from zero) to its halfway or centred position, I’d want to set this parameter value:

 

SERVO3 = 50

 

I needed to construct some system for sending these parameters over I2C. I settled on this:

image

 

The first byte will always be the slave address (0x31, or 0x30 if the A0 pin is connected to ground). The second byte will be the desired command. A command of 0x00 will mean SERVO0. 0x01 will mean SERVO1 and so on. There will also be commands to set the width and user min/max values.

 

The actual settings will be 16-bit integers, which means that two bytes are needed to send them. The ordering is least-significant-byte first. Here are the I2C values to set the fourth servo (SERVO3) to the decimal value 50 (which is 0x0032 in hexadecimal):

image

In Python on the Raspberry Pi this is easy, it takes just three lines:

 

from I2C import I2C
servo=I2C(0x31)
servo.write_subaddr_int(3, 50)

 

Line 2 shows the I2C interface being set up to communicate to the 0x31 slave address, and line 3 shows that servo 3 (fourth servo) is being set to the value 50. That write_subaddr_int function will automatically convert the number 50 into a two byte integer and send all the bytes in the correct order.

 

Wiring It Up

The top view pin configuration that was chosen is shown here:

image

 

Here is how it would be connected up to a servo (more servos can be added of course):

image

 

The schematic is shown below. The resistors R2 and R3 are pull-up resistors for the I2C bus. The Pi already has them so R2 and R3 are not needed for it, but the Arduino would require them. Note that the simpler Arduino boards (like Arduino Uno) use a 5V supply, but this servo controller uses 3.3-3.6V, so the SDA and SCL pull-up resistors must go to the 3.3V pin on such Arduino’s, and not to the 5V pin.

 

Resistor R1 and C3 form the reset circuit. Capacitors C1 and C2 provide supply decoupling to the microcontroller. Capacitor C4 provides supply decoupling for all the attached servos.

image

 

Summary

This first part of this mini-project investigated the motivation to create a $2 servo controller that could in theory perform better and have more features that existing off-the-shelf options. The operation of servos was described, and how the design could look internally with an I2C instruction decoder and PWM generator. A format/scheme for sending commands was also created, and the wiring diagram to see how it could be used. As next steps, a PCB will be created, and some coding will be done!

  • Sign in to reply

Top Comments

  • shabaz
    shabaz over 7 years ago in reply to Jan Cumps +6
    Hi Frank and Jan, Excellent, that looks feasible. Looks like there are specific 64-byte blocks of memory that can be written to, to save having to allocate a much larger chunk of Flash for this. That seems…
  • shabaz
    shabaz over 7 years ago +6
    The PCBs arrived last week, so I did assemble a few, but still need to test them! (slightly blurry pic from mobile..)
  • shabaz
    shabaz over 7 years ago in reply to beacon_dave +5
    Hi Dave, It's a really great idea. Unfortunately the particular chip I'm using (MSP430G2553) doesn't have any non-volatile storage apart from the Flash : ( I might move to a surface-mount part in a version…
  • Workshopshed
    Workshopshed over 7 years ago in reply to beacon_dave

    Hey Dave, I've seen this kind of thing on other boards, it seems like a good approach.

     

    https://github.com/alvaroferran/IntelliServo

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 7 years ago in reply to balearicdynamics

    Hi Enrico,

     

    Thanks!! I appreciate it, I'm always trying to learn ways to write stuff, so it's awesome to hear the feedback if I get things right or wrong : )

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • balearicdynamics
    balearicdynamics over 7 years ago

    Finally, I had the time to read this first part in depth. You are my official tutorial-man! The plus - observing pragmatically this post - is your ability to explain the thing no by your personal point of view (obviously having the proper needed knowledge) but by the point of view of the reader, that find all the information he needs to find the answers before the questions image

     

    Thank you for sharing. Enrico

    • Cancel
    • Vote Up +5 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • fmilburn
    fmilburn over 7 years ago in reply to 14rhb

    Inexpensive hot air rework stations  http://www.newark.com/tenma/21-11424/temperature-controlled-hot-air/dp/25AC4940?st=Hot%20air%20rework work fine in my experience for SMD part removal. In fact I think it is easier than through hole.  Soldering larger SMD parts by hand are not appreciably harder than through hole either with practice.  I think maker faires and such would be doing a real favor to introduce SMD, perhaps alongside through hole, for those who haven’t tried it.

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • jw0752
    jw0752 over 7 years ago in reply to genebren

    Jan Cumps mentioned removing a DIP component from a six layer board. Your trick for removal, cutting the leads and removing them one by one works well for this situation as well. It does help to have a very sharp and pointed cutter though.

     

    John

    • Cancel
    • Vote Up +5 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube