Example #1
0
void __attribute__((interrupt, no_auto_psv)) _CNInterrupt(void) {
    unsigned int ccwpat[] = {-1, 3, 6, 2, 5, 1, 4, -1};
    unsigned int cwpat[] = {-1, 5, 3, 1, 6, 4, 2, -1};

    state = (S3 << 2) | (S2 << 1) | S1; //Read hall effect sensors
    if(motoron == 1){     //If the motor has been turned on
        // is state transition valid?
        if (last_state == -1 || (state == ccwpat[last_state] || state == cwpat[last_state])) {
            commutate(state); //Change outputs based on hall effect sensor state
        }
    } else {              //If the motor is off
        commutate(0);     //Set all motor outputs to float
        printf("motor off: current state is %d\n", state);
    }

    if(USER) {
        commutate(0);
        motoron = 0;
    }

    if (last_state && (state != ccwpat[last_state] && state != cwpat[last_state])) {
        LED1 = 0;
        //commutate(0);
        //printf("noisy state...ending program\n");
        //printf("last state: %u  next state: %u valid next states: %u %u\n",
        //        last_state, state, ccwpat[last_state], cwpat[last_state]);
        /*
        while (1) {
            LED3 = !(state & 0x1);
            LED2 = !(state & 0x2);
            LED1 = !(state & 0x4);
        }
        */
    }
    else {
        LED1 = 1;
    }

    if(state == 0 || state == 7) {
        char reread = (S3 << 2) | (S2 << 1) | S1; //Read hall effect sensors
        commutate(0);
        printf("error state...ending program\n");
        printf("last state: %u  next state: %u valid next states: %u %u\n",
                last_state, state, ccwpat[last_state], cwpat[last_state]);

        
        printf("reread port and got %d as the current state\n", reread);

        while (1);
    }

    last_state = state;

    //LED1 = !LED1;
    //printf("%d",state);
    PORTD;                //Clear mismatch condition
    IFS1bits.CNIF = 0;    //Clear interrupt flag
}
Example #2
0
/* _CNInterrupt is the change notification interrupt trigger by a change in
 * state of the hall effect sensor inputs. The interrupt service routine reads
 * the hall effect sensor state and calls the commutate function to change the
 * motor lead outputs.
 *
 * Interrupt vector names are in Table 7-4 p101 of the MPLAB C30 User's Guide
 */
void __attribute__((interrupt, no_auto_psv)) _CNInterrupt(void) {
    state = (S3 << 2) | (S2 << 1) | S1; //Read hall effect sensors
    if(motoron == 1){     //If the motor has been turned on
        commutate(state); //Change outputs based on hall effect sensor state
    } else {              //If the motor is off
        commutate(0);     //Set all motor outputs to float
    }
    LED1 = !LED1;
    //printf("%d",state);
    PORTD;                //Clear mismatch condition
    IFS1bits.CNIF = 0;    //Clear interrupt flag
}
void TIM3_IRQHandler(void)
{
  /* "Read" all sensors sequence and execute the BLDC coils commutation */
  commutate ();

  /* Save current time between each hall sensor signal change */
  hall_sensors_time = TIM_GetCapture1(TIM3);

  // clear interrupt flag
  TIM_ClearITPendingBit (TIM3, TIM_IT_Trigger);
}
Example #4
0
int main(void) {
    int duty = 500;
    initialize();
    write_duty(duty); //apply duty cycle change
    motoron = 1;//turn motor on
    kick();//kick start commutation
    while (1){
        commutate(2);
        __delay32(40000000);
        commutate(4);
        __delay32(40000000);
        commutate(3);
        __delay32(40000000);
        if(USER){
            motoron=0;
        }
        LED1 = !S3;
        LED2 = !S2;
        LED3 = !S1;
        //test_MayDay();
    }
    return 0;
}
Example #5
0
/* The kick function needs to be called when the motor is starting from rest.
 * If the motor is not rotating the change notification interrupt will not
 * trigger and the commutate function will not be called. The kick function
 * drives the motor to change the hall effect sensor inputs.
 */
void kick(void){
    int kick;
    int state;
    int CWtable[6] = {5,3,1,6,4,2};
    int CCWtable[6] = {3,6,2,5,1,4};
    state = (S3 << 2) | (S2 << 1) | S1;
    if(direction==CW){
        kick = CWtable[state-1];
    } else{ //direction == CCW
        kick = CCWtable[state-1];
    }
    printf("%d",kick);
    commutate(kick);
}
Example #6
0
void motor_start(MOTOR *p) 
{
    p->state = STATE_START;
    p->phase = 1;
    p->start_counter = 0;
    *(p->phase_a_pwm) = 800;
    *(p->phase_b_pwm) = 800;
    *(p->phase_c_pwm) = 800;
    p->start_comm_period =  US_TO_TICKS(10000);
    commutate(p);
//    TIM_ITConfig(TIM10, TIM_IT_CC1, ENABLE);
    TIM10->DIER |= TIM_IT_CC1;
    *(p->commutate_timer) = *(p->commutate_counter) + p->start_comm_period;
    p->prev_comm_ticks = *(p->commutate_timer);
    p->start_comm_period = ((p->start_comm_period * 15) >> 4);
}
Example #7
0
/* The pulse width modulation module controls the motor torque by changing the
 * amount of time the on voltage is applied. The PWM module runs at 20kHz in
 * complementary mode to work with the HIP4086 BLDC driver.
 * In complementary mode each of the three PWM modules controls two outputs
 * whose states are the inverse of each other.
 * The module incorporates a dead time delay between the falling edge of one
 * signal and the rising edge of the next to prevent shoot through.
 */
void initialize_PWM(void){
    
    PTCON2bits.PCLKDIV = 0b010; //PWM input clock prescaled by 1:4
    //Period = 80 MHz / (PTPER * Prescaler)
    //PTPER = 80 MHz / (20kHz * 4) = 1000
    PTPER = 1000;
    //PTPER = 80 MHz / (50kHz * 4) = 400
    PTPER = 400;

    IOCON1bits.PMOD = 0; //Set PWM1 to Complementary Mode
    IOCON2bits.PMOD = 0; //Set PWM2 to Complementary Mode
    IOCON3bits.PMOD = 0; //Set PWM3 to Complementary Mode

    //DTR = Fosc * Deadtime / Prescaler
    //DTR = 80MHz * 0.5us / 4
    DTR1 = DTR2 = DTR3 = 10; //Set deadtime of 0.5us
    ALTDTR1 = ALTDTR2 = ALTDTR3 = 10; //Set alternate deadtime of 0.5us

    //Enable PWM outputs
    IOCON1bits.PENH = 1;
    IOCON1bits.PENL = 1;
    IOCON2bits.PENH = 1;
    IOCON2bits.PENL = 1;
    IOCON3bits.PENH = 1;
    IOCON3bits.PENL = 1;
    //Set polarity of PWM registers
    IOCON1bits.POLH = 1; //PWM1H pin is active-low
    IOCON2bits.POLH = 1; //PWM1H pin is active-low
    IOCON3bits.POLH = 1; //PWM1H pin is active-low
    IOCON1bits.POLL = 0; //PWM1L pin is active-high
    IOCON2bits.POLL = 0; //PWM1L pin is active-high
    IOCON3bits.POLL = 0; //PWM1L pin is active-high

    //Use MDC register to provide duty cycle information for all PWM modules
    PWMCON1bits.MDCS = 1;
    PWMCON2bits.MDCS = 1;
    PWMCON3bits.MDCS = 1;

    MDC = 100; // Sets master duty cycle at 10%. 100% is at MDC = 1000
    MDC = 10;

    commutate(0); //Set all motor outputs to float

    PTCONbits.PTEN = 1; //Enable PWM
}
Example #8
0
void initialize_pwm(void){
    PTCON2bits.PCLKDIV = 0b010; //PWM input clock prescaled by 1:4
    //Period = 80 MHz / (PTPER * Prescaler)
    //Period = 80 MHz / (20kHz * 4) = 1000
    PTPER = 1000;
    IOCON1bits.PMOD = 00; //Set PWM to Complementary Mode
    IOCON2bits.PMOD = 00; //Set PWM to Complementary Mode
    IOCON3bits.PMOD = 00; //Set PWM to Complementary Mode

    DTR1 = DTR2 = DTR3 = 10;
    ALTDTR1 = ALTDTR2 = ALTDTR3 = 10;

    IOCON1bits.PENH = 1;
    IOCON1bits.PENL = 1;
    IOCON2bits.PENH = 1;
    IOCON2bits.PENL = 1;
    IOCON3bits.PENH = 1;
    IOCON3bits.PENL = 1;

    IOCON1bits.POLH = 1;
    IOCON2bits.POLH = 1;
    IOCON3bits.POLH = 1;
    IOCON1bits.POLL = 0;
    IOCON2bits.POLL = 0;
    IOCON3bits.POLL = 0;

    PWMCON1bits.MDCS = 1; //MDC register provides duty cycle information
    PWMCON2bits.MDCS = 1;
    PWMCON3bits.MDCS = 1;

    MDC = 100; // Sets master duty cycle at 10%

    commutate(0);

    PTCONbits.PTEN = 1;
}
Example #9
0
void commutate_state(comm_state_t n_state) {
    state = n_state;
    commutate();
}