• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Servo reciever with working variable speed bi-dir

    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.

    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 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
 

EE World Online Articles

Loading

 
Top