Servo Motor Control With PIC Microcontrollers – PWM PT1

Previous Tutorial Previous Tutorial Tutorial 30 Next Tutorial Next Tutorial
Servo Motor Control With PIC Microcontrollers | PWM
Intermediate Level ★★☆☆☆

 

Servo Motor Control Tutorial – PART1

Servo Motor Tutorial With PIC Microcontroller Part1 Thumbnail

 

In this Article / Tutorial, we’ll discuss how servo motor works. And how to control servo motor with pic microcontrollers. Why it’s difficult to generate 50Hz PWM with CCP in PIC Microcontrollers. And what are the different design solutions to control servo motors with microcontrollers? This article will address the CCP/PWM solution. Other methods for controlling servos will be introduced in future articles, such as: soft PWM, NCO, PCPWM, and much more!

Without further ado, let’s get started!


   Required Components For This Tutorial   

 

Qty. Component Name Buy On Amazon.com
1 PIC18F2550 Add
1 BreadBoard Add
1 Micro Servo Motor (Metal Gear) Add
1 LED Add    Add
1 Resistors Kit Add    Add
1 Capacitors Kit Add    Add
1 Jumper Wires Pack Add    Add
1 LM7805 Voltage Regulator (5v) Add
1 Crystal Oscillator Add
1 PICkit2 or 3 Programmer Add
2 9v Battery or DC Power Supply Add    Add    Add

My DSO Siglent-SDS1104 (on Amazon.com)

My Function Generator Fy-6900 (on Amazon.com)

*Affiliate Links Disclosure: links will make me a small commission at no additional cost to you*

The Prototyping Board Setup

Prototyping Board - Embedded Systems Tutorials With PIC MCUs

 


   What Are Servo Motors?   

 

Servo Motor With PIC Tutorial

A servo motor is a closed-loop control system consisting of a DC motor, gearbox, and potentiometer to provide feedback information about the angular position of the motor to be controlled. Servo motors are typically used in applications where precise small angular motion is required. 

Servo motors are widely used in robotics, automation, and electromechanical systems in general. Which includes: robotic arms, small bots, hexapods, and bio-inspired robots, and much more…

Servo Motors Applications

Hereafter in this article, we’ll discuss how servo motors internally work and how to control servo motors with microcontrollers & even without using a microcontroller in order to test your servos on the bench for the purpose of verification. Sometimes you get defect parts and sometimes the timing diagrams given in datasheets are not the exact ones for a specific model of a servo motor.

 


   How To Control Servo Motors?   

 

The way servo motors are working is simply by comparing a reference voltage to the actual angular shaft position using a potentiometer attached to the gearbox. The reference voltage can be controlled by sending a 50Hz PWM (pulse-width-modulated) signal to the servo motor. Which in turn changes the reference voltage and the control circuitry steers the motor in the right direction until it reaches the exact required angle position and it keeps holding it while the PWM signal is not changing.

The diagram down below indicates the behavior of the servo motor’s shaft due to the change of the PWM pulse width. Typically the full sweep (0->180°) is achieved by sweeping the pulse width from (1ms to 2ms).

How To Control Servo Motor With PIC Microcontroller

Different servo motors have different ranges for the pulse width of the 50Hz PWM signal which corresponds to the 0° position and 180° maximum angular position.

So, it’s important to double-check the datasheet for the specific servo motor you are using. However, it’s always best to take a test on the bench yourself because some servos come with a couple of Chinese papers that are poorly translated to English and may not be the exact documents for the attached servo motor at all!

And you’ll end up trying to figure out why your servo motor is not sweeping over the full scale using the values found in the “DATASHEET”.

 


   Testing Servo Motor Without Microcontroller   

Servo Motor Tutorial MG90S

That’s the servo motor we’ll be using in this tutorial. The first search result that popped up in my face when i was googling for its datasheet was a document that turned out to be not so accurate in terms of the timing diagram for the PWM signal. Here is the diagram snippet from the datasheet.

Servo Motor MG90S PWM Signal

And it turned out that the correct range for the PWM pulse width is 0.6ms to 2.4ms for angular motion from 0° to 180°. And that’s what we’ll be using for the test without and with a microcontroller.

 Note That:

0.6ms of 20ms period is a 3% duty cycle (0° Position),

1.4ms of 20ms period is a 7% duty cycle (90° Position),

2.4ms of 20ms period is a 12% duty cycle (180 ° Position).

Speaking of the no-microcontroller test, you can use the bench signal generator to generate the required 50Hz PWM signal for the servo motor. And here are the functional settings I’ve programmed my DDS generator to perform.

  • Square wave output signal 0-5v
  • Fixed frequency 50Hz
  • Sweep Function Activated for (Duty Cycle), Start value is 3%, End Value is 12%, Time period is 2 Seconds

The output signal from the DDS Function generator is connected to the servo motor signal pin. And here is the test demo video.

 


   Servo Motor Control With PIC Microcontrollers   

 

There are different ways to generate the 50Hz PWM signal required by the servo motor using a microcontroller. Speaking about PIC microcontroller, the first thing that should pop-up in your mind is the CCP PWM hardware module inside the microcontroller itself. But it turns out to be a little bit tricky business to get that right, here is why!

 

Why Is It Challenging To Use CCP PWM In PIC Microcontrollers To Control Servo Motors?

 

The problem stems from the fact that the timer2 period register used by the CCP PWM is an 8-Bit register and it can reach up to 255 at maximum. And here is the formula for the PWM frequency.

PWM Time Period

Let’s use the highest Prescaler possible (16) and the lowest Fosc you might have got (4MHz). The desired period is (1/50) to get 50Hz PWM Signal. Hence, the only unknown is the value to be written in PR2. By solving for PR2, it turns out to be 1249!! which is definitely way more than an 8-Bit (PR2) register can handle!

Even with a moderately low frequency (4MHz) oscillator, we still can’t generate a PWM signal that has a very low frequency near the 50Hz range. That’s the challenge!

One simple solution (at least cheap in code) is to settle down for the internal low-frequency low-power RC oscillator (31250Hz) inside the microcontroller itself. By plugging this Fosc=31250 in the previous PWM period equation, the PR2 value will be 155! And that’s obviously in the 8-Bit range and achievable.

Servo Motor Control With PIC18F2550

In the practical LABs hereafter, I’ll show you how to implement this solution and create a servo motor driver using the CCP PWM. However, down below are some other solutions that will be investigated in future articles (so stay tuned for that and please, keep sharing!).

 

What Are Some Other Design Techniques & Solutions To Control Servo Motors?

 

1 CCP PWM Hardware Module & Lowering Down Fosc using LP internal RC oscillator

(This solution is the one we’ll implement today).

2 Software PWM Generation Using Timer or Compare Match Interrupts

(Servo Motor Control Tutorial PART2 – With Soft PWM )

In a previous article, I’ve discussed the topic of software-generated PWM signals and how to precisely control the resolution, frequency, and duty cycle of it. You can refer to this article, or wait for the software PWM servo driving. But all in all, it’s a viable way to generate the 50Hz PWM signal and more importantly, it opens up the possibility to control any number of servo motors simultaneously (at least theoretically and @ high Fosc).

3 Using PCPWM module in Microchip PIC Microcontrollers

The Power Control PWM module from Microchip is available in a number of microcontrollers dedicated to motors and power control applications. Embedded systems designers for these sorts of applications are more familiar with this module and the dsPIC part with sophisticated PWM generation hardware.

The PCPWM hardware module is controlled by a total of 22 registers. And it has a larger time base registers and a very wide range of Prescaler values that makes your task much easier. The output channels may be up to 6 or 8.

4 Using NCO (Numerically Controlled Oscillator) Module

The NCO module from Microchip is available in too many microcontrollers especially the 8-Bit parts. This intelligent hardware module is capable of LINEARLY sweep over a wide range of frequencies and it can reach a resolution of 1/Fosc. I just can’t emphasize more how powerful and elegant this module is! It’s definitely a huge topic to be discussed in the future.

And it can potentially be the solution for a problem like a servo control. And let me show you how to do this but in another article!

 

 

Well, i think there still be other solutions like using external I2C servo driver and maybe combining CLC with timers. The list goes on, that’s enough for this section. Other solutions will be discussed and hopefully implemented in future articles. If you’re interested in that, please drop me a comment! i’d really like to know this!

 


   Servo Motor Sweep – LAB1   

 

Lab Name PWM – Servo Motor Sweep
Lab Number 38
Lab Level Beginner
Lab Objectives Learn how to use CCP modules to generate PWM signals @ 50Hz and control the position of a servo motor.

 

In this LAB, we’ll replicate the Arduino servo example that sweeps over the angular position range from 0° up to 180° back and forth. The same as what you’ve seen in the previous test using my function generator.

 Note: Refer to this tutorial, to learn all the calculations & setup steps for PWM 

 

       1. Coding       

 

Open the MPLAB IDE and create a new project name it “Servo_Motor_PWM”. If you have some issues doing so, you can always refer to the previous tutorial using the link below.

Create New Project With MPLAB IDE

Set the configuration bits to match the generic setting which we’ve stated earlier. And if you also find troubles creating this file, you can always refer to the previous tutorial using the link below.

Now, open the main.c file and let’s start developing the firmware for our project.

The full code listing for this lab is as follows

/*
* File: main.c
* Author: Khaled Magdy
*/

#include <xc.h>
#include "config.h"
#include "PWM.h"
#define _XTAL_FREQ 31250

void main(void) {

  INTSRC = 1; // Fosc = 8MHz/256 = 31.25KHz
  OSCCON = 0x02; // Internal Oscillator Selection
  Setup_PWM1();
  // DutyCycle Value (19 -> 75) = (3% -> 12%)
  unsigned int i=19;
  while(1)  
  {
    PWM1_Set_DC(i++);
    __delay_ms(15);
    if(i>75)
    {
      __delay_ms(500);
      i=19; PWM1_Set_DC(i);
      __delay_ms(500);
    }
  }
  return;
}

Project Files Download

 

       2. Simulation       

 

Servo Motor Control Sweep With PIC Microcontroller

 

       3. Prototyping       

 

Connect the Brown wire to GND and the Red to Vdd and the Orange to RC2 (CCP1 PWM Pin). And turn on the power supply. The 50Hz PWM signal is captured by my DSO (digital storage oscilloscope).

Servo 50Hz PWM Signal

At position 0° the Duty Cycle is 3% And by measuring the pulse width it turns out to be exactly what we’ve designed for (0.6ms)!

At position 180° the Duty Cycle is 12% And by measuring the pulse width it turns out to be exactly what we’ve designed for (2.4ms)!

 

Here is a short demo video for the running test for this LAB

Play Video On YouTube

 


   Servo Motor Manual Knob – LAB2   

 

Lab Name PWM – Servo Motor Knob
Lab Number 39
Lab Level Beginner
Lab Objectives Learn how to use CCP modules to generate PWM signals @ 50Hz and control the position of a servo motor.

 

In this LAB, we’ll replicate the Arduino servo example that uses the ADC and potentiometer to manually control the position of the servo motor using the analog input. We’ll read the AN1 channel, then the AD_RES result will get mapped to fit in the range of the servo PWM duty cycle 3% to 12% or 19 to 75.

Servo Motor Mapping Function With PIC Microcontroller 1

 Note: Refer to this tutorial, to learn all the calculations & setup steps for PWM 

 

       1. Coding       

 

Open the MPLAB IDE and create a new project name it “Servo_Motor_Knob”. If you have some issues doing so, you can always refer to the previous tutorial using the link below.

Create New Project With MPLAB IDE

Set the configuration bits to match the generic setting which we’ve stated earlier. And if you also find troubles creating this file, you can always refer to the previous tutorial using the link below.

Now, open the main.c file and let’s start developing the firmware for our project.

The full code listing for this LAB is as follows

/*
* File: main.c
* Author: Khaled Magdy
*/
#include <xc.h>
#include "ADC.h"
#include "PWM.h"
#include "config.h"
#define _XTAL_FREQ 31250

void main(void) {

  INTSRC = 0; // Fosc = 8MHz/256 = 31.25KHz
  OSCCON = 0x02; // Internal Oscillator Selection  
  unsigned int AD_RES, DC = 19;
  Setup_PWM1();
  ADC_Init();
  while(1)  
  {
    // Read The ADC Channel
    GO_nDONE = 1;
    while(GO_nDONE);
    AD_RES = (ADRESH<<2)+(ADRESL>>6);  
    // Mapping From ADC_RES To DutyCycle
    DC = 0.056*AD_RES+19.0;
    // Set The DC To Change The Servo Motor Angluar Position
    PWM1_Set_DC(DC);  
  }  
  return;
}

Download Project Files

 

       2. Simulation       

 

Servo Motor Knob With PIC Microcontroller LAB

 

       3. Prototyping       

 

Despite the fact that the simulation test did run smoothly but the poor PWM resolution due to the very low-frequency makes the servo inconsistent in movement. Moreover, the low RC oscillator for the Fosc did make the whole system a lot slower so it takes time to convert the A/D channel then change the PWM pulse width.

All in all, it did prove that the CCP PWM could be used but don’t expect it to be so great. Other solutions are coming in the next tutorials. Here is the demo video for this awful test!

 

Play Video On YouTube

 


   Concluding Remarks   

 

  1  

Yea, CCP PWM Can Be Used To Control Servo Motors. But…

But it has very limited (poor) resolution @ the operating frequency of 50Hz. And also it has pushed us to settle down for a very low running CPU frequency of 31250Hz or so. That’s not sufficient if your microcontroller has to perform any sort of processing!

Obviously using the CCP PWM was a not-so-good solution. But it was worth the try in order to get some results that are comparable to other design solutions and techniques which we’ll be discussing in the next tutorials. Let’s see if we can get much better results. Stay tuned for that!

  2  

Servo Motor Set Angle

You can also easily create a mapping function to map the servo motor angle (angular position) to the PWM duty cycle. Over the full range using the formula derivation below. The same way as we’ve done in the knob control LAB previously.

Servo Motor Mapping Function With PIC Microcontroller 2

The C-Code for the function implementation maybe something like this below.

void Servo_MoveTo(unsigned char Angle)
{
  // Angle is ranging from 0 upto 180
  int DC = 0.3111*Angle + 19;
  PWM1_Set_DC(DC);
}

  3  

Power Supply Precautions

Please, pay attention to power supply issues that arise when dealing with any kind of loads such as motors or so. Make sure to connect convenient decoupling capacitors on your microcontroller’s board. And to separate the power supply source if you’re going to use multiple servo motors.

Motor motion causes fluctuation in current being drawn by your circuit which causes voltage fluctuation in case of using not-so-good power supply circuitry. This can cause your microcontroller to restart very frequently, so please pay attention to this.

  4  

Don’t forget to SHARE these articles/tutorials. And let me know in the comments what do you think? Do you have any other ideas? maybe questions or problems?

I’ll be always here for help!

Regards ^^

Khaled M.

 

 

 

 

Previous Tutorial Previous Tutorial Tutorial 30 Next Tutorial Next Tutorial
Share This Page With Your Network!

Khaled Magdy

I'm an embedded systems engineer doing both Software & Hardware. I'm an EE guy who studied Computer Engineering, But I'm also passionate about Computer Science. I love reading, writing, creating projects and Technical training. A reader by day a writer by night, it's my lifestyle. You can view my profile or follow me via contacts.

You may also like...

7 Responses

  1. DJ says:

    Hi Khaled,
    Thanks a lot for your blog, I followed the advice for the sensor and got it working with PIC32MX320F128H.

    • Khaled Magdy says:

      That’s amazing! Thanks for your feedback though ^^
      Part3 of this tutorial is coming up very soon and I’m pretty sure it’s gonna appeal to you as well!

  2. Qasim says:

    Hi, Khaled. Great Tutorial.
    I have a small problem that im unable to understand. When mapping angular position to DC from 3% to 12% or 19 to 75, can you explain how 3% -> 19 and how 12% -> 75 ?

    • Khaled Magdy says:

      Greetings Qasim,

      Thanks for the feedback and that nice question. The limits for that mapping operation stem from the following equation (in the datasheet).

      Let’s put the values we’re using and get the digital value that we’ve to write in order to get a 100% duty cycle. OK?
      The 100% DutyCycle is when The Duty = The Period of the signal. The period T = 1/F = 1/50 = 20mSec = 0.020 sec

      PWM_Duty_Cycle = DC_Registers * Tosc * T2_Prescaler

      0.020 = DC_Registers * 1/31.25KHz * 1

      Solving for DC_Registers, it turns out to be 625
      Well, In order to get 100% DC you’ve got to write 625 in the (CCPR1L:CCP1CON<5:4>) register pair.

      100% -> 625
      3% -> x
      12% -> y

      x = 3 * 625 / 100 = 19
      y = 12 * 625 / 100 = 75

      I hope you got it now! And I’ll be always here for any question. Good luck with your projects ^^

      Regards,

  3. Thanks For the great Tutorial!

    I am doing the same with PIC16F1517.

    Really helpful!

  4. CredX says:

    Can i use the pic16f877a for this tutorial?

Leave a Reply

%d bloggers like this: