18F46K22 PBP2.6C
Ok, wanting to command a servo... but, want to use interupts so that the pic can do other things and/or drive multiple servo's...
So, first of all, i started off doing it with PAUSEUS to make sure i get the timings right...
Simples... works perfectly...Code:SERVO1 VAR LATD.0 SERVO1POS VAR BYTE MAIN: SERVO1POS = 128 FOR ALOOP = 1 to 250 SERVO1 = 1 PAUSEUS 988 PAUSEUS (SERVO1POS * 4) SERVO1 = 0 PAUSEUS (20000 - (988 + (SERVO1POS * 4))) NEXT ALOOP SERVO1POS = 1 FOR ALOOP = 1 to 250 SERVO1 = 1 PAUSEUS 988 PAUSEUS (SERVO1POS * 4) SERVO1 = 0 PAUSEUS (20000 - (988 + (SERVO1POS * 4))) NEXT ALOOP SERVO1POS = 255 FOR ALOOP = 1 to 250 SERVO1 = 1 PAUSEUS 988 PAUSEUS (SERVO1POS * 4) SERVO1 = 0 PAUSEUS (20000 - (988 + (SERVO1POS * 4))) NEXT ALOOP GOTO MAIN
So now i start doing the math and working out the preloads for timers with the help of an excell spreadsheet.
And thats where i now have a problem and i don't understand why.Code:SERVO1 VAR LATD.0 SERVO1POS VAR BYTE PRELOAD1 VAR WORD PRELOAD2 VAR WORD PRELOAD3 VAR WORD SERVOCMDMODE VAR BYTE SERVOPWMCOUNTER VAR WORD PRELOAD1 = 63556 ' 990us '63556 TMR0_CON_PL1 CON %10000010 ' 1:8 PRELOAD2 = 65528 ' 4us '65528 TMR0_CON_PL2 CON %10000010 ' 1:8 PRELOAD3 = 29556 ' 17990us '29556 TMR0_CON_PL3 CON %10000010 ' 1:8 @ INT_ENABLE TMR0_INT TMR0L = PRELOAD3.LOWBYTE TMR0H = PRELOAD3.HIGHBYTE T0CON = TMR0_CON_PL3 SERVOCMDMODE = 1 MAIN: SERVO1POS = 0 PAUSE 5000 SERVO1POS = 128 PAUSE 5000 SERVO1POS = 255 PAUSE 5000 GOTO MAIN SERVO_HANDLER: IF SERVOCMDMODE = 2 Then IF SERVOPWMCOUNTER < 256 THEN T0CON = TMR0_CON_PL2 TMR0L = PRELOAD2.LOWBYTE TMR0H = PRELOAD2.HIGHBYTE IF SERVO1POS < SERVOPWMCOUNTER THEN SERVO1 = 0 LATD.1 = 0 LATD.2 = 0 LATD.3 = 0 ELSE SERVO1 = 1 LATD.1 = 0 LATD.2 = 1 LATD.3 = 0 ENDIF SERVOPWMCOUNTER = SERVOPWMCOUNTER + 1 ELSE T0CON = TMR0_CON_PL3 TMR0L = PRELOAD3.LOWBYTE TMR0H = PRELOAD3.HIGHBYTE SERVO1 = 0 LATD.1 = 0 LATD.2 = 0 LATD.3 = 1 SERVOCMDMODE = 1 ENDIF @ INT_RETURN ENDIF IF SERVOCMDMODE = 1 Then T0CON = TMR0_CON_PL1 TMR0L = PRELOAD1.LOWBYTE TMR0H = PRELOAD1.HIGHBYTE SERVOCMDMODE = 2 SERVO1 = 1 LATD.1 = 1 LATD.2 = 0 LATD.3 = 0 SERVOPWMCOUNTER = 1 @ INT_RETURN ENDIF @ INT_RETURN
For debug purposes i added the three LATD outputs so that i could find where i was having issues.
First off, the frequency is 46.75... ok, i'm sure it can still handle it, and i can adjust this later.
Secondly, the duty cycle goes from 84.0% to 93.9% to 99.6%...
It should be 5%, 7.5% and 10%...
Debug output shows LATD1 at 84.4%...
LATD1 is for pre-duty phase, when in my code is SERVOCMDMODE = 1
It's on for 84% of the time and it shouldn't, it should be 5%...
I'm looking at my code thinking 'that is not possible'...
So, I've got to have made a stupid mistake somewhere and i can't see it. Can some wonderful person tell me what my stupid mistake is?
Thanks




Bookmarks