Continue to Site

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.

  • 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.
i'm sorry...but i've already done with one servo.. that's why i'm asking how to make it to go 180, because it only went until 90. and after a few calculation i found that the 10 bit resolution for AD is only giving 30ff which is 1023 and my servo can go until 2032.... CAN YOU HELP ME....PLEASE
 
The servo's output position has nothing to do with the AD converter. It has to do with the duty cycle of the PWM signal you're sending it.
1.5ms is center 1ms is -45 degrees 2ms is +45 degrees giving you a 90 degree range of motion. You can try sending it shorter signals like .5ms and 2.5ms to get more of a travel angle out of it, but it won't be linear and you may not get a full 180 degrees. You'll have to experiment with the servo's you have.
 
but when i input the value manually using code, i can get full 180 even more and could risk damaging the servo for over movement, but with potentiometer it only get about 90, i tried to use an on off switch to increment the value every cycle as the code below

#include <p18f458.inc>

ORG 0X00
GOTO main
ORG 0X08
RETFIE
ORG 0X18
RETFIE



CBLOCK 0X20

ServoPosH,ServoPosL,src1,src2,dst1,dst2,src1a,src2b

endc


main movlw 1
movwf src1a
movwf src2b
bsf TRISC,A
bcf PORTC,A
movlw 0x00
MOVWF OSCCON
bcf TRISB,3 ;make servo pin output
bcf LATB,3 ;Servo output off
movlw b'00001011' ;Special event trigger
movwf CCP1CON
movlw b'10100001' ;Timer 1 on with Pre=4
movwf T1CON
movlw 0x01 ;set servo to min position
movwf ServoPosH
movwf CCPR1H ;and set CCP initial value
movlw 0xf4
movwf ServoPosL
movwf CCPR1L

start btfss PIR1,CCP1IF ;wait for CCP interrupt bit
goto start
bcf LATB,3 ;end pulse
movlw 0x4e ;Off time = 20ms - Servo Time
movwf src1
movlw 0x20
movwf src2
movff ServoPosH,dst1
movff ServoPosL,dst2
call sub16
movff dst1,CCPR1H
movff dst2,CCPR1L
bcf PIR1,CCP1IF ;clear int flag
btfsc PORTC,0,A
call forward
btfsc PORTC,1,A
CALL reverse
movff src1a,src1
movff src2b,src2
movlw 0x01
movwf dst1
movlw 0xf4
movwf dst2
call add16
movff dst1,ServoPosH
movff dst2,ServoPosL
wait btfss PIR1,CCP1IF ;wait for int flag
goto wait
bsf LATB,3 ;start pulse
movff ServoPosH,CCPR1H ;Servo time in uS
movff ServoPosL,CCPR1L
bcf PIR1,CCP1IF ;clear int flag
goto start

sub16 movf src2,W
subwf dst2,F
movf src1,W
btfss STATUS,C
incf src1,W
subwf dst1,F
return

add16 movf src2,W
addwf dst2,F
movf src1,W
btfsc STATUS,C
incf src1,W
addwf dst1,F
return

forward incf src2b
btfsc STATUS,OV
incf src1a
return

reverse decf src1a
btfsc STATUS,Z
decf src2b
RETURN



end​

BUT IT DOESN'T SEEMS TO WORK.....

I DON'T KNOW HOW TO POST THE CODE PROPERLY.....SORRY
 

Attachments

  • servoSW.asm
    1.7 KB · Views: 133
Last edited:
if i'm not mistaken this code is for 40Mhz pic right that's why the cycle is exacly 4e20 or 20000 cycle to generate 20ms period. my pic is using 20Mhz crystal, if my calculation is right i need to generate 100000 cycle for 20ms period. is this correct? i'm not really good about this calculation stuff......maybe that's why my servo only travel 90 degrees even after i scaled up the adresh/l to double it....is this the problem? can someone help me..i would really appreciate it....
 
The code is for an 8MHz pic with the timer prescaler set to 2 so the timer increments in uS. With a 20MHz pic I would set the prescaler to 4 and the value for a 20mS interval would be 20,000,000/4/4*0.02 = 25000. Likewise, 1mS will be 1250.

Mike.
 
man i am so stupid.. thank you MIKE. I have a question about the OSCCON register, this register is to switch between external clock and internal clock as said in the data sheet, what does it mean exactly?
 
hi poeple, i have another question that i need to ask.....if i'm using this manually generated pwm,is that means i only can have 20ms time for the whole program in the pic ? if i need to run another subroutine does it has to be in the 20ms cycle, if i for example make a 5 sec delay for other sub routine will the servo return back to 0 pisotion?

if i'm using the ccp pwm module, does the module will keep repeat the period pulse even other sub routine is running (even) with delay ?
 
Last edited:
wiseman, that depends entirely on how you write the PWM generation software weather or not it's timer/interrupt based or how you otherwise implement it and the rest of your code.
There's no reason you can't run a relatively slow (even multiple) PWM channels and other code at the same time, but you have to make sure the code doesn't cause collisions or glitches with each other, and since you're the one writing the software it's not a question we can actually answer.
 
actually i took this one from mike..... from the mike's code, it is 20ms period and keep on looping to to give a steady update to the servo for every 20ms, and for what i know if the update is a bit longer the servo will start to drift and started to jitter.. assembly code execute the program line by line right? is it possible to run the prog simultaneously, means that one program will keep on looping every 20 ms and other prog can run for other sub routine...?
 
The servo signal goes through a pulse stretcher, and that signal is what drives the actual motor driver. Jitter depends on load, and the feedback electronics. You really need to test your code to see if it will work in your situation. Personally, I think 20ms period (50hz) is abysmally slow, and I've over driven standard servos to around 150hz before the pulse stretching circuit overlaps and the servo starts to tweak out. Higher is better as long as it can still function in the range required. Applied torque is higher, the function when overdriven (properly) is almost as good as so called 'digital' servos
 
thanks it does has better torque...now since most of my servo knowledge went completely south, what does the period of the servo actually means, my servo specs says 20ms period max and 0.5-2ms duty cycle...so the 20ms period update rate is wrong then?
 
I'VE MADE IT...I'VE MADE THE SERVO GO 180....but still a bit sloppy...and i need to figure out why....i'm really happy right now....
 
i need a comment on this one...since the adc only 10 bit that means it can only generate 1023 decimal numbers, and when my clock configuration is set so that to generate 20ms it must have 20000 cycle that means i can only get maximum duty cycle of 1.023ms, but i need 1.5ms maximum duty cycle, or 1500.........

what if i use 11Mhz clock cycle with prescale 4?

11mhz/4/4x0.0015=1031.25 cycle close to 1023 .....will this work?....do they make 11Mhz crystal?......
 
You take the ADC reading and multiply it to get the desired value. If you need 0.8 to 2.2mS then the range is 1.4 seconds. So, you take 1024 and multiply by 1.4 and then add 800 to give the required values. This is for a timer setup to increment in 1uS intervals.

As for doing other things whilst driving the servos, you can run the pulse code completely on interrupt and have the main process do whatever else you wish. See the original thread for the interrupt driven example.

Mike.
 
i have tried the multiplying version but it didn't turn smoothly, if i turn the potentiometer very quickly back and forth it went smoothly....but if turn it slowly it jitters......i just multiply it it with 2...........

about the interupt version...i don't really understand the program.....i thought interupt will stop other subroutine while executing the interupt and will start back at the main program....


how do you multiply decimal point in assembly...?
 
Last edited:
If you use interrupts the main code will be stopped for a very short time when a pulse starts or stops. The rest of the time (99.5%) it is free to run the main code.

To multiply by decimal in assembly you switch to C. Just kidding but it is a little tricky.

To multiply by 1.5 you half the number (shift right once) and add it to itself.
For 1.25 you shift twice and add.
For 1.4 you need to approximate. The nearest binary number is 1.375 which is 1+¼+⅛. So you shift right twice and add then shift once more and add.
Or, you switch to C.:)

Mike.
 
Status
Not open for further replies.

Latest threads

Back
Top