{"id":3966,"date":"2019-11-19T15:43:54","date_gmt":"2019-11-19T13:43:54","guid":{"rendered":"https:\/\/deepbluembedded.com\/?p=3966"},"modified":"2023-08-17T23:52:21","modified_gmt":"2023-08-17T20:52:21","slug":"servo-motor-control-with-pic-microcontroller-16bit-pwm-pt3","status":"publish","type":"post","link":"https:\/\/deepbluembedded.com\/servo-motor-control-with-pic-microcontroller-16bit-pwm-pt3\/","title":{"rendered":"Servo Motor Control With PIC Microcontroller – 16Bit PWM PT3"},"content":{"rendered":"\n\n\n\n\n
\"Previous<\/a><\/td>\nPrevious Tutorial<\/strong><\/a><\/td>\nTutorial 32<\/span><\/strong><\/span><\/td>\nNext Tutorial<\/strong><\/td>\n\"Next<\/td>\n<\/tr>\n
<\/td>\nServo Motor Control With PIC Microcontrollers | 16Bit PWM<\/strong><\/span><\/td>\n<\/td>\n<\/tr>\n
<\/td>\nIntermediate Level \u2605\u2605\u2606\u2606\u2606<\/strong><\/span><\/td>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n

 <\/p>\n

Servo Motor Control Tutorial – PART 3<\/strong><\/p>\n

\"Servo<\/p>\n

 <\/p>\n

In this Article \/ Tutorial, we’ll discuss how to control servo motor with PIC microcontroller using 16-Bit High-Resolution PWM signals. This depends on a technique proposed in an earlier article that utilizes the CCP Compaer+Timer module in order to create a high-resolution PWM<\/a> signal @ any desired frequency.<\/span><\/p>\n

This technique will dramatically increase our control precision over the servo motor angular position as we’ll see in a couple of LABs hereafter in the article.<\/span><\/p>\n

Without further ado, let’s get started!<\/span><\/p>\n

[toc]<\/p>\n


\n

\u00a0 \u00a0Required Components For This Tutorial\u00a0 \u00a0<\/span><\/strong><\/span><\/h3>\n

 <\/p>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Qty.<\/strong><\/span><\/td>\nComponent Name<\/strong><\/span><\/td>\nBuy<\/strong> On Amazon.com<\/span><\/td>\n<\/tr>\n
1<\/td>\nPIC18F2550<\/span><\/td>\nAdd<\/a><\/td>\n<\/tr>\n
1<\/td>\nBreadBoard<\/span><\/td>\nAdd<\/a><\/td>\n<\/tr>\n
1<\/td>\nMicro Servo Motor (Metal Gear)<\/span><\/td>\nAdd<\/a><\/td>\n<\/tr>\n
1<\/td>\nLED<\/span><\/td>\nAdd<\/a>\u00a0 \u00a0 Add<\/a><\/td>\n<\/tr>\n
1<\/td>\nResistors Kit<\/span><\/td>\nAdd<\/a>\u00a0 \u00a0 Add<\/a><\/td>\n<\/tr>\n
1<\/td>\nCapacitors Kit<\/span><\/td>\nAdd<\/a>\u00a0 \u00a0 Add<\/a><\/td>\n<\/tr>\n
1<\/td>\nJumper Wires Pack<\/span><\/td>\nAdd<\/a>\u00a0 \u00a0 Add<\/a><\/td>\n<\/tr>\n
1<\/td>\nLM7805 Voltage Regulator (5v)<\/span><\/td>\nAdd<\/a><\/td>\n<\/tr>\n
1<\/td>\nCrystal Oscillator<\/span><\/td>\nAdd<\/a><\/td>\n<\/tr>\n
1<\/td>\nPICkit2 or 3 Programmer<\/span><\/td>\nAdd<\/a><\/td>\n<\/tr>\n
2<\/td>\n9v Battery or DC Power Supply<\/span><\/td>\nAdd<\/a>\u00a0 \u00a0 Add<\/a>\u00a0 \u00a0 Add<\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n

My DSO Siglent-SDS1104 (on Amazon.com)<\/a><\/p>\n

My Function Generator Fy-6900 (on Amazon.com)<\/a><\/p>\n

*Affiliate Links Disclosure: links will make me a small commission at no additional cost to you*<\/p>\n

The Prototyping Board Setup<\/a><\/strong><\/p>\n

\"Prototyping<\/a><\/p>\n

 <\/p>\n


\n

\u00a0 \u00a0How To Control Servo Motors?\u00a0 \u00a0<\/span><\/strong><\/span><\/h3>\n

 <\/p>\n

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.<\/span><\/p>\n

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\u00b0) is achieved by sweeping the pulse width from (1ms to 2ms).<\/span><\/p>\n

\"How<\/p>\n

Different servo motors have different ranges for the pulse width of the 50Hz PWM signal which corresponds to the 0\u00b0 position and 180\u00b0 maximum angular position. <\/span>So, it’s important to double-check the datasheet for the specific servo motor you are using.<\/span><\/p>\n

The range for the PWM pulse width for my servo motors (MG90S) is 0.6ms to 2.4ms for angular motion from 0\u00b0 to 180\u00b0. And that\u2019s what we\u2019ll be using.<\/span><\/p>\n

\u00a0Note That:<\/strong><\/span><\/p>\n

\u00a00.6ms of 20ms period is a 3% duty cycle (0\u00b0 Position),\u00a0<\/strong><\/span><\/p>\n

\u00a01.4ms of 20ms period is a 7% duty cycle (90\u00b0 Position),\u00a0<\/strong><\/span><\/p>\n

\u00a02.4ms of 20ms period is a 12% duty cycle (180 \u00b0 Position).\u00a0<\/strong><\/span><\/p>\n

 <\/p>\n


\n

\u00a0 \u00a0Servo Motor Control With PIC Microcontrollers\u00a0 \u00a0<\/span><\/strong><\/span><\/h3>\n

 <\/p>\n

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. We’ve discussed the reasons for this in the previous tutorial and put it to the test.<\/span><\/p>\n

 <\/p>\n

What Are Some Design Techniques & Solutions To Control Servo Motors?<\/span><\/strong><\/h4>\n

 <\/p>\n

1 CCP PWM Hardware Module & Lowering Down Fosc using LP internal RC oscillator <\/strong><\/span><\/del><\/p>\n

(This solution was implemented in the previous tutorial PART-1<\/a>).<\/p>\n

2 Software PWM Generation Using Timer or Compare Match Interrupts<\/strong><\/span><\/del><\/p>\n

(This is the solution was implemented in the previous tutorial PART-2<\/a>).<\/p>\n

3 Using PCPWM module in Microchip PIC Microcontrollers<\/strong><\/span><\/p>\n

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.<\/span><\/p>\n

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.<\/span><\/p>\n

4 Using NCO (Numerically Controlled Oscillator) Module<\/strong><\/span><\/p>\n

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.<\/span><\/p>\n

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!<\/span><\/p>\n

5 The CCP Capture + Timer1 = 16-Bit PWM!<\/strong><\/span><\/p>\n

(This is the technique we’ll be implementing today in this tutorial).<\/p>\n

Theoretically, the 16-Bit Timer1 module can be combined with the CCP Capture module and use the CCPR1 16-Bit register pair to work as a Duty Cycle controller. We’ll end up having a 16-Bit of resolution PWM signal with a wide band of frequency control!<\/span><\/p>\n

This means, we can effectively push the CCP PWM beyond its fundamental limits in terms of 10-Bit resolution, so we end up with a x64 times more levels of resolution in the duty cycle which will potentially increase our control ability over the servo motor’s angle!<\/span><\/p>\n

Read The Article For High-Resolution (16-Bit) PWM Generation With Capture+Timer Technique<\/a><\/span><\/p>\n

 <\/p>\n

 <\/p>\n

Well, I think there still be other solutions like using external I2C servo drivers 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 about this!<\/span><\/p>\n

 <\/p>\n


\n

\u00a0 \u00a0Servo Motor Control With High-Resolution PWM\u00a0 \u00a0<\/span><\/strong><\/span><\/h3>\n

 <\/p>\n

Prerequisites<\/strong><\/span><\/h4>\n

1<\/strong> Timer Modules Tutorial<\/a><\/p>\n

2<\/strong> Timer Preloading<\/a><\/p>\n

3<\/strong> CCP Capture+Timer 16-Bit PWM Article<\/a><\/p>\n

4<\/strong> ADC Tutorial<\/a><\/p>\n

5<\/strong> Servo Motor Control PART-1<\/a><\/p>\n

6<\/strong> Servo Motor Control PART-2<\/a> (the previous tutorial)<\/p>\n

How To Generate Servo Motor Control Signal?<\/strong><\/span><\/h4>\n

Using the CCP Compare+Timer technique for generating a high-resolution PWM is not so difficult. We only need to find out the timer preload value using the formula down below. Assuming Fosc=48MHz, Prescaler=4, Desired FPWM=50Hz. Therefore, we can solve for TMR1 (the value to be preloaded)<\/span><\/p>\n

\"High<\/p>\n

50 = 48000000 \/ 4 x 4 x (65536-TMR1)<\/span><\/p>\n

TMR1 = 5536<\/strong><\/span> (the preload value)<\/span><\/p>\n

Now, it’s time to figure out how to get the desired duty cycle as well. The duty cycle in order to be in the range of 3% up to 12% for a full range rotation (0\u00b0 up to 180\u00b0), we need to write the convenient data to the CCPR1 register pair.<\/span><\/p>\n

By simple calculations & mapping, it turns out that the CCPR1 values which correspond to duty cycle ranging from 3% up to 12% falls within the range (7335 for 3% DC up to 12735 for 12% DC). And any value in between can be easily found by mapping.<\/span><\/p>\n

\"Mapping<\/p>\n

Now, we can set the frequency of the PWM to 50Hz and move the duty cycle in the range from 3% up to 12% so we’re almost ready to test out this technique on a servo motor. I’ll create a couple of LABs down below to highlight the strength of this technique.<\/span><\/p>\n

 <\/p>\n


\n

\u00a0 \u00a0Servo Motor Sweep 16Bit PWM – LAB6\u00a0 \u00a0<\/span><\/strong><\/span><\/h3>\n

 <\/p>\n\n\n\n\n\n\n
Lab Name<\/span><\/strong><\/span><\/td>\nHigh-Resolution 16-Bit PWM – Servo Motor Sweep<\/span><\/td>\n<\/tr>\n
Lab Number<\/span><\/strong><\/span><\/td>\n43<\/span><\/td>\n<\/tr>\n
Lab Level<\/span><\/strong><\/span><\/td>\nIntermediate<\/span><\/td>\n<\/tr>\n
Lab Objectives<\/span><\/strong><\/span><\/td>\nLearn how to generate software PWM signals @ 50Hz and control the position of a servo motor.<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n

 <\/p>\n

\u00a0 \u00a0 \u00a0 \u00a01. Coding\u00a0 \u00a0 \u00a0 \u00a0<\/strong><\/span><\/h4>\n

 <\/p>\n

Open<\/strong> the MPLAB IDE and create a new project name it “Servo_16Bit_PWM”. If you have some issues doing so, you can always refer to the previous tutorial using the link below.<\/span><\/p>\n

\"Create<\/a><\/p>\n

Set<\/strong> 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.<\/span><\/p>\n

\"\"<\/a><\/p>\n

Now, open the main.c<\/strong> file and let’s start developing the firmware for our project.<\/span><\/p>\n

The full code listing for this lab is as follows<\/span><\/p>\n

\/*\r\n* File: main.c\r\n* Author: Khaled Magdy\r\n* LAB: Servo Motor Control - LAB6\r\n* PIC18F2550 - 4MHz OSC With PLL -> Fosc = 48MHz\r\n*\/\r\n#include <xc.h>\r\n#include \"config.h\"\r\n#include <stdint.h>\r\n#include \"Servo.h\"\r\n\r\nvoid main(void) {\r\n\r\n  TRISC2 = 0;\r\n  Servo_Init();\r\n  while(1) \r\n  {\r\n    for(int i=0; i<180; i++) \r\n    {\r\n      Servo_MoveTo(i);\r\n      __delay_ms(5);\r\n    }\r\n    __delay_ms(500);\r\n    for(int i=180; i>0; i--)\r\n    {\r\n      Servo_MoveTo(i);\r\n      __delay_ms(5);\r\n    }\r\n    __delay_ms(500);\r\n  }\r\n  return;\r\n}\r\n\r\nvoid __interrupt() ISR()\r\n{\r\n  if(TMR1IF)\r\n  {\r\n    CCP1CON = 0x00;\r\n    PWM1 = 1;\r\n    CCP1CON = 0x09;\r\n    TMR1IF = 0;\r\n    TMR1 = PreLoad; \/\/ Timer1 Preloading\r\n  }\r\n}<\/pre>\n

 <\/p>\n

Project Files Download<\/strong><\/a><\/p>\n

 <\/p>\n

\u00a0 \u00a0 \u00a0 \u00a02. Simulation\u00a0 \u00a0 \u00a0 \u00a0<\/strong><\/span><\/h4>\n

 <\/p>\n

\"Servo<\/p>\n

 <\/p>\n

\u00a0 \u00a0 \u00a0 \u00a03. Prototyping\u00a0 \u00a0 \u00a0 \u00a0<\/strong><\/span><\/h4>\n

 <\/p>\n

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

Here is a short demo video for the running test for this LAB<\/strong><\/p>\n

 <\/p>\n\n\n\n\n
\"Play<\/a><\/td>\n<\/tr>\n