help: servo motor

Thread Starter

mastertiger

Joined Jul 9, 2012
24
can i change the direction of servo motor by change polarity ?
if not
how can i change the direction of servo motor by using pic 16f877a?
i use servo motori sys s3006
3 wire
void main()
{
int x;
trisb=0;
trisd=0;
portb=0;
portd=0;

for(x=0;x<4;x++)
{
PORTB.F0 = 1;
Delay_us(1000);//1ms Delay
PORTB.F0 = 0;

Delay_us(1000);

}
}
connect single wire to port b pin 0 in pic
i read some threads about change delay time to change direction
but it do not work
help please
thanks

 

BMorse

Joined Sep 26, 2009
2,675
To control an RC servo you will need to use PWM with a duty‐cycle of 20ms, and the pulse width contained within those 20ms varies from 1ms to 2ms.

This variation in the pulse width is what controls the servo. As a rule of thumb, if a 1ms
pulse is constantly fed to the servo, it will position itself around ‐60° angle,
1.5ms and it will go to the center (0°), and 2 ms will position the servo at +60°
angle.

Here is an example using a pic16f877a written in Mikropascal:
Rich (BB code):
//designed for a PIC16F877A with a 4Mhz clock
interrupt {
     if (TMR0IF flag is raised) {
          flagServo = true;
          TMR0 := 100;
          SetBit(INTCON,TMR0IE);
          ClearBit(INTCON,TMR0IF);
     }
}
main_body {
     TRISC = 0;
     delay = 1000; //-60
     increment := 1;
     steps := 10; //10 steps = approx. 1 degree
     OPTION_REG := $86; //setup TMR0 to trigger
     TMR0 := 100; //every 20ms
     SetBit(INTCON,GIE);
     SetBit(INTCON,TMR0IE);
     while (1==1) {
          if (flagServo) {
          //generate pulse with width = “delay” microseconds
              SetBit(PORTC,0);
              delay_microseconds(delay);
              ClearBit(PORTC,0);
         //increase/decrease angle
             delay = delay + increment * steps;
             if (delay > 2000) {
                    delay = 1999;
                    increment = -1;
            } else if (delay < 900) {
                    delay = 901;
                    increment = 1;
                    }
          flagServo = false;
          }
     }
}
 

Thread Starter

mastertiger

Joined Jul 9, 2012
24
To control an RC servo you will need to use PWM with a duty‐cycle of 20ms, and the pulse width contained within those 20ms varies from 1ms to 2ms.

This variation in the pulse width is what controls the servo. As a rule of thumb, if a 1ms
pulse is constantly fed to the servo, it will position itself around ‐60° angle,
1.5ms and it will go to the center (0°), and 2 ms will position the servo at +60°
angle.

Here is an example using a pic16f877a written in Mikropascal:
Rich (BB code):
//designed for a PIC16F877A with a 4Mhz clock
interrupt {
     if (TMR0IF flag is raised) {
          flagServo = true;
          TMR0 := 100;
          SetBit(INTCON,TMR0IE);
          ClearBit(INTCON,TMR0IF);
     }
}
main_body {
     TRISC = 0;
     delay = 1000; //-60
     increment := 1;
     steps := 10; //10 steps = approx. 1 degree
     OPTION_REG := $86; //setup TMR0 to trigger
     TMR0 := 100; //every 20ms
     SetBit(INTCON,GIE);
     SetBit(INTCON,TMR0IE);
     while (1==1) {
          if (flagServo) {
          //generate pulse with width = “delay” microseconds
              SetBit(PORTC,0);
              delay_microseconds(delay);
              ClearBit(PORTC,0);
         //increase/decrease angle
             delay = delay + increment * steps;
             if (delay > 2000) {
                    delay = 1999;
                    increment = -1;
            } else if (delay < 900) {
                    delay = 901;
                    increment = 1;
                    }
          flagServo = false;
          }
     }
}
thanks of replay
ok if i want to do that with normal pin not pwm pin
i need to change pulse wide time to reverse direction
i try use (.7ms or 2ms ) to change direction but do not work
void main()
{
int x;
trisb=0;
trisd=0;
portb=0;
portd=0;

for(x=0;x<4;x++)
{
PORTB.F0 = 1;
Delay_us(700);
PORTB.F0 = 0;

Delay_ms(1000);

}
}
and this
void main()
{
int x;
trisb=0;
trisd=0;
portb=0;
portd=0;

for(x=0;x<4;x++)
{
PORTB.F0 = 1;
Delay_us(2000);
PORTB.F0 = 0;

Delay_ms(1000);

}
}
what i missed ?
if i change the polarity like dc motor direction will change or motor will damage ?
 
Last edited:

Markd77

Joined Sep 7, 2009
2,806
instead of 1000ms you want 20ms, and if you reverse the polarity it could damage the motor, it certainly wouldn't do what you want.
 

BMorse

Joined Sep 26, 2009
2,675
I don't see why you are having issues, when the site you got the circuit from provides the code to run the servo..... you just need to modify it to suit your needs, (and write it in the appropriate compiler language since this is written in MicroC)....

Rich (BB code):
void main()
{
  TRISB = 0; // PORTB as Ouput Port
  do
  {
   //To Turn to 0 Degree
   PORTB.F0 = 1;
   Delay_us(1000);//1ms Delay
   PORTB.F0 = 0;

   Delay_ms(1000);

   //To Turn to 90 Degree
   PORTB.F0 = 1;
   Delay_us(1500);
   PORTB.F0 = 0;

   Delay_ms(1000);

   //To Turn to 180 Degree
   PORTB.F0 = 1;
   Delay_us(2000);
   PORTB.F0 = 0;

   Delay_ms(1000);
 }while(1);
}
 

BMorse

Joined Sep 26, 2009
2,675
OK, so I had to try it to see if the code works.... I am using Hi-tech C with a Pic16f887 running at 20Mhz.... this will run the servo from one end to the other looping it constantly... (Just change the word Servo to the I/O pin you are using.....)

Rich (BB code):
void Move_Servo()
{
	int x;
	while(1){
		//to turn to 0 degrees
		for (x=0;x<25;x++){
			Servo = 1;
			DelayMs(1);
			Servo = 0;
			DelayMs(10);
		}//end for

	DelayMs(1000);	//short delay between moves
	
		//to turn it all the way to 180
		for (x=0;x<25;x++){
			Servo = 1;
			DelayMs(2);
			Servo = 0;
			DelayMs(10);
		}//end for 
	};//end while
}
 

Thread Starter

mastertiger

Joined Jul 9, 2012
24
OK, so I had to try it to see if the code works.... I am using Hi-tech C with a Pic16f887 running at 20Mhz.... this will run the servo from one end to the other looping it constantly... (Just change the word Servo to the I/O pin you are using.....)

Rich (BB code):
void Move_Servo()
{
    int x;
    while(1){
        //to turn to 0 degrees
        for (x=0;x<25;x++){
            Servo = 1;
            DelayMs(1);
            Servo = 0;
            DelayMs(10);
        }//end for

    DelayMs(1000);    //short delay between moves
    
        //to turn it all the way to 180
        for (x=0;x<25;x++){
            Servo = 1;
            DelayMs(2);
            Servo = 0;
            DelayMs(10);
        }//end for 
    };//end while
}
thanks for replay
i make delay (delay_us(3000);)
it work nice
thanks again
 
Top