PyroElectro.com Forum Index PyroElectro.com
Build what you want, Be the pyro you are.
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Servo Motor Control
Goto page 1, 2, 3, 4, 5, 6  Next
 
Post new topic   Reply to topic    PyroElectro.com Forum Index -> Tutorials
View previous topic :: View next topic  
Author Message
ThePyroElectro
PyroElectro Admin


Joined: 12 Nov 2007
Posts: 401
Location: Earth

PostPosted: Sun Nov 18, 2007 6:08 am    Post subject: Servo Motor Control Reply with quote

The Servo Motor Control Tutorial Write-up

Quote:
Servo motors offer two things a DC motor rarely can: Torque & Precision.
Learn how to use the PIC to control servo motors so you can include them
in your next project!



Questions & Comments?
Back to top
View user's profile Send private message Send e-mail AIM Address MSN Messenger
Smeg-Head
Newbie Pyro


Joined: 07 Dec 2007
Posts: 2

PostPosted: Fri Dec 07, 2007 11:09 pm    Post subject: Reply with quote

Hi!

First off, I would like to say I like how the site is setup and the concept behind it all. I have always wanted to setup something similar but I am not an EE, rather and ME. Programming is not really my forte.

I am going through the tutorial and I can not find the includes for timers and delays. I was hoping to setup what you have and and watch my servo do as your servo has done. Then, I plan to figure out how to make my pretzel dipping machine move.

I am new pwm. I can make sense of your code but am not sure how to compile the code without timers.h and delays.h.

Where can I find these?
_________________
--
Later,
Matthew
Back to top
View user's profile Send private message
ThePyroElectro
PyroElectro Admin


Joined: 12 Nov 2007
Posts: 401
Location: Earth

PostPosted: Fri Dec 07, 2007 11:28 pm    Post subject: Reply with quote

Hey Smeg-Head,

Thanks, I'm glad you like the site.

A Pretzel Dipping Machine?
Awesome! You are truly a god among insects Very Happy . (no sarcasm)

The timers.h and delays.h are from the C18 Libraries that Microchip
offers with its C18 Compiler.

You can download a free copy of the C18 Compiler here: Click!
(Scroll to the bottom for the download)

You'll have to register with microchip but its no big deal.
Afterward you can download the student edition for free.

Arrow (Be sure to check out the pdf: MPLAB C18 Libraries Documentation on that page
as well. It explains all the functions the C18 Library offers in great detail.)


One thing to note is that it's preferrable to use the C18 Compiler
with the MPLAB IDE for PIC development. C18 was made to
integrate into MPLAB with no issues. See this tutorial for more
info:The PIC Microcontroller & installation help.

After installing, these two fies (timers.h and delays.h) will be found:
C:\MCC18\h\timers.h
C:\MCC18\h\delays.h

(Assuming you installed the compiler on the C:\ drive)
Back to top
View user's profile Send private message Send e-mail AIM Address MSN Messenger
Smeg-Head
Newbie Pyro


Joined: 07 Dec 2007
Posts: 2

PostPosted: Sat Dec 08, 2007 5:51 pm    Post subject: Reply with quote

Thanks for the reply. Checking out the links now.

The reason I am getting into this is because in my last semester prior to graduating, I took a mechatronics class. I bought the kit which includes software called "PCW C Compiler IDE", the ICD-U40 usb programmer thingy, and the prototype board that has the 18F452, a trim pot, 3 leds, an rs232 jack, and a ribbon cable adapter for all other pinouts. We wrote some simple programs to learn about timers, interrupts, and ADC/DAC stuff.

I had to learn a very quicky C programming. As a result, most of my code is just copy and paste of what works. After tinkering around with it a while, I kinda realize what I am doing and am able to manipulate the code enough to get what I need done. Otherwise, don't ask me what all the nonsense gibberish means.

I will take a picture of what I am building and post it here later. Right now it looks like a crane. I even have a flag toothpick on it. It is pretty cool.
_________________
--
Later,
Matthew
Back to top
View user's profile Send private message
jwen88
Newbie Pyro


Joined: 16 Dec 2007
Posts: 8

PostPosted: Sun Dec 16, 2007 5:58 am    Post subject: Reply with quote

for(count=0;count<=50;count++) //50 * 0.020ms = 1 Second

how did you get the 0.020ms ?? the total delay for PWM is 20ms, or is there a typo error ??

Regards,
Junwen
Back to top
View user's profile Send private message
ThePyroElectro
PyroElectro Admin


Joined: 12 Nov 2007
Posts: 401
Location: Earth

PostPosted: Sun Dec 16, 2007 6:40 pm    Post subject: Reply with quote

Hi Junwen,

It is a typo. It should read 0.020 Seconds or 20mS.
Thanks for pointing that out. I fixed it on the website.

The number 20mS refers to the time it takes to complete 1 period. Since the servos run at
50Hz frequency there will be 50 periods in 1 second. That is what the
50 * 0.020 Seconds = 1 Second represents.

For the full specifications on the servo check out this website:
http://www.hitecrcd.com/servos/show?name=HS-422

Feel free to ask more questions if you have them.
Back to top
View user's profile Send private message Send e-mail AIM Address MSN Messenger
jwen88
Newbie Pyro


Joined: 16 Dec 2007
Posts: 8

PostPosted: Wed Dec 19, 2007 4:34 am    Post subject: Reply with quote

could you explain or refer me to any website on how the interrupt control for servo movement works??

my application requires the servo to move very smoothly,changing the Duty cycle by 0.01ms.

As i have said, i'm using 8Mhz for a continous interrupt from Timer2 every 0.01ms(Setting PR2 and enable Timer2 Interrupt. However, someone told me that 20 assembly instruction cycle is too short for 0.01ms interrupt handling due to pushing stack etc.

So i'm wondering how many instruction cycles is needed to execute the intended program.

#pragma interrupt T2ISR // To generate return from interrupt.
void T2ISR(void){
PIR1bits.TMR2IF = 0; // Clear Timer 2 Flag.
P1MS++;
if(P1MS==2000){ // Period = 20mS
P1MS = 0;
PORTBbits.RB2 = 1;
}
if(P1MS==WidthPitch) PORTBbits.RB2 = 0; // This determines the pulse width
}
Back to top
View user's profile Send private message
ThePyroElectro
PyroElectro Admin


Joined: 12 Nov 2007
Posts: 401
Location: Earth

PostPosted: Fri Dec 21, 2007 2:13 am    Post subject: Reply with quote

I calculated it out and 20 Instructions will give you the delay you need for 0.01mS however
that would only work with the non-interrupt method in the servo tutorial. When you're doing
things with interrupts there will be more instructions and I'd say that it would actually
be a longer delay than you want.

What happens when it interrupts is that the return address to your currently running
code is pushed onto the stack and the program counter is loaded with the interrupt vector address.
The datasheet says this process can take 1-4 instruction cycles depending on the type of interrupt
and how many flags it sets. The Timer2 Interrupt should take 2 instruction cycles to load the
return address onto the stack & tell the program counter where to execute code from.

Take into account that these instructions:

Code:
PIR1bits.TMR2IF = 0; // Clear Timer 2 Flag.
P1MS++;
if(P1MS==2000){ // Period = 20mS
P1MS = 0;
PORTBbits.RB2 = 1;


Are also executed along with the interrupt code.

Other more invisible instructions will be the 'Goto' statement (2 instruction cycles) used to direct
the interrupt code to your T2ISR function and the RETFIE return from interrupt (2 instruction
cycles) reloads the top of stack into the program counter.

When timing down to 10-20 single instruction cycles becomes critical I typically suggest doing
things in ASM. This gives you complete control over the timing and since your program is fairly
simple it wouldn't be much of a change, although I'd understand if you didn't want to. Most
people don't like programming ASM.
Back to top
View user's profile Send private message Send e-mail AIM Address MSN Messenger
jwen88
Newbie Pyro


Joined: 16 Dec 2007
Posts: 8

PostPosted: Fri Dec 21, 2007 2:19 am    Post subject: Reply with quote

well, i actually willing to do anything to get the code working, problem is, i dont know how to program in ASM. Any guidance??

Thanks
Back to top
View user's profile Send private message
ThePyroElectro
PyroElectro Admin


Joined: 12 Nov 2007
Posts: 401
Location: Earth

PostPosted: Fri Dec 21, 2007 3:05 am    Post subject: Reply with quote

Well aside from learning ASM quickly...You can actually vary the servo by 0.01mS without ever using interrupts with a program like this:

Code:
//8MHz Clock
//40,000 Instructions per 20mS
//20 Instructions per 0.01mS

#include <p18f452.h>
#include <delays.h>

void main(void)
{
int count=0;
int up_var=2000;
int down_var=0;
TRISC = 0x00;
PORTC = 0x00;

   while(1)
   {
      //This for loop changes the servo up/down times by 0.01mS every 0.2 Seconds
      //10 * 0.020 Seconds = 0.2 Seconds
      for(count=0;count<10;count++)
      {
      PORTC = 0x00;         //  Logic 0 to the Servo
      Delay1KTCYx(36);       //  36,000
      Delay10TCYx(up_var);    //  2,000->0 in steps of 20
                        //  Total: 38,000->36,000 Instruction Cycles = 19mS->18mS

      PORTC = 0x01;         //  Logic 1 to the Servo
      Delay100TCYx(20);      //  2,000 Instruction Cycles = 1mS
      Delay10TCYx(down_var);   //  0->2,000 in steps of 20 Instruction Cycles = 0.01mS
      }                  //  Total: 2,000->4,000 Instruction Cycles = 1mS -> 2mS
      down_var += 2;
      up_var -= 2;
   }

}


I didn't get the chance to compile this exact code, but I justed tested a similar version of the code on one of my boards and the movement was pretty smooth.

Since servos only have two changing values you just change the down time and up time gradually. You can add some extra if statements in there so that it moves smoothly back and forth infinitely. I'm not entirely sure of the specifics of what you need but I think this should help some.
Back to top
View user's profile Send private message Send e-mail AIM Address MSN Messenger
jwen88
Newbie Pyro


Joined: 16 Dec 2007
Posts: 8

PostPosted: Fri Dec 21, 2007 3:41 am    Post subject: Reply with quote

thank you
Back to top
View user's profile Send private message
jwen88
Newbie Pyro


Joined: 16 Dec 2007
Posts: 8

PostPosted: Fri Dec 21, 2007 5:34 am    Post subject: Reply with quote

the code works fine, but i want to control 2servos.

So i'm thinking if i could split the On time into 2segments,so i could control 2 servos. You think this idea is workable ??
Back to top
View user's profile Send private message
jwen88
Newbie Pyro


Joined: 16 Dec 2007
Posts: 8

PostPosted: Fri Dec 21, 2007 6:00 am    Post subject: Reply with quote

Kind of confusing.

Delay1KTCYx(36); // 36,000
Delay10TCYx(up_var); // 2,000->0 in steps of 20
// Total: 38,000->36,000 Instruction Cycles = 19mS->18mS

36000 + (2000x10) = 56000 => 28ms

or it should be 200 instead of 2000 ??
Back to top
View user's profile Send private message
ThePyroElectro
PyroElectro Admin


Joined: 12 Nov 2007
Posts: 401
Location: Earth

PostPosted: Fri Dec 21, 2007 8:09 am    Post subject: Reply with quote

Yes, it is possible using the delay method to create seperate pulses for each servo using clever
programming but it's a bit more difficult to do. However, you can send the same PWM signal
to the two servos and they'll move the same direction.

Yea, 200 should be the initialization for up_var
So change that value.

Code:
int up_var=200;

I don't have access to a compiler or 8 MHz PIC setup right now so I couldn't test it out.
Back to top
View user's profile Send private message Send e-mail AIM Address MSN Messenger
jwen88
Newbie Pyro


Joined: 16 Dec 2007
Posts: 8

PostPosted: Mon Dec 31, 2007 10:33 am    Post subject: Reply with quote

Happy New Year!!!! hahah, kind of early but got work to do later.

Actually the servo doesn't need to see a pulse every 20mS, it only need to see a On-Pulse every 10ms to 20ms. Don't go below 10mS off time.

for(count=0;count<5;count++)
{
//Pitch
PORTBbits.RB3=1; //Logic 1 to the Servo
Delay1KTCYx(2); //2 x 1000 = 2000
Delay100TCYx(5); //5 x 100 = 500
Delay10TCYx(Pit_on); //(inital value of Pit_on is 0)
PORTBbits.RB3=0; //Logic 0 to the Servo
Delay1KTCYx(15); //15 x 1000 = 15000
Delay100TCYx(Cool; //8 x 100 = 800
Delay10TCYx(Pit_off); //
//Altitude
PORTBbits.RB2=1; //Logic 1 to the Servo
Delay1KTCYx(2); //2 x 1000 = 2000
Delay100TCYx(9); //9 x 100 = 900
Delay10TCYx(Alt_on); //(inital value of Alt_on is 700)

PORTBbits.RB2=0; //Logic 0 to the Servo
Delay1KTCYx(16); //1000 x 16 = 16000
Delay100TCYx(3); //100 x 2 = 200
Delay10TCYx(Alt_off); //16200 -> 16900 (inital value of Alt_off is 0)
}

if(try_Landing==1){
Pit_on += 2; // 0.0005ms x 20 = 0.01ms
Pit_off -= 2;
Alt_on -= 1;
Alt_off += 1;
if(Pit_on==170)try_Landing=0;
}
if(try_Reset==1){
Pit_on -= 2; // 0.0005ms x 20 = 0.01ms
Pit_off += 2;
Alt_on += 1;
Alt_off -= 1;
if(Pit_on==0)try_Reset=0;
}
if((PORTAbits.RA0==0)&&(Pit_on==0))try_Landing=1;//Landing
if((PORTAbits.RA1==0)&&(Pit_on==170))try_Reset=1;//Reverse

here's the program i wrote to control 2 servo. And i use an interrupt to output a third pwm. Problem is: When i enable the interrupt, my routine above doesn't function as it did. I have no control over it. But it went back to the normal function when i disable the interrupt. Any suggestion for this abnormal behaviour??

here's the interrupt program that produce the pwm.
(initalisation part)
T2CON = 0x04; // posS=1, preS=1, Timer 2 ON.
PR2 = 199; // 0.1mS with 8-MHz crystal

RCONbits.IPEN = 1; // Enable Priority Features
IPR1bits.TMR2IP = 1; // Timer 2 is High Priority
PIR1bits.TMR2IF = 0; // Clear Timer 2 Flag.
PIE1bits.TMR2IE = 1; // Enable Timer 2 Interrupt.
INTCONbits.GIEH = 1; // Enable Global Interrupt, High.

(in the ISR)
if(PIR1bits.TMR2IF==1)
{
PIR1bits.TMR2IF = 0;
P1MS++;
if(P1MS==200){ // Period = 20mS
P1MS = 0;
PORTBbits.RB1 = 1;
}
if(P1MS==Width) PORTBbits.RB1 = 0; // This determines the pulse width
}

basically, it generate a interrupt every 0.1ms, so you can increment a variable and take note of the timing and toggle the output to get an pwm.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    PyroElectro.com Forum Index -> Tutorials All times are GMT
Goto page 1, 2, 3, 4, 5, 6  Next
Page 1 of 6

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group