• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

ECCP1 PWM on PIC18F458

Status
Not open for further replies.

heyhey

New Member
I am trying to modulate 2 servos using the CCP1 and ECCP1 pins on the PIC.

the motor which is using the CCP1 pin is working as expected but the servo on the ECCP1 pin isn't moving. the code im using is as follows:

Code:
#include <p18f458.h>
#include <pwm.h>

void main (void)
{

//PWM settings for a frequency of 50Hz */
        TRISCbits.TRISC2 = 0; //PWM-pin ON
  		T2CON  = 0b00000101; //timer2 on
        PR2    = 0x7c;

/*setting up A/D converter as ADCON0 all pins are analouge and adcon0 channel selected */
/* 00 = FOSC/2 | 000 = AN0 Channel | 0 = Go/Done | 01 = A/D On */
		ADCON0 = 0b00000000;

/*Forward Both wheels (5% Duty Cycle)*/
		/*left wheel*/
        CCPR1L = 0b00000110;
        CCP1CON= 0b01001100;
		/*right wheel*/
		ECCPR1L = 0b00000110;
		ECCP1CON = 0b00001100;

while(1);
}
i am using microchip's C18 compiler.

is it a code problem or something else?

thanks in advance.
 

Pommie

Well-Known Member
Most Helpful Member
You have the timer set to rollover every 500 cycles. For this to be 50Hz your pic has to be running at 10kHz. I think you may be out by a factor of 1000. The best way to control a servo is using the special event trigger. See this thread for an example.

Mike.
 

WISEMEN

New Member
You have the timer set to rollover every 500 cycles. For this to be 50Hz your pic has to be running at 10kHz. I think you may be out by a factor of 1000. The best way to control a servo is using the special event trigger. See this thread for an example.

Mike.
hi MIKE i'm new here, and also in microcontroller....i've see you thread there and try to understand you code, and it kinda make sense to me. i have a question. i'm using p18f458 to control a servo with potentiometer, i notis you only do setting for timer1 in your code, but it says in the data sheet, pwm only uses timer 2? and also does eccp works just like ccp pin, means that i can control up to 5 servo independantly? can you help me...? thanks in advance..
 

Mr RB

Well-Known Member
Didn't Nigel or someone here have code for manually generating multiple RC servo PWM signals?

The easiest way to control 5 servos is generate the servo HI period using the CCP set to compare. Then do it again for the next 4 servos. After that wait for a total of 20mS (this includes all the HI periods) and repeat. To generate the 20mS you can use the other 16bit timer.
 

WISEMEN

New Member
Didn't Nigel or someone here have code for manually generating multiple RC servo PWM signals?

The easiest way to control 5 servos is generate the servo HI period using the CCP set to compare. Then do it again for the next 4 servos. After that wait for a total of 20mS (this includes all the HI periods) and repeat. To generate the 20mS you can use the other 16bit timer.
oh so that's what it is....a manually generating pwm based on the ccp pin and timer. is that means you can make pin other than ccp pin as pwm output? instead of timer , if i use a delay prog to make on and off at the signal pin and then loop it to make it pulsating like the pwm waveform, will it work?
 

Pommie

Well-Known Member
Most Helpful Member
In the code I linked to earlier, it uses the special events trigger to do precise timings and could be extended to easily output 8 accurate pulses on 8 different pins. The problem with using the ccp pin is that there is only one.

How good is your C? Can you follow the code linked above?

Mike.
 

WISEMEN

New Member
In the code I linked to earlier, it uses the special events trigger to do precise timings and could be extended to easily output 8 accurate pulses on 8 different pins. The problem with using the ccp pin is that there is only one.

How good is your C? Can you follow the code linked above?

Mike.
well sorta... i'm terrible at c, i just can understand what bit is move to what register, thats all. for now i'm only familiar with assembly. that's right there's only one ccp pin, before i was thinking about using a pwm multiplexer chip. but now it makes sense, you can use any i/o pin to make pwm output, that's is genius....but first i need to know how it works...can i use the same timer for other pwm output at the same time as well? and if not much of a trouble, can you translate those code into assembly?. i just want to get the idea....oh i'm using pic18f458
 

Pommie

Well-Known Member
Most Helpful Member
If you look further down the linked thread you will see that another member (Futz) converted it to assembly.

Mike.
 

WISEMEN

New Member
hi, i have a question...in the assembly code, what does LATB means? is it the same as PORT B?

main btfss PIR1,CCP1IF ;wait for CCP interrupt bit
goto main
bcf LATB,3 ;end pulse
movlw 0x4e ;Off time = 20ms - Servo Time
movwf src1
movlw 0x20
movwf src2


why is it 4e and 20?

and also in the code, 0x05 move to ccpr1h and 0xdc to ccpr1l, is this the minimum and maximum range of the period? and if i want to have 25ms then i have to put 0xff into ccpr1l correct? my servo is 180 degree....
 

Pommie

Well-Known Member
Most Helpful Member
LATB is the output latch of PortB to prevent RMW problems. Just think of it as the place to write to Port B.

The value 0x4e20 = decimal 20,000 = 20mS. 0x05dc = 1500 = 1.5mS. You get these values because in assembly you can only use 8 bit variables. I think in the thread I suggested he changed it to,
Code:
main		btfss	PIR1,CCP1IF	;wait for CCP interrupt bit
		goto	main
		bcf	LATB,3		;end pulse
		movlw	high(d'20000')	;Off time = 20ms - Servo Time
		movwf	src1
		movlw	low(d'20000')
		movwf	src2
As this is more readable.

Mike.
 

WISEMEN

New Member
i've been through this code over and over again, and if i'm not mistaken, the duty cycle is generated at the end of the the period cycle, instead of at the beginning. is that right? so i guess it won't be any problem since servo works base on the duty cycle width instead of WHEN it is generated in time in a single period, right? I have tried this code and it worked. i just gotta change my potentiometer to about 5k. bcos right now i'm using 100 ohm. and try to tweak this code to use with 10 servo....
thanks mike you're a life saver.....
 

Pommie

Well-Known Member
Most Helpful Member
Just think of it as a sequence of events, read pot, convert to time, make pulse, read pot etc. It just happens that the pulse part is first in code.

To make it work with 10 servos is going to be difficult as you need over 2mS per servo and there are not enough time slots in 20mS. However, most servos will work perfectly well with a pulse every 25mS and so it should be doable. I suggest that you look at the interrupt version of the code as this will free up the processor to do other things - I assume you need to calculate or receive positions.

Mike.
 

WISEMEN

New Member
I don't understand, there are 20ms period, but the servo range is between 0.5ms to 2.5ms why is it like this? why can't we use the other 17.5ms space? and when you say over 2ms per servo, that means we have to assign for each servo a time slot without overlaping with another dutycycle, is it? can't we just make the period larger? what happen if we make it larger?
 

Pommie

Well-Known Member
Most Helpful Member
The normal pulse period for a servo is 1 to 2 mS but newer servos tend to accept a wider range of values such as 0.8 to 2.2mS. They expect to get a pulse every 20mS or they start to loose position (drift). To output a timed pulse requires the hardware to be tied up doing it and so each servo will require a time slot of upto 2.2mS. So, with 10 servos you need 10 time slots and so they will only get updated every 22mS. In reality you can't start a new pulse immediately after the previous one and so your slots will need to be slightly longer and your update rate will probably end up nearer 25mS.

Mike.
 

WISEMEN

New Member
that means only about 8 servo can fit into 20ms period huh? what if i use timer 3 and timer 1 each 20ms will that work? and how do i get the servo to move up to 180 degrees with potentio meter, but potentiometer only have max value of 03ff with right justify. my servo spec is 0.5ms to 2.5 ms, but in the code it only can generate upto 2.023. so my range is only 1023 instead of 2000 like in the spec.
 

Sceadwian

Banned
Only 8 servos an fit into a 20ms period if they're run one after the other....
If they're all run at the same time and stopped when their timers expire you can run a lot more at once with decent resolution. And you can run even more additional banks aside from that, as long as the resolution isn't too high.
 

WISEMEN

New Member
But with my project, i need to control about 8 servo independently, if i move 2 potentiometer at once ,will both servo respond smoothly or there will be a lag to one of the servo? And how do i make the servo to move 180 degrees....? Can you please help me...?
 

Sceadwian

Banned
Servos are designed to move from a 0 state to +45 or -45 degrees from that state (90 degrees total) stretch or shrink the 1-2ms pulse with to .5 and 2.5ms and you MAY get 180 degrees, or not, and it probably won't be linear both ways.

You need to define smoothly, IE the delay after you trigger the POT to it's effect at the control surface, typically, regardless of the servo controller the delay is no more than about 20ms from a position change in the joystick to a signal getting to the servo.
 

Mr RB

Well-Known Member
Have you even got 1 servo working yet? You should do that first and then get 1 pot working with that servo. Then if you post your code people can help you with suggestions.

You keep asking for more and more complex help but there is no sign you have done anything yet.
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top