Electronic Projects, forums and more.

Go Back   Electronic Circuits Projects Diagrams Free > Electronics Categories > Robotics Chat


Robotics Chat Specific to discussions about robots and the making of.

Reply
 
Thread Tools Display Modes
Old 25th November 2007, 07:53 AM   (permalink)
Default Driving a servo motor

In this post I will demonstrate how to connect and drive a servo motor.
The brain of the servo motor is the input pulse width. The pulse width determines the servo motor's drive position.

A servo motor only has 3 wires, usually red, black and white. Red and black are +ve and ground connections, and white
is the drive connection. Usually a pulse width of 1 mS will make the servo motor to drive from one far end, and 2 mS
to the other end (180 degree). A 1.5 mS will be for middle position. However, bear in mind that every servo motor is different. You have to adjust the pulse
width accordingly.

servo1.jpg

So, all we need to do to drive the servo motor is to generate a pulse train with pulse width (PWM) of 1 mS to 2mS.

There are many ways to generate Pulse Width Modulation (PWM). We can use 555 or 556 chip, or use software with microcontroller. I like to use micro because it's versatile and it can be used as a central system.
It can be used to detect input signal and outputs waveforms to drive a motor.

There are different ways to generate PWM by sofware. We can use delay routine, Timer0, Timer0 and Timer1,
interrupt, or PWM in CCP module in some PIC micro.

I will start with the easiest method, ie, by delay routine. Please refer to block diagram and program code.

serveDelay_C.txt

Program code is for Hitec C compiler, and the delay routine can be downloaded from Hitec site. This motor drives more
than 180 degree.
The micro used is 16f84A.



To produce the pulse width:
PortB.1 is set high, delay for the required time duration then set low,and delay for 15 mS.
This process is repeated for 50 times. This method of producing PWM is not very accurate, but the pulse period for
the motor is not that critical, so this method works.
The program will make the servo motor to go to the far right, back to the middle and to the far left.
Because it takes bit longer to go to the far right when first starts, so it takes 50 pulses.

Next time I will use Timer0 method........
__________________
May the force be with you.


My project: Simple White Line Follower

http://au.youtube.com/watch?v=8Z_MmrdH4oc

http://i271.photobucket.com/albums/j...nefollower.jpg

Last edited by Wingmax; 7th December 2007 at 01:20 AM.
Wingmax is offline   Reply With Quote
Old 25th November 2007, 01:58 PM   (permalink)
Default

A servo motor only has 3 wires, usually red, black and white. Red and white are +ve and ground connections, and white
is the drive connection. Usually a pulse width of 1 mS will make the servo motor to drive from one far end, and 2 mS
to the other end (180 degree). A 1.5 mS w

Not to pic at this, but a small edit, white should be black, the image is correct. Would also suggest checking the specific servo's data sheet to make sure, read they are easy to damage if hooked up wrong.
HarveyH42 is online now   Reply With Quote
Old 25th November 2007, 10:24 PM   (permalink)
Default

Quote:
Originally Posted by HarveyH42
A servo motor only has 3 wires, usually red, black and white. Red and white are +ve and ground connections, and white
is the drive connection. Usually a pulse width of 1 mS will make the servo motor to drive from one far end, and 2 mS
to the other end (180 degree). A 1.5 mS w

Not to pic at this, but a small edit, white should be black, the image is correct. Would also suggest checking the specific servo's data sheet to make sure, read they are easy to damage if hooked up wrong.

My apology. It should be red for +ve, black for ground, and white for drive connection. As shown on my diagram. However, I couldn't draw white line as it won't show up on white background. This is based on my experience and usually this is the case. But of course, always check the specs.
Sorry if I caused any problem for any body regarding this.
__________________
May the force be with you.


My project: Simple White Line Follower

http://au.youtube.com/watch?v=8Z_MmrdH4oc

http://i271.photobucket.com/albums/j...nefollower.jpg
Wingmax is offline   Reply With Quote
Old 26th November 2007, 01:09 AM   (permalink)
Default

I should apologize, I didn't mean to be critical. This is a good thing. You can edit your own past posts and correct typing errors. Figured you were going to keep adding more to this thread.

Anyway, I've got some interest in micros and servos, but I'm using AVR, and was going to try BASIC (just started learning a few weeks ago).
HarveyH42 is online now   Reply With Quote
Old 26th November 2007, 02:01 AM   (permalink)
Default

Quote:
Originally Posted by HarveyH42
I should apologize, I didn't mean to be critical. This is a good thing. You can edit your own past posts and correct typing errors. Figured you were going to keep adding more to this thread.

Anyway, I've got some interest in micros and servos, but I'm using AVR, and was going to try BASIC (just started learning a few weeks ago).
The error has been fixed. Thanks for spoting the error.
I will be adding more new threads regarding different methods of generating pulses.
__________________
May the force be with you.


My project: Simple White Line Follower

http://au.youtube.com/watch?v=8Z_MmrdH4oc

http://i271.photobucket.com/albums/j...nefollower.jpg

Last edited by Wingmax; 27th November 2007 at 04:31 AM.
Wingmax is offline   Reply With Quote
Old 2nd December 2007, 02:35 PM   (permalink)
Default

Quote:
Originally Posted by HarveyH42
Anyway, I've got some interest in micros and servos, but I'm using AVR, and was going to try BASIC (just started learning a few weeks ago).
Hi Harvey,

If it helps, here's a relatively simple high performance low overhead 8-channel Servo demo' I posted on the Swordfish BASIC Forum awhile ago. Perhaps it will provide ideas for using a similar module on AVR?

PORTB outputs a servo pulse for the Servo(0) through Servo(7) array element "on times" and the Servo(8 ) array element is used for the period "off time" (20000 usecs minus the cumulative servo "on times").

Have fun. Mike

Code:
{ 
**************************************************************** 
*  Name    : K8LH_Soft_Servo.BAS                               * 
*  Author  : Mike McLaren, K8LH                                * 
*  Notice  : Copyright (c) 2007 Micro Applications Consultants * 
*          : All Rights Reserved                               * 
*  Date    : 11/28/07                                          * 
*  Version : 1.0 "untested"                                    * 
*  Notes   : Uses CCP1 "compare" mode for 8 servos on PORTB    * 
*          : 1-usec resolution, extended 600-2400 usec pulses  * 
**************************************************************** 
} 
 
Device = 18F452 
Clock = 8 
 
{ 
**************************************************************** 
*  Servo(0)..Servo(7) elements hold 600..2400 usec "on times"  * 
*  Servo(8) = period "off time" (20000 - cumulative on times)  * 
**************************************************************** 
} 
Dim Servo(9) As Word            ' 8 servo and 1 period elements 
Dim TMR1 As TMR1L.AsWord        ' promote to 16 bit TMR1H:L 
Dim CCPR1 As CCPR1L.AsWord      ' promote to 16 bit CCPR1H:L 
Dim CCP1IF As PIR1.2            ' the CCP1 interrupt flag bit 
Dim Servx As Byte               ' servo bitmask (only 1 bit hi) 
Dim n As Byte                   ' servo array index 
 
{ 
**************************************************************** 
*  K8LH Hi-Rez Soft 8-channel PORTB 'compare' Servo Algorithm  * 
**************************************************************** 
} 
Interrupt Soft_Servo() 
  LATB = Servx                  ' output new Servo pulse bit 
  CCPR1 = CCPR1 + Servo(n)      ' setup next compare interrupt 
  CCP1IF = 0                    ' clear CCP1 interrupt flag 
  Servo(8) = Servo(8)- Servo(n) ' adjust end-of-cycle off time 
  Servx = Servx << 1            ' and prep for next channel 
  Inc(n)                        ' increment servo array index 
  If n = 9 Then                 ' if end of 20 msec period 
    n = 0                       ' reset array index 
    Servo(8) = 20000            ' reset 20 msec period element 
    Inc(Servx)                  ' reset Servo shadow to Servo 1 
  EndIf 
End Interrupt 
 
{ 
**************************************************************** 
*  Init Ports and Variables                                    * 
**************************************************************** 
} 
Sub Init() 
   LATB = 0                     ' all PORT B servo outputs '0' 
   TRISB = 0                    ' set PORT B all outputs 
   ADCON1 = 15                  ' all digital I/O (no analog) 
 
   For n = 0 To 7               ' preload the Servo array 
     Servo(n) = 1500            ' mid-range 1500 usec position 
   Next                         ' 
   Servo(8) = 20000             ' Servo period = 20 msecs 
   n = 0                        ' init ISR array index 
   Servx = %00000001            ' init PORT B servo output mask 
 
   TMR1 = 0                     ' clear 16 bit TMR1H:L pair 
   CCPR1 = 1000                 ' first "compare" interrupt 
   T1CON = %00010000            ' pre 2, post 1, 1 usec 'ticks' 
   CCP1CON = %00001010          ' setup CCP1 "compare" mode 
 
   PIR1 = 0                     ' clear peripheral int flags 
   PIR2 = 0                     ' 
   PIE1 = 0                     ' clear peripheral int enables 
   PIE2 = 0                     ' 
 
   PIE1.2 = 1                   ' enable CCP1 interrupts 
   INTCON.6 = 1                 ' enable peripheral interrupts 
   T1CON.0 = 1                  ' turn on Timer 1 
   Enable(Soft_Servo)           ' set GIE, enable interrupts 
End Sub 
 
{ 
**************************************************************** 
*  Main Program                                                * 
**************************************************************** 
} 
Init 
Repeat 
Until 0 = 1

Last edited by Mike, K8LH; 3rd December 2007 at 12:56 AM.
Mike, K8LH is online now   Reply With Quote
Old 6th December 2007, 09:32 AM   (permalink)
Smile why trun to far right only ?

i test your program in by using pic16f877a, as you say this program will make that motor to far right then back to middle then to far left, why the motor after trun to far right then direct stop there ?
antkids is offline   Reply With Quote
Old 6th December 2007, 11:13 AM   (permalink)
Default

Quote:
Originally Posted by antkids
i test your program in by using pic16f877a, as you say this program will make that motor to far right then back to middle then to far left, why the motor after trun to far right then direct stop there ?

Your program codes are not the same as mine, so you will not get the same result.
Also your crystal is 20Mhz, much faster than mine.

According to your codes , your mistake is you use decimal point.
If you check the delay function, you'll find that there are limits of the delay.e.g delay(x)
x must not > 255.

My motor can go as low as 500uS. I can't use 0.5 mS and I can't use 500uS. That's why I used
DelayUs(250) twice.

Hope these help.
__________________
May the force be with you.


My project: Simple White Line Follower

http://au.youtube.com/watch?v=8Z_MmrdH4oc

http://i271.photobucket.com/albums/j...nefollower.jpg
Wingmax is offline   Reply With Quote
Old 6th December 2007, 01:33 PM   (permalink)
Default

Thank for replay !!!
I am using your program code to test servo motor, because i'm using PIC16F877A and my crystal is 20MHz, so what i should change in your program code ?

I try to change "#define XTAL 4000000" to "
#define XTAL 20000000" but the result also same, after move to right just stop there. Why like this ? I also try to change the delay time but the result also same.

May i add you as friend in hotmail ? Because I can easily ask you the question ?
antkids is offline   Reply With Quote
Old 6th December 2007, 09:40 PM   (permalink)
Default

Quote:
Originally Posted by antkids
Thank for replay !!!
I am using your program code to test servo motor, because i'm using PIC16F877A and my crystal is 20MHz, so what i should change in your program code ?

I try to change "#define XTAL 4000000" to "
#define XTAL 20000000" but the result also same, after move to right just stop there. Why like this ? I also try to change the delay time but the result also same.

May i add you as friend in hotmail ? Because I can easily ask you the question ?
Can you show us your codes?
__________________
May the force be with you.


My project: Simple White Line Follower

http://au.youtube.com/watch?v=8Z_MmrdH4oc

http://i271.photobucket.com/albums/j...nefollower.jpg
Wingmax is offline   Reply With Quote
Old 7th December 2007, 03:57 AM   (permalink)
Default

Below are my program code :

#include <pic.h>
#include "delay.c"
#include "delay.h"

__CONFIG(WDTDIS & XT & UNPROTECT);

#define XTAL 20000000 //crystal frequency- 20MHz


main()

{
int i;
TRISC = 0; //PortC is output.

for (i = 0; i < 50; i++) //Send 50 pulses with width 600 uS
{
PORTC = 1; //Pulse high for 600uS
DelayBigUs(600); //since delayUs (x); x<255 so i change to delaybigus
PORTC = 0; //Pulse low for 20mS
DelayMs(20);
}
DelayMs(100); //Pause for 100mS

for (i = 0; i < 50; i++) //Send 50 pulses with width 1.5mS
{
PORTC = 1;
DelayMs(1); //Pulse high for 1.5mS
DelayBigUs(500);
PORTC = 0;
DelayMs(20);
}
DelayMs(100);

for (i = 0; i < 50; i++) //Send 50 pulses with width 2ms
{
PORTC = 1;
DelayMs(2);
PORTC = 0;
DelayMs(20);
}
DelayMs(100);

while (1); //Stops here, do nothing.

}

why send 50 pulses? why motor trun to right then stop there ? Acctually this program code is same as you post on forum, I just change something only.
What meaning of " __CONFIG(WDTDIS & XT & UNPROTECT); "
I'm using PIC16F877A, 20Mhz crystal.
antkids is offline   Reply With Quote
Old 7th December 2007, 05:57 AM   (permalink)
Default

Quote:
Originally Posted by antkids
Below are my program code :

#include <pic.h>
#include "delay.c"
#include "delay.h"

__CONFIG(WDTDIS & XT & UNPROTECT);

#define XTAL 20000000 //crystal frequency- 20MHz


main()

{
int i;
TRISC = 0; //PortC is output.

for (i = 0; i < 50; i++) //Send 50 pulses with width 600 uS
{
PORTC = 1; //Pulse high for 600uS
DelayBigUs(600); //since delayUs (x); x<255 so i change to delaybigus
PORTC = 0; //Pulse low for 20mS
DelayMs(20);
}
DelayMs(100); //Pause for 100mS

for (i = 0; i < 50; i++) //Send 50 pulses with width 1.5mS
{
PORTC = 1;
DelayMs(1); //Pulse high for 1.5mS
DelayBigUs(500);
PORTC = 0;
DelayMs(20);
}
DelayMs(100);

for (i = 0; i < 50; i++) //Send 50 pulses with width 2ms
{
PORTC = 1;
DelayMs(2);
PORTC = 0;
DelayMs(20);
}
DelayMs(100);

while (1); //Stops here, do nothing.

}

why send 50 pulses? why motor trun to right then stop there ? Acctually this program code is same as you post on forum, I just change something only.
What meaning of " __CONFIG(WDTDIS & XT & UNPROTECT); "
I'm using PIC16F877A, 20Mhz crystal.
I haven't had much success with DelayBigUs() before, so I don't know if it's OK.

You're using different PIC, so try use this in your Configuration word:
__CONFIG(WDTDIS & XT & UNPROTECT & BORDIS & LVPDIS);

don't forget it's double underscore before the CONFIG.
If this configuration word isn't set correctly, program won't work properly.

Hope this will work.
__________________
May the force be with you.


My project: Simple White Line Follower

http://au.youtube.com/watch?v=8Z_MmrdH4oc

http://i271.photobucket.com/albums/j...nefollower.jpg
Wingmax is offline   Reply With Quote
Old 7th December 2007, 09:44 AM   (permalink)
Smile

Thanks for your help!!!
After change the code, the result also same. just keep trun in 1 direction that is form left to right. I have change the time but it also get the same result. Why like this ?? The code problem ? Below are the code :

#include <pic.h>
#include "delay.c"
#include "delay.h"

__CONFIG(WDTDIS & XT & UNPROTECT & BORDIS & LVPDIS);

#define XTAL 20000000 //crystal frequency- 20MHz


main()

{
int i;
TRISC = 0; //PortC is output.

for (i = 0; i < 50; i++) //Send 50 pulses with width 600 uS
{
PORTC = 1; //Pulse high for 600uS
DelayUs(300); //since delayUs (x); x<255 so i change to delaybigus
PORTC = 0; //Pulse low for 20mS
DelayMs(20);
}
DelayMs(100); //Pause for 100mS

for (i = 0; i < 50; i++) //Send 50 pulses with width 1.5mS
{
PORTC = 1;
DelayMs(1); //Pulse high for 1.5mS
DelayBigUs(500);
PORTC = 0;
DelayMs(20);
}
DelayMs(100);

for (i = 0; i < 50; i++) //Send 50 pulses with width 2ms
{
PORTC = 1;
DelayMs(2);
PORTC = 0;
DelayMs(20);
}
DelayMs(100);

while (1); //Stops here, do nothing.

}
antkids is offline   Reply With Quote
Old 7th December 2007, 12:30 PM   (permalink)
Default

This should be a simple program. It shouldn't be that hard.
I got a feeling the configuration word hasn't been set correctly. The code on my chip definitely works. Only differences are we used different chip, crystal and delay function.

Also you haven't included DelayBigUs in your #include section. Wonder why you haven't got errors when you compiled the codes.
__________________
May the force be with you.


My project: Simple White Line Follower

http://au.youtube.com/watch?v=8Z_MmrdH4oc

http://i271.photobucket.com/albums/j...nefollower.jpg
Wingmax is offline   Reply With Quote
Old 7th December 2007, 01:12 PM   (permalink)
Default

What about the fuse bits? I really don't know a lot about PIC, still little better than a beginner with AVR. But on my setup, burning the program is one thing, and setting the fuses is another. On the AVR, there are several choices that involve the clock (well 2 that I've used and understand). One divides the clock by 8. If PIC has a similar fuse, then the timing in your program wouldn't be set up right. Servos are all about the timing.
HarveyH42 is online now   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes


Similar Threads
Thread Thread Starter Forum Replies Latest
Driving a unipolar stepper motor Wingmax Robotics Chat 0 22nd October 2007 01:01 PM
Project: DC Motor Control (using a single switch) arijit18 Electronic Projects 10 27th December 2006 06:03 AM
Help required with servo motor controller mayhem Robotics Chat 3 26th May 2006 04:21 PM
Stepper Motor Driving Using PIC16F74 t_anjan Electronic Projects Design/Ideas/Reviews 0 31st January 2006 06:13 PM
DC Motor Postion control help (servo) lompa Robotics Chat 6 24th October 2004 03:16 PM



All times are GMT. The time now is 04:36 PM.


Electronic Circuits  |  Electronics Wiki
Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.