Triode
Well-Known Member
I'm still trying to improve my servo signal capture project. I found a useful document **broken link removed** which explains how servo pulses are timed relative to each other. I have modified my code to check for the delays between pulses as well and that part seems to work. If I hook up channel 1 and 3 I get two readings, I was pretty excited about that, but if I hook up channel 1 and 2, 2 and 3 or 1,2 and 3 I get nothing. I think maybe it's not fast enough to catch the gap between them, or it could be some issue I haven't even thought of. Being a mechanical engineer but an electronics beginner you guys have gotten me unstuck before. Any ideas what could cause this behavior? And is there a way to make the capture any more accurate?
Code:
//Basic configureation of chip periferials
#pragma config OSC = INTIO2, WDT = OFF, LVP = OFF
#include <p18f1320.h>
#include <delays.h>
#include<timers.h>
//setup pins for PWM input
#define ReceiverPin PORTBbits.RB3
#define ReceiverTris TRISBbits.TRISB3
//PWM capture variables
unsigned int PWM1RiseTime = 0; //timer value at rising edge capture
unsigned int PWM1FallTime = 0; //timer value at falling edge capture
unsigned int PWM1Width = 0; //calculated width
unsigned int channel1_width = 0;
unsigned int channel2_width = 0;
unsigned int channel3_width = 0;
unsigned int channel4_width = 0;
unsigned int PWMGap = 0; //calculated gap between pulses
char PWM1Edge = 1; //edge currently being monitored 1 = rising, 0 = falling
unsigned char Channel_Being_Captured = 1; //this will record which channel is being watched
//set up interrupt
void low_ISR(void);//prototype
#pragma code low_vector = 0x08 //0X08 IS LOW 0X18 IS HIGH
void low_interrupt (void){
_asm goto low_ISR _endasm
}
#pragma code
#pragma interrupt low_ISR
void main(void)
{
OSCCON = 0x72; //8MHz clock
while(!OSCCONbits.IOFS); //Wait for OSC to become stable
//configure timer1
//OpenTimer1(0b10010101);
//PIE1bits.TMR1IE = 1; //periferial interupt register, 1 = timer 1 interupt enabled
PIR1bits.TMR1IF = 0; //clears the timer 1 interupt flag
T1CONbits.TMR1ON = 1; //turn on timer
T1CONbits.T1CKPS1 = 0; //set prescaler
T1CONbits.T1CKPS0 = 0; //set prescaler
//setup timer2
OpenTimer2(TIMER_INT_ON);
PIR1bits.TMR2IF = 0; //clears the timer 2 interupt flag
PR2 = 20;
T2CON = 0b00000100; //(-)always 0 (----) postscale (-)on/off (--) prescale
//configure CCP1
CCP1CON = 0b0000101; //configure CCP1 for capture, rising edge
INTCONbits.PEIE=1; //enable peripheral interrupts
PIE1bits.CCP1IE=1; //enabled CCP1 interrupt
INTCONbits.GIE=1; //enable branching to interrupt
ReceiverTris = 1; //set RB3 for input so the capture can work.
TRISBbits.TRISB2 = 1; //set rb2 for in so it can be used to differentiate channels
//configure ports
ADCON1 = 0xff; //all digital
INTCON2bits.RBPU = 0; //port b weak pullups on
//configure control bits for output
TRISAbits.TRISA0 = 0;
TRISAbits.TRISA6 = 0;
//controll bits for second motor
TRISAbits.TRISA1 = 0;
TRISAbits.TRISA4 = 0;
while(1)
{
}
}
void low_ISR(void)
{
//Timer 2 flag
if(PIR1bits.TMR2IF == 1)
{
PIR1bits.TMR2IF = 0; //clears the timer 1 interupt flag
}
//ccp interrupt
if(PIR1bits.CCP1IF == 1)
{
PIR1bits.CCP1IF = 0; //clear the flag
if(PWM1Edge == 1)//if detecting rising
{
CCP1CON = 0b0000100;//switch to detect falling edge
PWM1RiseTime = CCPR1;//save the low timer value for the rise time
PWM1Edge = 0;//switch to indicate falling edge is next
PWMGap = CCPR1 - PWM1FallTime; //calculate what the gap between pulses was
if (PWMGap>25000){Channel_Being_Captured = 1;}
}
else //if detecting falling
{
CCP1CON = 0b0000101;//switch to detect rising edge
PWM1FallTime = CCPR1; //save the time of the pwm fall
PWM1Edge = 1;//switch to indicate rising edge is next
PWM1Width = CCPR1 - PWM1RiseTime; //(pwm rise time is the time that the pwm rise occured)
//store in the apropriate channel
if(Channel_Being_Captured == 1){channel1_width = PWM1Width;}
if(Channel_Being_Captured == 2){channel2_width = PWM1Width;}
if(Channel_Being_Captured == 3){channel3_width = PWM1Width;}
if(Channel_Being_Captured == 4){channel4_width = PWM1Width;}
Channel_Being_Captured ++; //go to next channel
}
}
}