Blog Entry




Basic Servo Motor Controlling with Microchip PIC Microcontroller

February 17, 2009 by , under Robotics.




The servo motor is widely used in model hobbyist such as airplane R/C model for moving the rudder, ailerons, elevators and acceleration control or in the car R/C model for steering and acceleration control. In this tutorial we will learn how to control the servo motor as well as the simple close loop control algorithm for this servo motor.

The servo motor basically is a high quality geared DC motor equipped with electronic circuit for controlling the DC motor rotation direction and position. Currently there are two types of servo motor available on the market, the first one is called standard servo and the other one is called continues servo; standard servo can rotate to maximum (clockwise or counterclockwise) of 120 to 180 degrees while continues servo can rotate up to 360 degrees in both direction.

The Servo Motor

The servo motor use PWM signal for controlling the DC motor; unlike normal PWM usually used in ordinary DC motor; this PWM signal is not use for controlling the rotation speed, instead it is use for controlling the motor direction or position. Most servo motor will work well on 50 Hz of PWM frequency; this mean the PWM signal should have a period of 20ms. The electronic circuit inside the servo motor will response to the PWM signal width; the 0.7ms to 1ms PWM width will make the servo motor to turn clockwise (CW), the 1.7ms to 2ms PWM width will make the servo motor to turn counterclockwise (CCW). For the standard servo the 1.5ms PWM width will turn the servo motor to its center.

The exact PWM width is depend on the servo motor types and brands; on this tutorial we will use the Parallax Continues Servo which using 1ms and 2ms respectively. The Parallax servo motor consists of three wires colored with White, Red and Black. The Red and Black wires go to the Vcc and Gnd, while the White wire is use to feed the PWM signal from the PIC 16F690 microcontroller I/O port.

Driving the servo motor using PIC 16F690 microcontroller might be simple as you thing at the first time; we just use the PIC PWM peripheral to do the job (you could learn of how to use the PIC PWM peripheral on the article H-Bridge Microchip PIC Microcontroller PWM Motor Controller posted on this blog), but looking at the PIC 16F690 datasheet with the 8 Mhz of internal frequency clock (use in this tutorial) and using maximum prescaler of 16 (TIMER2) the minimum PWM frequency we could achieve can be calculated using this formula:

PWM period = [( PR2 + 1) ] x 4 x Tosc x (TMR2 prescaler value) second

Using maximum PR2 register value of 0xFF (255 decimal), we will get this result:

PWM period = (255 + 1) x 4 x (1 / 8000000) x 16= 0.002048 second
PWM frequency = 1 / PWM period = 1 / 0.002048 = 488.28 Hz

The 488.28 Hz frequency is still too high from the servo motor working frequency of 50Hz; therefore this leads us to these three methods bellow:

  • Keep using the PIC PWM peripheral and lower the operation frequency by setting the OSCCON register and PR2 register until it meets the servo motor frequency requirement. This approach will secrify the program execution speed as we will operate the PIC Microcontroller with the 500 khz clock speed, so we simply not choose it.
  • Secondly, we create our own PWM function to mimic the PWM signal as follow: turn on the PORT, make some 2 ms delay, turn off the PORT, and make some 18 ms delay and so forth. This approach is what I called a dirty method which is not the efficient way to do it, so we just drop this method.
  • The third approach is to use the PIC 16F690 microcontroller TIMER0 with the interrupt to actually generate the PWM signal as the TIMER0 have wider prescaler to choose comparing to the TIMER2, but unfortunately the PWM peripheral on the PIC 16F690 only work with TIMER2 not TIMER0. Therefore we will make this TIMER0 as our PWM base generator for driving the servo motor on this tutorial. The principal we learn here could be applied to the other type of PIC Microcontroller or AVR Microcontroller as well.

Instead of just demonstrating the servo motor to rotate clockwise and counterclockwise, I decide to make it more challenging and attractive by putting the LDR (light dependent resistor) as the light sensor to our servo motor and make this servo motor to behave as the light seeking machine; …hey this sound like we are touching the robotics field; …hmm yes isn’t it cool, as we know most of the embedded robotics hobbyist widely use the servo motor for robot’s arms, walkers robots, light seeking robot (know also as photovore robot) and many more.

The LDR (Light Dependent Resistor)

By just looking at the name, is clear that this is the type of resistor that its resistance depends on the light intensity; it’s also called photoresistor, made from the Cadmium Sulfide (CdS) one of the semiconductor material. The LDR will response to light it received, the brightest the light the smaller its resistance and vise versa; on the complete darkness the LDR resistance will become very high (about 150K Ohm; for the LDRs I use in this tutorial)

From the above circuit diagram we connect serially the LDR with the 10K trimport and use it as the voltage divider circuit to the PIC 16F690 analog input AN4 and AN5 (you could learn about Basic Resistor Circuit posted in this blog); therefore the variation on the light intensity received by the LDR will result on the variation of the voltage level to the PIC analog input port. Because of the LDR resistance vary widely among the types and brands, therefore we use the trimport and I suggest that you preset it to about 5 K Ohm on the first time and later on you can adjust it as needed.

The LDR pairs will be functioned as the light sensor that controlled the servo motor position toward the light source; therefore to get the maximum performance we put these two LDRs inside the paper tube in such a way that their position is about 45 degrees away from the light source center (see the top view picture above).

The Light Seeking Head Construction

One of my favorite construction material is to use a thick paper (…yes it’s a paper) for fast prototyping as its easy to cut, bend, light weight and quiet strong; our seeking light head project use just a thick paper to demonstrate the servo motor concept or what we usually called it as the proof of concept (POC); so let’s do the cut and paste; and of course you could experiment with any kind of head forms or faces as you like and these following pictures can be use as the starter.

The following is the list of hardware and software used in this tutorial:

1. Thick paper, scissor, glue, duct tape and spray paint for our light seeking head
2. One continues servo motor (in this project I’am using Parallax continues servo)
3. Two LDR
4. Two Trimport 10K
5. PICJazz 16F690 learning board from ermicro (the schema)
6. JazzMate 2576-5V power board, the 5 volt switching power supply
7. Microchip PICKit2 Programmer
8. Microchip MPLAB IDE v8.0 or higher
9. HITEC PICC-Lite PICC-Lite Version 9.60PL1

Now let’s take a look at the C code that makes this thing happen:

// ***************************************************************************
//  File Name    : servo.c
//  Version      : 1.0
//  Description  : Servo Motor Controller
//                 Using TIMER0 for Generating Servo PWM
//  Author       : RWB
//  Target       : PICJazz 16F690 Board
//  Compiler     : HITECT PICC-Lite Version 9.60PL1
//  IDE          : Microchip MPLAB IDE v8.00
//  Programmer   : PICKit2
//  Last Updated : 03 Jan 2009
// ***************************************************************************
#include <pic.h>
/*   PIC Configuration Bit:
**   INTIO     - Using Internal RC No Clock
**   WDTDIS    - Wacthdog Timer Disable
**   PWRTEN    - Power Up Timer Enable
**   MCLREN    - Master Clear Enable
**   UNPROTECT - Code Un-Protect
**   UNPROTECT - Data EEPROM Read Un-Protect
**   BORDIS    - Borwn Out Detect Disable
**   IESODIS   - Internal External Switch Over Mode Disable
**   FCMDIS    - Monitor Clock Fail Safe Disable
*/
__CONFIG(INTIO & WDTDIS & PWRTEN & MCLREN & UNPROTECT \
  & UNPROTECT & BORDIS & IESODIS & FCMDIS);
// Using Internal Clock of 8 Mhz
#define FOSC 8000000L
// Servo definition and variables
#define MAX_VALUE 200
#define CCW_ROTATION MAX_VALUE - 20
#define CW_ROTATION MAX_VALUE - 10
#define STOP_ROTATION MAX_VALUE
#define THRESHOLD_VALUE 50
unsigned char pulse_max=0;
unsigned char pulse_top=0;
unsigned char top_value = 0;
static void interrupt isr(void)
{
  if(T0IF) {	            // TIMER0 Interrupt Flag
    pulse_max++;            // Pulse Max Increment
    pulse_top++;            // Pulse Top Increment

    /* MAX_VALUE=200 turn off the pulse */
    if (pulse_max >= MAX_VALUE) {
      pulse_max=0;
      pulse_top=0;
      RC2=0;                // Turn off RC2
    }

    /* top_value = MAX_VALUE - n, n=10: 10 x 0.1ms = 1.0ms, n=20: 20 x 0.1ms = 2.0ms */
    /* 2ms -> CCW Rotation, 1ms -> CW Rotation */
    if (pulse_top == top_value) {
      RC2=1;                // Turn On RC2
    }
    TMR0 = 156;             // Initial Value for 0.1ms Interrupt
    T0IF = 0;		    // Clear TIMER0 interrupt flag
  }
}
void main(void)
{
  unsigned char ldr_left;
  unsigned char ldr_right;
  int ldr_diff;
  OSCCON=0x70;         // Select 8 Mhz internal clock
  /* Initial Port Used */
  TRISC = 0x03;        // Set RC0 and RC1 as input others as Output
  ANSEL = 0x30;        // Set PORT AN4 and AN5 as analog input
  ANSELH = 0x00;       // Set PORT AN8 to AN11 as Digital I/O
  PORTC = 0x00;        // Turn Off all PORTC
  /* Init Servo Pulse */
  pulse_max=0;
  pulse_top=0;
  top_value = MAX_VALUE; // top_value = MAX_VALUE: Servo Motor Stop
  /* Initial ADC */
  ADCON1=0b00110000;   // Select the FRC for 8 Mhz
  /* Init TIMER0: Period: Fosc/4 x Prescaler x TMR0
     0.0005 ms x 2 * 100 = 0.1 ms */
  OPTION = 0b00000000; // 1:2 Prescaller
  TMR0=156;            // Interupt every 0.1 ms
  T0IE = 1;		       // Enable interrupt on TMR0 overflow
  GIE = 1;		       // Global interrupt enable

  for(;;) {
    /* Read the ADC here */
    ADCON0=0b00010001;       // select left justify result. ADC port channel AN4
    GODONE=1;	             // initiate conversion on the channel 4
    while(GODONE) continue;  // Wait for ldr_left conversion done
    ldr_left=ADRESH;         // Read 8 bits MSB, Ignore 2 bits LSB in ADRESL
    ADCON0=0b00010101;       // select left justify result. ADC port channel AN5
    GODONE=1;	             // initiate conversion on the channel 5
    while(GODONE) continue;  // Wait for ldr_right conversion done
    ldr_right=ADRESH;        // Read 8 bits MSB, Ignore 2 bits LSB in ADRESL

    /* Get the different */
    ldr_diff=ldr_left - ldr_right;    

    if ((ldr_diff >= -THRESHOLD_VALUE) && (ldr_diff <= THRESHOLD_VALUE)) {
      top_value = MAX_VALUE;     // Stop the Servo Motor
    } else {
      if (ldr_diff > THRESHOLD_VALUE) {
        top_value = CCW_ROTATION;  // Counterclockwise Rotation
      } else {
        top_value = CW_ROTATION;   // Clockwise Rotation
      }
    }
  }
}
/* EOF: servo.c */

PIC Microcontroller TIMER0 Peripheral

The heart of the servo motor PWM pulse is rely on the PIC TIMER0 peripheral; this TIMER0 together with the interrupt service will be used as our servo motor base PWM pulse generator. The TIMER0 peripheral is actually the 8-bit counter that always increase it count base on the clock pulse supply to it. The PIC microcontroller TIMER0 counter use the TMR0 register to hold the counted number, each of the clock pulse will increase the TMR0 register value by 1 until it reach its maximum value of 255 and start all over again from 0 (overflow); and when this happening the PIC TIMER0 peripheral will rise the interrupt signal. The interrupt signal raised by the PIC TIMER0 peripheral will be interpreted by the microcontroller as this following explanation:

1. Stop whatever you are doing right now
2. Save the current execution address for later used in memory; this area of memory is known as the stack area
3. Jump to the assigned TIMER0 interrupt service address
4. Start execute the code in the TIMER0 interrupt service address
5. Return back to your last task by loading the last execution address in the stack area and continue execute the code from it.

The principal we use here is to set the TMR0 register to overflow every 0.1 ms and set our own counter variable (pulse_max) to count up to maximum 200; this will give us the constant 20 ms period which is the same as 50 Hz frequency required by our servo motor.

The TIMER0 period could be calculated using this formula bellow:

TIMER0 period = [(TMR0 + 1)] x 4 x Tosc x (TIMER0 prescaler value) second

By selecting the TIMER0 prescaler of 2; PS2=0, PS1=0 and PS0=0 bits in OPTION_REG register and initial the TMR0 register value to 156 (99 more counts to reach its maximum value of 255) with the system frequency clock of 8 Mhz, the PIC microcontroller TIMER0 overflow period can be calculated as follow:

TIMER0 period = [((255 – 156) + 1)] x 4 x 1/8000000 x 2 = 0.0001 second = 0.1 ms

The following C code is used to initialize the PIC 16F690 TIMER0 peripheral:

/* Init TIMER0: Period: Fosc/4 x Prescaler x TMR0
   0.0005 ms x 2 * 100 = 0.1 ms */
OPTION = 0b00000000; // 1:2 Prescaller
TMR0 = 156;          // Interupt every 0.1 ms
T0IE = 1;	     // Enable interrupt on TMR0 overflow
GIE = 1;	     // Global interrupt enable

In order to generated the PWM pulse, we need to have two separate variable counter here; one is the pulse_max variable used for resetting the RC2 port (logical “0“) which connected to the servo motor and secondly is the pulse_top variable used to set the RC2 port; the pulse_top variable will be compared to the top_value variable; and if it equal than we will set the RC2 port (logical “1“).

From the timing diagram above the pulse_max variable is used to hold our own PWM counter and the pulse_max value increase every 0.1ms (TMR0 overflow). By the time it reaches the maximum value of 200 than we will reset the RC2 port together with the pulse_max variable and the pulse_top variable. The pulse_top value also increase every 0.1 ms and its value constantly compared to the top_value variable value; when it equal we will set the RC2 port (logical “1“); for example by setting the top_value variable to 190, means when the pulse_top variable reach 190, the RC2 port will be set and when pulse_max reach 200 the RC2 port will be reset, this will make our servo motor to turn clockwise. Again by setting the top_value variable to 180 the servo motor will turn counterclockwise as it receive the 2 ms of PWM signal. Bellow is the code inside the TIMER0 interrupt service routine:

if(T0IF) {		  // TIMER0 Interrupt Flag
  pulse_max++;            // Pulse Max Increment
  pulse_top++;            // Pulse Top Increment
/* MAX_VALUE=200 turn off the pulse */
  if (pulse_max >= MAX_VALUE) {
    pulse_max=0;
    pulse_top=0;
    RC2=0;                // Turn off RC2
  }
  /* top_value = MAX_VALUE - n, n=10: 10 x 0.1ms = 1.0ms, n=20: 20 x 0.1ms = 2.0ms   */
  /* 2ms -> CCW Rotation, 1ms -> CW Rotation */
  if (pulse_top == top_value) {
    RC2=1;               // Turn On RC2
  }
  TMR0 = 156;             // Initial Value for 0.1ms Interrupt
  T0IF = 0;               // Clear TIMER0 interrupt flag
}

 

Because the TIMER0 interrupt flag bit (T0IF) in the INTCON register is not automatically reset to 0, therefore we have to manually reset it inside the TIMER0 interrupt function.

As you see by using this method the program code for controlling the servo motor will be much easier now as we only assign the correct value to the top_value variable and let the PIC microcontroller TIMER0 peripheral do the job by supplying the required PWM signal to the servo motor as it shown on this following C code example:

#define MAX_VALUE 200
#define CCW_ROTATION MAX_VALUE - 20
#define CW_ROTATION MAX_VALUE - 10
#define STOP_ROTATION MAX_VALUE
top_value = MAX_VALUE;     // Stop the Servo Motor
top_value = CCW_ROTATION;  // Counterclockwise Rotation
top_value = CW_ROTATION;   // Clockwise Rotation

The Light Seeking Sensor

As I mention before that instead of just making our servo motor to rotate clockwise (CW) or counterclockwise (CCW); we will use it to position our paper head toward the light source. This can be achieve by using the pair of LDRs to detect the light source and base on the light intensity information received by the LDR pair; we make the servo motor to rotate in such away that our head paper will always facing the light source as seen on this following picture

The LDR pairs will constantly give the light source position feedback to the servo motor so it can always turn our paper head toward the light source; this is known as the close loop control which is one of the most important topics in the embedded system.

The method of controlling the paper head we use here is called the “on-off controller” or “bang-bang controller“; this is the simplest method of controlling usually found in the heater, air-condition and refrigerator for controlling the temperature or in the line follower robot and summo wrestling robot. The more advanced controlling method is called the “PID (Proportional, Integral, Derivative) controller” which is used such as in motor speed controlling, however we will not discuss this controlling method on this tutorial, but once you understand and implement the principal of the basic close loop control presented here, later on it will be easier for you to learn this PID controlling method.

The algorithm we use here is base on the differential value returned by the left LDR and the right LDR; the positive result will rotate the servo motor counterclockwise and the negative result will rotate the servo motor clockwise. The servo motor will keep rotating until the different result is zero; which mean the paper head is facing the light source.

To make the servo motor rotate smoothly we use the threshold value or known as the hysteresis band in the on-off controller method, this mean if the different result is within the hysteresis band the servo motor will always stop and if the different result is outside the hysteresis band the servo motor will start to rotate counterclockwise or clockwise as shown in this following time diagram:

The following is the C code for implementing the on-off controller method with the hysteresis band:

#define THRESHOLD_VALUE 50
/* Get the different */
ldr_diff=ldr_left - ldr_right;    

if ((ldr_diff >= -THRESHOLD_VALUE) && (ldr_diff <= THRESHOLD_VALUE)) {
  top_value = MAX_VALUE;     // Stop the Servo Motor
} else {
  if (ldr_diff > THRESHOLD_VALUE) {
    topvalue=CCW_ROTATION;  // Counterclockwise Rotation
  } else {
    topvalue=CW_ROTATION;   // Clockwise Rotation
  }
}

The LDRs value is read by the PIC ADC peripheral through the analog input port channel 4 (AN4) and channel 5 (AN5); when the left LDR received more light compare to the right LDR the voltage level input on the AN4 port will be more higher and the different result in ldr_diff variable will be positive; when the right LDR received more light than the voltage level input on the AN5 port will be more higher and the different result in ldr_diff variable will be negative. The following is the C code used to read the LDR’s voltage level:

/* Read the ADC here */
ADCON0=0b00010001;       // select left justify result. ADC port channel AN4
GODONE=1;	             // initiate conversion on the channel 4
while(GODONE) continue;  // Wait for ldr_left conversion done
ldr_left=ADRESH;         // Read 8 bits MSB, Ignore 2 bits LSB in ADRESL
ADCON0=0b00010101;       // select left justify result. ADC port channel AN5
GODONE=1;	             // initiate conversion on the channel 5
while(GODONE) continue;  // Wait for ldr_right conversion done
ldr_right=ADRESH;        // Read 8 bits MSB, Ignore 2 bits LSB in ADRESL

To learn more about the PIC ADC (analog to digital conversion) peripheral you could read the PIC Analog to Digital Converter C Programming posted in this blog.

Inside the C Code

This program is start by initializing the PIC port used in this tutorial and continue with the PIC ADC peripheral clock selection in the ADCON1 register for using the 8 Mhz internal clock and the last is to initial the PIC TIMER0 peripheral. After the initialization process the program enter the endless loop where we read the voltage level returned by the left LDR and the right LDR and do the “bang-bang controller” algorithm.

/* Initial Port Used */
TRISC = 0x03;        // Set RC0 and RC1 as input others as Output
ANSEL = 0x30;        // Set PORT AN4 and AN5 as analog input
ANSELH = 0x00;       // Set PORT AN8 to AN11 as Digital I/O
PORTC = 0x00;        // Turn Off all PORTC

It’s important to remember that we have set the port to the analog input mode first before we use it for reading the analog signal.

Downloading the Code

After compiling and simulating your code hook up your PICKit2 programmer to the PICJazz 16F690 board ICSP port turn the PICJazz 16F690 power. From the MPLAB IDE menu select Programmer -> Select Programmer -> Pickit2 it will automatically configure the connection and display it on the PICkit2 tab Output windows:

Now you are ready to down load the code from MPLAB IDE menu select Programmer -> Program; this will down load the HEX code into the PICJazz 16F690 board:

Basic Servo Motor Controlling with Microchip PIC Microcontroller

Now just relax and enjoy your light seeking head in action:

Bookmarks and Share


bookmark bookmark bookmark bookmark bookmark bookmark bookmark bookmark bookmark bookmark




109 Responses to “Basic Servo Motor Controlling with Microchip PIC Microcontroller”

11.02.11#1

Comment by unni.0p.

is the Processor fan of computer a servo motor?
can i use that for a servo motor?

11.02.11#2

Comment by rwb.

@pichaha: As long as the supply power (i.e. polarity and voltage) is within the servo motor specification than your servo motor will be fine. The wrong PWM frequency only effecting the servo motor rotation.

@unni.0p: No its not a servo motor, it usually called brushless DC motor. The servo motor used in this project is a combination of geared DC motor with the electronic motor control circuit and position feedback mechanism inside.

12.02.11#3

Comment by pichaha.

Hi,
I would like to ask, can the servo motor be driven using 5V voltage generated from 7805 voltage regulator??
If i am using 9V battery as the regulator input. Thanks a lot.

13.02.11#4

Comment by rwb.

Yes, as long as you use the 5 volt servo motor specification

15.02.11#5

Comment by pichaha.

Hi,
My servo is working already, the motor malfunction was caused by the power shortage of the supply. But I have met another question here…I want to let my servo to turn in clockwise direction, so I let the pwm signal to has 1.0ms pulse width, after that I put a delay loop to make it turn in a certain degree(I use push button to trigger), then I stop the motor, there are still other instructions after that. My problem is the rotation works only when my delay loop is long enough. When my delay loop is short, it sometime works and sometime not works. So how if i want my servo to move just a small ditance? Any suggestion? Thanks a lot.

16.02.11#6

Comment by rwb.

Experiment, improve your delay and read button program routine

16.02.11#7

Comment by pichaha.

What do you mean by improve my delay, do you mean prolong it? What if I just want my servo to move for a short distance(small degree)? Thanks a lot

16.02.11#8

Comment by rwb.

In order to rotate the servo motor clockwise at certain degree you need to supply the 1 ms PWM at certain period of time. That’s what I mean that you have to “experiment” with it (i.e. “delay loop”), because you need to know the require period before stop the PWM. The read button routine also could effecting this behavior (bounced effect).

27.02.11#9

Comment by Eric88.

To: rwb

can you provide me a basic servo motor assembler code controlling with Microchip PIC Microcontroller ??
thanks…

27.02.11#10

Comment by rwb.

No, I don’t have the assembler code for this project.

05.03.11#11

Comment by milanivic.

can you tell me, why output mesage error:
– undefined identifier “OPTION”
– undefined identifier “GODONE”
thanks

05.03.11#12

Comment by rwb.

Make sure you install and configure the Microchip MPLAB IDE and Microchip HITECT PICC C compiler correctly.

06.03.11#13

Comment by milanivic.

Thenks, I instal MPLAB IDE 8.63 and everythings working.
Many thanks for yuor help!

12.03.11#14

Comment by Secky.

Hi,

What a great and detail article you have, learn a lot from it. thank you.=)

Just wondering can I use this neat method to control more servos by creating another variable pulse_top2 and top_value2 and add in the following code?

if (pulse_top2 == top_value2) {
RC3=1; // Turn On RC3
}

13.03.11#15

Comment by rwb.

Yes you could experiment with it and make some adjustment to the TIMER0 counter register (TMR0) initial value for the timing.

25.09.11#16

Comment by nerv.

can i use a pic16f684 for this project

26.09.11#17

Comment by rwb.

Yes you could try to use the 14-Pins Microchip PIC16F684 microcontroller. Just remember that PIC16F684 doesn’t have the ANSELH register.

30.11.11#18

Comment by BF1Quang.

Hi rwb, I’m Quang and I’m doing a project relating to RC servo, I use 6 RC servos to make a robot arm with 5 degrees of freedom! I can control the RC Servo now, I’m using 3 types of RC Servo (Hitec, Futaba and TowerPro). Unfortunately, I got problems with the power of the Servo and the ATmega, I intend to use 6V battery to power the RC Servo but it’s maybe excess the limit voltage for the MCU. I’m really need your advice to solve that. What should I do, and can you give me a Schematic to wire the servo and the MCU. I mean if the MCU and the Servo have the same power supply, they can operate smoothly, but when I’d separated them I got problems (The Servo didn’t work!!!). I’m looking forward to your guide! Thank you very much!!

02.12.11#19

Comment by rwb.

You could use two separate power supply i.e. 5 volt for the Microcontroller and 6 volt for the servo as long as they both share the same ground. The other option, you could use a diode (e.g. 1N4001/2) to reduce the 6 volt to about 5.3 volt for the Microcontroller. You could read more information about this subject on this following article:

Diode for reducing the voltage output

07.12.11#20

Comment by BF1Quang.

Thank you so much, it’s really really helpful, I used 7805! ^^

28.12.11#21

Comment by nerv.

hye,

i have tried running the program using mplab ide, it works but when i use proteus to do the simulation it also works but there are around 6752 warning for this part :
while(GODONE) continue; // Wait for ldr_left conversion done
0x0057 – ADC conversion started before wait time has expired following previous conversion or channel change.
0x0062 – ADC conversion started before wait time has expired following previous conversion or channel change.

what can be done?or this this ok once i construct the real thing..

29.12.11#22

Comment by rwb.

Yes, just construct the real project.

05.01.12#23

Comment by nerv.

hye,

why i can’t burn the code into my 16f690,im using pickit 2..

this error pop out :
PK2Error0027: Failed verify (Address = 0x0 – Expected Value 0x3000 – Value Read 0x3FFF)

tq.

06.01.12#24

Comment by rwb.

Make sure you install the Microchip MPLAB IDE and connect your Microchip PICKit2 to the PIC16F690 microcontroller Correctly.

10.01.12#25

Comment by nerv.

i already construct my circuit,the problem is when i point the light to each of the ldr i can hear and see the motor moving CCW & CW but with very very little movement and i can hear it like moving foward and reverse when i point the light to the LDR.Why is this?

TQ..

10.01.12#26

Comment by nerv.

and my white pin which is the signal is only around 0.5 volt, where else the requirement is 3.3v right?why is this please help me..tq.

10.01.12#27

Comment by rwb.

Please check your servo operating voltage specification, make sure you recheck and use the same schematic/circuit as shown on the project.

10.01.12#28

Comment by nerv.

i am using the same servo as this project..and the same circuit.my rc2 is giving 0.5v, and is this the problem, because this servo needs 3.2 to more right for the rc2 port.and 1 more thing can i share the voltage for the servo with other’s like the LDR.

11.01.12#29

Comment by rwb.

Remember the RC2 port output is a PWM (Pulse Width Modulation) signal, therefore you need to used an oscilloscope when you want to examine its output. Using DVM (Digital Volt Meter) only give you an average value not the pulse HIGH value. Yes you could share the voltage for the servo as shown on the schematic. Again recheck your circuit.

29.02.12#30

Comment by gechihoney.

Hi your tutorials are really good.
I need to control the speed of a stepper motor, at the moment I’m using delays to simply vary the amount of time the windings of my motor are energised. But I want to know how to use PWM signals to control the motor instead. Pls help

01.03.12#31

Comment by rwb.

The stepper motor used different method of rotating the rotor. You could use the TIMER to control the speed instead of the delay. For more information about using the stepper motor you could read this following article:

Using Transistor as a Switch

26.04.12#32

Comment by john.

hye,
i try to use your program in my pic16f887 but it does not worked at all. Can you give me some suggestion or modification that can be made to fit to this pic16f887. please help me. sorry for my bad english.

01.05.12#33

Comment by rwb.

You could read the comment #14 above.

09.06.12#34

Comment by pradeep_K_B.

hi,can i control 2 or more servos using one 16f690???

11.06.12#35

Comment by rwb.

Yes, you can and of course you need to modify this program.

12.06.12#36

Comment by fariskhan101.

where do i change the configuration bit and the OSCCON for pic 16f8877a and change it into?thank you i really need help.im new to this…

12.06.12#37

Comment by fariskhan101.

undefined identifier “OSCCON”
undefined identifier “ANSEL”
undefined identifier “ANSELH”
how can i solve this if i wanna use if for 16f877a

12.06.12#38

Comment by rwb.

You need to change the configuration bit and the OSCCON register when you use PIC16F877A since the PIC16F877A microcontroller has no internal oscillator clock like PIC16F690. The PIC16F877A also don’t have the ANSEL and ANSELH registers.

13.06.12#39

Comment by fariskhan101.

IF im using pic16f886,but i want to use a 4mhz external cyrstal how do i do so?

17.06.12#40

Comment by rwb.

The default OSCCON setup is 4 MHz or you could use this following statement:

OSCCON=0x60; // Select 4 Mhz internal clock (default)

For more information please read the Microchip PIC16F886 Microcontroller datasheet

18.06.12#41

Comment by fariskhan101.

thank you,i read it but i cant really understand.so by changing this,im i still able to move this servo motor and achieve a signal if i use the oscilator?

20.06.12#42

Comment by rwb.

Yes, you need to modify the TIMER0 timing in order to achieve the same signal result. Please read the article and the Microchip PIC16F886 microcontroller datasheet for more information.

12.08.12#43

Comment by iwestbury.

Thank you very much. I was looking for a servo interface to a PIC. This is an excellent article and simply the best explanation I have found of creating a PWM pulse with the hardware timers.

Thanks again, it was extremely useful.

07.09.12#44

Comment by alex.

Thank you very much, your tutorial is super good. However I have a problem when I implemented your “code” in MikroC. I got an error, for some reason MicroC doesn’t recognize the following expression:

GODONE=1;

Could you help me solve this problem?
Thank you so much

07.09.12#45

Comment by rwb.

In MikroC you should use GO_DONE_bit instead of GODONE in Microchip HI-TECH C. Or simply use the MikroC ADC_Read() ADC library to read the ADC value.

08.09.12#46

Comment by alex.

Hi rwd,

Thank you very much, you are very helpful. Quick question, by any chance do you have any tutorials on ultrasound in arrays configuration?

thank you!!

08.09.12#47

Comment by rwb.

No, I don’t have it.

20.09.12#48

Comment by alex.

Hello rwb
Question: I am attempting to implement your project, but I am getting the following error.

Error [192] C:\Documents and Settings\ale\Desktop\FIU\Senior\Codigos\infra-II\Infra.c; 92.1 undefined identifier “OPTION”
Error [192] C:\Documents and Settings\ale\Desktop\FIU\Senior\Codigos\infra-II\Infra.c; 100.1 undefined identifier “GODONE”.

I am using MPLab IDEv 8.87, any recommendation!

20.09.12#49

Comment by rwb.

Check your MPLAB IDE installation and make sure you select the proper Language Toolsuite (e.g. HI-TECH Universal Toolsuite), from MPLAB IDE menu Project -> Select Language Toolsuite.

22.09.12#50

Comment by alex.

Thanks for your reply. i just added the following line of code “#define _LEGACY_HEADERS”, and compiled without problem. Now I have another question, since I my board is an easyPIC board I am using the Mikroprog to download the ” .HEX”(created in MPLab) file to the MICRO. It should work fine rigth?

22.09.12#51

Comment by rwb.

Yes you could use the mikroProg to load the HEX file produced by the Microchip MPLAB.

23.10.12#52

Comment by mirza_sd.

hey, please can you post a detail schematic of the circuit and the whole design. where i can find Jazzmate

25.10.12#53

Comment by rwb.

The schematic is shown in the project. You could Contact the sales@ermicro.com regarding the JazzMate board.

30.10.12#54

Comment by mirza_sd.

Hi, Instead of cardboard paper.

I was wondering if we install a PV panel of 4 to 6 kgs, to sense the sunlight.

would code be different from what is written and motor specification?

30.10.12#55

Comment by rwb.

For that kind of load, you need to use a big torque servo motor for moving the PV Panel. About the code you need to check the servo motor control signal pulse specification, usually it use a similar control signal pulse as described in this project.

13.03.13#56

Comment by uscahmad.

Hello rwb
Question: I am using pic18f4550 and Iam using MikroC pro and my simulation software is Proteus I have problem with the interrupt_routine the pic send me errors //stack overflow is forcing device reset //the code I am used is :
void interrupt_routine() org 0x04
{
…code truncated…
}
could you please help me to solve this problem ?
Thanks very much

29.09.14#57

Comment by Shaibu.

Hi rwb, I’ve been going through your piece and I find it very informative but I’m having a problem here trying to run the program on mplab x. program builds fine but doesn’t rotate
servo. and RC2 remains in d low state while I tried it on Proteus 7. what are tge likely problems? thank you

06.06.15#58

Comment by Peca.

Hi to everybody!
I am knew to this site and after reading this text I find that it is very informative.
But…
To obtain 50Hz I will use some other approach on Tomer2.
Let me explain.
Timer2 is 8-bit wide (counts from 0 to 255)and actually has THREE dividers:
1.prescaler-divides in steps 2,4 16,
COMPARATOR and PERIOD REGISTER – comparator compares two

06.06.15#59

Comment by Peca.

O.K. I accidentally hit some keyboard button and post the previous message and can not find the way to edit it so ignore it!
And again…
Hi to everybody!
I am knew to this site and after reading this text I find that it is very informative and useful.
But…
To obtain 50Hz I will use some other approach on Timer2.
Let me explain.
Timer2 (read carefully DS41262C-page 91) is 8-bit wide (counts from 0 to 255)and ACTUALLY has THREE dividers:
1.prescaler – divides in steps 2,4 16,
2.COMPARATOR and PERIOD REGISTER – comparator compares two values: one FROM Timer2 and the other FROM PERIOD REGISTER. When values matches COMPARATOR SEND ONE PULSE to postscaler and reset timer2. Period register is 8-bit wide and can have values from 0-255. So, THIS is that another divider with values in between 0-255!
3.postscaler – divides in steps 1, 2, 4… up to 16.

So, to achieve ~50Hz I`ll try this:
– Main oscillator is 8MHz,
– clock to prescaler is Fosc/4=8MHz/4=2MHz,
– prescaler divide by 16: 2MHz/16=125kHz (125000Hz),
– PERIOD REGISTER value to compare: 250,
– COMPARATOR comapare on every 250-th pulse from Timer2 so the output is 125kHz/250=500Hz to postscaler,
– postscaler further divide by 10: 500Hz/10=50Hz,
– after that postscaler sets flag bit TMR2IF.
Very often I am using Timer2 to have pause in milli or micro seconds.
Please, correct me if I am wrong. Thank You.