|
While debugging the code for the 12F683 servo slowdown project I had the need for a debugger to find a weird problem. But you can't debug a 12F683 unless you spend $35+ for Microchip's debuggable 14-pin version of the chip. So I ported the code to the 18F1320 on the Junebug.
I tried several different methods before settling on something that would work on the 12F683 as well as the 18F1320. And I cured my weird problem completely. Works very well. The Olimex ARM7 board outputs a servo pulse-train which varies according to the position of the potentiometer you can see me turning in the photo (right). I connect that output to RB3 on the 18F1320. The breadboard still has the 12F683 circuit on it, but that's not connected. I'm only using the servo connector for convenience. Both circuit boards and the breadboard have common grounds, and the Junebug is supplying 5V for the breadboard/servo. I'm using RB4 on the 18F1320 as the servo output. VR1 on the Junebug sets the servo speed. If VR1's value is <5 then the servo runs at full speed. 
Here's the code: /*-----------------------------------------------------------*/ /*PIC 18F1320 */ /*Measures servo input pulses on RB3 and outputs matching */ /*pulse-train on RB4, but slowed by the amount selected */ /*by pot value. If pot value is <5 then servo runs at full */ /*speed. */ /*To change setting either stop input pulse-train or briefly */ /*kill the power to the 18F1320. */ /*-----------------------------------------------------------*/
#include <system.h> #pragma CLOCK_FREQ 8000000 #pragma DATA _CONFIG1H, _INTIO2_OSC_1H #pragma DATA _CONFIG2H, _WDT_OFF_2H #pragma DATA _CONFIG3H, _MCLRE_ON_3H #pragma DATA _CONFIG4L, _LVP_OFF_4L
unsigned int loop1(void); void movedown(void); void moveup(void); unsigned int straight_thru(void); unsigned int pulsin(void); void pulsout(int);
unsigned int pwinprev,pwout,pwinerr; volatile unsigned int pwin,start,end; unsigned char delay,skip; volatile unsigned char flag;
void main() { osccon = 0x72; //set int osc to 8MHz trisa = 0b00000010; //set data directions trisb = 0b00001000; adcon0 = 0b00000100; //VREF = AVDD/AVSS adcon1 = 0b01111101; //AN1 is analog, the rest digital adcon2 = 0b00011101; //left justified,6TAD,FOSC/16 ccp1con = 0b00000101; //capture rising edge t1con = 0b00010001; //Timer1 enable, pre=2 rcon.IPEN = 0; //disable priority interrupts pie1.CCP1IE = 0; //disable ccp1 interrupt pie1.TMR1IE = 0; //disable timer1 overflow interrupt intcon.PEIE = 1; //enable peripheral interrupts intcon.GIE = 1; //disable global interrupts
while(1){ do{ skip = 0; pulsout(1000); //sorta center servo delay_ms(2); adcon0.ADON = 1; //enable A/D on AN1 adcon0.GO = 1; //start conversion while(adcon0.DONE); //wait for conversion to complete delay = adresh; //get 8-bit A/D value adcon0.ADON = 0; //disable A/D on AN1 pulsin(); //read incoming pulse width }while(pwin == 0); pwinprev = pwin; if(delay < 5) straight_thru(); delay = delay / 21; pwout = pwin; loop1(); } }
unsigned int loop1(void) { while(1){ pwinprev = pwin; pulsin(); if(pwin == 0) return 0; pwinerr = pwin - pwout; if(pwinerr < 8 || pwinerr > 0xfff8) pulsout(pwout); //stay put else if(pwout < pwin) moveup(); else if(pwout > pwin) movedown(); } }
void movedown(void) { if(skip < delay){ skip += 1; } else{ skip = 0; pwout -= 12; } pulsout(pwout); }
void moveup(void) { if(skip < delay){ skip += 1; } else{ skip = 0; pwout += 12; } pulsout(pwout); }
unsigned int straight_thru(void) { while(1){ pulsin(); if(pwin == 0) return 0; pwinerr = pwin - pwinprev; if((pwinerr < 8) || (pwinerr > 0xfff8)){ pulsout(pwinprev); } else{ pulsout(pwin); pwinprev = pwin; } } }
void pulsout(int width) { unsigned int temp; t1con.TMR1ON = 0; //timer1 disable temp = 7 - width; //preload timer1 HIBYTE(tmr1h,temp); LOBYTE(tmr1l,temp); pie1.TMR1IE = 1; //enable timer1 overflow interrupt t1con.TMR1ON = 1; //timer1 enable portb.RB4 = 1; //start servo pulse }
unsigned int pulsin(void) { int f; flag = 0; pie1.CCP1IE = 1; //enable ccp1 interrupt for(f=0;f<3200;f++){ //wait for pulse measurement if(flag){ //if pulse measured then pie1.CCP1IE = 0; //disable ccp1 interrupt return 0; //and return } } pwin = 0; //but if no pulse then timeout pie1.CCP1IE = 0; //disable ccp1 interrupt }
void interrupt(void) { if(pir1.CCP1IF){ //timer1 capture interrupt if(portb.RB3){ //rising edge detected start = ccpr1l; //store start value start |= ccpr1h << 8; ccp1con = 0b00000100; //set to capture falling edge } else{ //falling edge detected end = ccpr1l; //store end value end |= ccpr1h << 8; ccp1con = 0b00000101; //set to capture rising edge flag = 1; if(end < start){ pwin = (0xffff - start) + end; } else{ pwin = end - start; } } pir1.CCP1IF = 0; //clear interrupt flag } if(pir1.TMR1IF){ //timer1 overflow interrupt portb.RB4 = 0; //end servo pulse pie1.TMR1IE = 0; //disable timer1 overflow interrupt pir1.TMR1IF = 0; //clear interrupt flag } }
|