Home PIC 18F1320 Servo Slowdown with Junebug 18F1320

Main Menu

Servo Slowdown with Junebug 18F1320

thumbWhile 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. Cool 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
}
}