control the servo degree using Mikroc & Proteus PIC16f877a

Status
Not open for further replies.

mot1639

Member level 1
Joined
Jul 10, 2011
Messages
32
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,513
hi all

i write this code in Mikroc and it work fine with me .. in Proteus .. also i am using PIC16f877a @ 8Mhz
Code:
void PWM1_Init(const long freq);
void PWM1_Start(void);
void PWM1_Set_Duty(unsigned short duty_ratio);
void PWM1_Stop(void);

unsigned short i;

void main() {
PORTC = 00; // Set PORTC to $FF
TRISC = 0; // PORTC is output
Pwm1_Init(8000); // Initialize PWM module

Pwm1_Start(); // Start PWM

while (1) { // Endless loop


{
Pwm1_set_Duty(255);

delay_ms(1000);

 Pwm1_set_Duty(127);
 delay_ms(1000);
 
 }
} }

now the problem is how i can move the servo , 0,90,137,180,270,360 degree ?
now i have -90 and +90 ..

please help me out ..

regards
 

You can control the position of a servo by varying the duty cycle of the PWM. The period of your PWM should typicaly be 20ms or 50 pulses per second, with the ON time of the PWM set at between 0.9ms to 2.1ms. Each servo is different so these are just typically values.

Checkout:

Servo Motor Control: Theory

BigDog
 
sorry i am new i this world (programming Electronic) , please where i can modify , i set my code to 50 p /s but still , where is the problem
regards
 

Using a oscillator frequency of 8MHz makes it very difficult to generate 50Hz PWM using the CCP modules.

I would suggest using a timer interrupt.

Step 1: You first set the timer for the ON duration of duty cycle, between 0.9ms to 2.1ms as previously mentioned, then set the pulse high.

Step 2: When the timer expires in the ISR, you bring the pulse low and reset the timer for the remain period of the cycle (< 20ms).

Step 3: When the timer expires you are back to Step 1.

Following these steps you will generate a PWM of 50Hz and by varying the ON duration or duty cycle you will be able to control the position of the servo.

A duty cycle of 1.5ms and a remaining period of 18.5ms will in effect put the servo into idle position, half way between the minimum and maximum positions.

The tutorial I gave you the link explains these principles well.

Does this info help?

BigDog

---------- Post added at 17:35 ---------- Previous post was at 17:16 ----------

now the problem is how i can move the servo , 0,90,137,180,270,360 degree ?
now i have -90 and +90 ..


By the way most, but not all, RC Servos have a limited range of +/- 90°, which you have already reached.

What is the make and model of the Servo you are using? I'll attempt to look the specs.

To implement a set of preset position points, degrees of rotation, you could use an array with duty cycle values required to position the servo at various points of rotation.

Moving the servo to a preset position would simply required to retrieve the value of the duty cycle from the array, subtract it from 20ms, and now you have both values required to rotate the servo to the desired position.

Does this help?

BigDog
 
As Bigdog state most servo's are +/- 90 and the video show one that is of that type.
 

Here are a few more tutorials and projects:

The following example appears to use basically the same approach I described above:

Driving a standard servo motor with a PIC.

MikroC Pro User Manual

I would suggest studying the sections of the MikroC user manual which cover timers and interrupts.

You can then adapt the examples to your requirements.

BigDog
 

thanks for your great support
regards
 

why do some codes show 5000 as argument for pwm1_init() in the case of servo motor?
Also can i use the below code for the servo?


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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(20);
 
   //To Turn to 90 Degree
   PORTB.F0 = 1;
   Delay_us(1500);
   PORTB.F0 = 0;
 
   Delay_ms(20);
 
   //To Turn to 180 Degree
   PORTB.F0 = 1;
   Delay_us(2000);
   PORTB.F0 = 0;
 
   Delay_ms(20);
 }while(1);
}



IS THIS CORRECT......am using pic16f877a with mikroc
 
Last edited by a moderator:

You need to remember that the servo will be looking a pulse every 20ms to hold the position.

I do not program in C but, Your code, if I am reading it correctly, would move it quickly to the end point and then go into an endless loop without supplying a pulse to the servo on a regular basis.
 

Re: control the servo degree using Mikroc &amp;amp; Proteus PIC16f877a

What about this one.....i want to move the vehicle as well as control servo?



Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
void main()
{
TRISC=0x00;
TRISB=0xFF;
 
ADCON1=0x06;
CMCON=0x07;
 
TRISA=0XFF;
TRISD=0X00;
 
PORTB=0x00;
PORTC=0X00;
 
while(1)
{
while(PORTB==0x20)
{
PORTD=0x30;
}
 
while(PORTB==0x40)
{
PORTD=0x20;
}
 
while(PORTB==0x10)
{
PORTD=0x10;
}
 
while(PORTB==0x80)
{
PORTD=0xC0;
}
 
 
if(RA0)
{
PORTC=0x04;
Delay_us(2000);
PORTC=0x00;
Delay_us(20000);
}
 
if(RA1 & RA0)
{
PORTC=0x04;
Delay_us(1350);
PORTC=0x00;
Delay_us(20000);
}
 
if(RA1)
{
PORTC=0x04;
Delay_us(2000);
PORTC=0x00;
Delay_us(20000);
}
}
}




- - - Updated - - -

......and 20ms=50hz.........then why 5000hz in the argument?
Sorry, I am totally new to servos
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…