- Blog entry posted in 'Uncategorised', February 22, 2010.
I finally got that timer interrupt working, and so here is my first code that does all of my original project statement. It takes a servo PWM signal and outputs a motor controlling, multi level, bidirectional PWM signal. I'm sure it could use some cleaning up, but basically it captures the signal the same way as before, but now it uses an Timer 2 interrupt to generate a signal at pins A0 and A6. For now I have the range all set by variables, later I would like to add some calibration buttons, which set the low and high range based on what signal they're getting when the buttons are pressed. So the user would just push the joystick high and click the high range setter, and likewise for low and middle. Here's the code, if anyone actually reads this feel free to ask me a question, I check it almost every day.
//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 PWM1Width = 0; //calculated width
char PWM1Edge = 1; //edge currently being monitored 1 = rising, 0 = falling
//variables to figure out relative range once signal is captured
unsigned int PWMRangeTop = 4330; //top of range
unsigned int PWMRangeBottom = 2350; //bottom of range
unsigned int PWMRangeMiddle = 3280; //middle of range
unsigned int PWMRangeWidth; //span of range
unsigned char PWMCenterWidth = 10; //width of band in middle with no movement as fraction of total
unsigned int PWMCenterTop;
unsigned int PWMCenterBottom;
unsigned char MotorControlRez = 16; //the number of different levels low and high the motor can run at
//motor PWM variables (prefix with MOT1)
unsigned char MOT1CyclePos = 0; //used to hold position in PWM duty cycle
unsigned char MOT1HighTime = 0; //holds amount of time that it should be high
//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)
{
unsigned int MotorCount = 1;
unsigned char MotorOn;
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
//set values for center range ends
PWMRangeWidth = PWMRangeTop - PWMRangeBottom;
PWMCenterTop = PWMRangeMiddle + (PWMRangeWidth/PWMCenterWidth);
PWMCenterBottom = PWMRangeMiddle - (PWMRangeWidth/PWMCenterWidth);
//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.
//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;
while(1)
{
}
}
void low_ISR(void)
{
//Timer 2 flag
if(PIR1bits.TMR2IF == 1)
{
PIR1bits.TMR2IF = 0; //clears the timer 1 interupt flag
//handle motor controll pulses
//upper is about 2150, lower is about 1210
//middle is near 1640 to 1660
//vars are MOT1CyclePos MOT1HighTime
MOT1CyclePos++; //move up in cycle
if(MOT1CyclePos > MotorControlRez){MOT1CyclePos = 0;} //loop at end of cycle
//Port output of PWM signal
if(MOT1CyclePos > MOT1HighTime)
{
LATAbits.LATA6 = 0;
LATAbits.LATA0 = 0;
}
else
{
if(PWM1Width > PWMCenterTop)
{
LATAbits.LATA6 = 0;
LATAbits.LATA0 = 1;
}
if(PWM1Width < PWMCenterBottom)
{
LATAbits.LATA6 = 1;
LATAbits.LATA0 = 0;
}
}
}
//ccp interrupt
if(PIR1bits.CCP1IF == 1)
{
PIR1bits.CCP1IF = 0; //clear the flag
if(PWM1Edge == 1)//if detecting rising
{
PWM1RiseTime = CCPR1;//save the low timer value for the rise time
CCP1CON = 0b0000100;//switch to detect falling edge
PWM1Edge = 0;//switch to indicate falling edge is next
//Generate motor controll timing length
if(PWM1Width > PWMCenterTop) //scaled distance from center in positive direction
{
MOT1HighTime = ((PWM1Width-(PWMCenterTop-30))*MotorControlRez)/(PWMRangeTop - PWMCenterTop);
}
if(PWM1Width < PWMCenterBottom) //scaled distance from center in negative direction
{
MOT1HighTime = (((PWMCenterBottom+30)-PWM1Width)*MotorControlRez)/(PWMCenterBottom-PWMRangeBottom); //the 30 is for a end space to go to full power
}
if(PWM1Width > PWMCenterBottom && PWM1Width < PWMCenterTop)
{
MOT1HighTime = 0;
}
}
else //set to detecting falling edge of incomming PWM signal
{
PWM1Width = CCPR1 - PWM1RiseTime;
CCP1CON = 0b0000101;//switch to detect rising edge
PWM1Edge = 1;//switch to indicate rising edge is next
}
}
}
Is the code all showing up in one line for anyone else? It wasn't doing that before.Comments