【AM32 电调学习】

AM32 电调学习–换相

#define INTERVAL_TIMER TIM2   ; 过零时间测量
#define TEN_KHZ_TIMER TIM6  ;tenKhzRoutine  frq=1M  load=1M/20k
#define UTILITY_TIMER TIM17
#define COM_TIMER TIM14  //PeriodElapsedCallback  过零后等待时间中断

3. 换相

(0)换相过程简述

  • 开始启动时:old_routine设置,tenKhzRoutine()任务中检测反相电动势,获取到零点后,执行zcfoundroutine().标志zcfound守护到换相结束。
  • zcfoundroutine中死等3/4 pwm换相,标志zcfound守护。zero_crosses++,大于30次后。清除old_routine,随后的换相通过规定动作中断进行。
  • ADC1_COMP_IRQHandler中运行interruptRoutine().
  • interruptRoutine: 过零点去抖,将换相时计算的 换相等待时间设置TIM14.
  • TIM14_IRQHandler中断换相时间到,运行PeriodElapsedCallback().
  • PeriodElapsedCallback:换相,计算下次的换相等待时间waitTime。

(1)六步换相定义

  • step1 2 3 4 5 6
  •     ab cb ca  ba bc ac 
    

(2)过零点

a. 比较器设置
void changeCompInput()
{
    if (step == 1 || step == 4) { // c floating    ba xx  xx  ab xx xx  
#ifdef N_VARIANT
        current_EXTI_LINE = PHASE_C_EXTI_LINE;
        active_COMP = PHASE_C_COMP_NUMBER;
#endif
        LL_COMP_ConfigInputs(active_COMP, PHASE_C_COMP, LL_COMP_INPUT_PLUS_IO3);
    }

    if (step == 2 || step == 5) { // a floating  ba bc xx ab cb xx
#ifdef N_VARIANT
        current_EXTI_LINE = PHASE_A_EXTI_LINE;
        active_COMP = PHASE_A_COMP_NUMBER;
#endif
        LL_COMP_ConfigInputs(active_COMP, PHASE_A_COMP, LL_COMP_INPUT_PLUS_IO3);
    }

    if (step == 3 || step == 6) { // b floating ba bc ac ab cb ca 
#ifdef N_VARIANT
        current_EXTI_LINE = PHASE_B_EXTI_LINE;
        active_COMP = PHASE_B_COMP_NUMBER;
#endif
        LL_COMP_ConfigInputs(active_COMP, PHASE_B_COMP, LL_COMP_INPUT_PLUS_IO3);
    }
    if (rising) {
        LL_EXTI_DisableRisingTrig_0_31(LL_EXTI_LINE_18);
        LL_EXTI_DisableRisingTrig_0_31(LL_EXTI_LINE_17);
        LL_EXTI_EnableFallingTrig_0_31(current_EXTI_LINE);
    } else { // falling bemf
        LL_EXTI_EnableRisingTrig_0_31(current_EXTI_LINE);
        LL_EXTI_DisableFallingTrig_0_31(LL_EXTI_LINE_17);
        LL_EXTI_DisableFallingTrig_0_31(LL_EXTI_LINE_18);
    }
}
b. 过零点后阻塞换相
void zcfoundroutine()
{ // only used in polling mode, blocking routine.
    thiszctime = INTERVAL_TIMER_COUNT;
    SET_INTERVAL_TIMER_COUNT(0);
    commutation_interval = (thiszctime + (3 * commutation_interval)) / 4;
    advance = commutation_interval / advancedivisor;
    waitTime = commutation_interval / 2 - advance;
    while ((INTERVAL_TIMER_COUNT) < (waitTime)) {
        if (zero_crosses < 10) {
            break;
        }
    }
#ifdef MCU_GDE23
    TIMER_CAR(COM_TIMER) = waitTime;
#endif
#ifdef MCU_F051
    COM_TIMER->ARR = waitTime;
#endif
    commutate();
    bemfcounter = 0;
    bad_count = 0;

    zero_crosses++;
    if (stall_protection || RC_CAR_REVERSE) {
        if (zero_crosses >= 20 && commutation_interval <= 2000) {
            old_routine = 0;
            enableCompInterrupts(); // enable interrupt
        }
    } else {
        if (zero_crosses > 30) {
            old_routine = 0;
            enableCompInterrupts(); // enable interrupt
        }
    }
}
c.过零点中断处理

void interruptRoutine()
{
    if (average_interval > 125) {
        if ((INTERVAL_TIMER_COUNT < 125) && (duty_cycle < 600) && (zero_crosses < 500)) { // should be impossible, desync?exit anyway
            return;
        }
        if (INTERVAL_TIMER_COUNT < (commutation_interval >> 1)) {
            return;
        }
        stuckcounter++; // stuck at 100 interrupts before the main loop happens
                        // again.
        if (stuckcounter > 100) {
            maskPhaseInterrupts();
            zero_crosses = 0;
            return;
        }
    }
    thiszctime = INTERVAL_TIMER_COUNT;
    if (rising) {
        for (int i = 0; i < filter_level; i++) {
#ifdef MCU_F031
            if ((current_GPIO_PORT->IDR & current_GPIO_PIN) == (uint32_t)GPIO_PIN_RESET) {
#else
            if (getCompOutputLevel()) {
#endif
                return;
            }
        }
    } else {
        for (int i = 0; i < filter_level; i++) {
#ifdef MCU_F031
            if ((current_GPIO_PORT->IDR & current_GPIO_PIN) != (uint32_t)GPIO_PIN_RESET) {
#else
            if (!getCompOutputLevel()) {
#endif
                return;
            }
        }
    }
    maskPhaseInterrupts();
    __disable_irq();
    if (INTERVAL_TIMER_COUNT > thiszctime) {
        SET_INTERVAL_TIMER_COUNT(INTERVAL_TIMER_COUNT - thiszctime);
    } else {
        SET_INTERVAL_TIMER_COUNT(0);
    }
    waitTime = waitTime >> fast_accel;
    SET_AND_ENABLE_COM_INT(waitTime); // enable COM_TIMER interrupt
    __enable_irq();
}
/**
 * @brief This function handles ADC1, COMP1 and COMP2 interrupts (COMP
 * interrupts through EXTI lines 17 and 18).
 */
void ADC1_COMP_IRQHandler(void)
{
    if (LL_EXTI_IsActiveFallingFlag_0_31(LL_EXTI_LINE_18)) {
        LL_EXTI_ClearFallingFlag_0_31(LL_EXTI_LINE_18);
        interruptRoutine();

        return;
    }

    if (LL_EXTI_IsActiveRisingFlag_0_31(LL_EXTI_LINE_18)) {
        LL_EXTI_ClearRisingFlag_0_31(LL_EXTI_LINE_18);
        interruptRoutine();
        return;
    }
    if (LL_EXTI_IsActiveFallingFlag_0_31(LL_EXTI_LINE_17)) {
        LL_EXTI_ClearFallingFlag_0_31(LL_EXTI_LINE_17);
        interruptRoutine();
        return;
    }
    if (LL_EXTI_IsActiveRisingFlag_0_31(LL_EXTI_LINE_17)) {
        LL_EXTI_ClearRisingFlag_0_31(LL_EXTI_LINE_17);
        interruptRoutine();
        return;
    }
}

(d) 换相等待中断(tim14)
void PeriodElapsedCallback()
{
    DISABLE_COM_TIMER_INT(); // disable interrupt
    commutate();
    commutation_interval = ((3 * commutation_interval) + thiszctime) >> 2;
    advance = (commutation_interval >> 3) * advance_level; // 60 divde 8 7.5 degree increments
    waitTime = (commutation_interval >> 1) - advance;
    if (!old_routine) {
        enableCompInterrupts(); // enable comp interrupt
    }
    if (zero_crosses < 10000) {
        zero_crosses++;
    }
}

(3)换相过程

(a) 换相动作:
  • 获取了每个过零点的时间 commutation_intervals[step - 1]= thiszctime,以0.5us为单位
void commutate()
{
    if (forward == 1) {
        step++;
        if (step > 6) {
            step = 1;
            desync_check = 1;
        }
        rising = step % 2;
    } else {
        step--;
        if (step < 1) {
            step = 6;
            desync_check = 1;
        }
        rising = !(step % 2);
    }
    __disable_irq(); // don't let dshot interrupt
    if (!prop_brake_active) {
        comStep(step);
    }
    __enable_irq();
    changeCompInput();
    if (stall_protection || RC_CAR_REVERSE) {
        if (average_interval > 2000) {
            old_routine = 1;
        }
    }
    bemfcounter = 0;
    zcfound = 0;
    commutation_intervals[step - 1] = thiszctime; // just used to calulate average
}

void comStep(int newStep)
{
    switch (newStep) {
    case 1: // A-B
        phaseCFLOAT();
        phaseBLOW();
        phaseAPWM();
        break;

    case 2: // C-B
        phaseAFLOAT();
        phaseBLOW();
        phaseCPWM();
        break;

    case 3: // C-A
        phaseBFLOAT();
        phaseALOW();
        phaseCPWM();
        break;

    case 4: // B-A
        phaseCFLOAT();
        phaseALOW();
        phaseBPWM();
        break;

    case 5: // B-C
        phaseAFLOAT();
        phaseCLOW();
        phaseBPWM();
        break;

    case 6: // A-C
        phaseBFLOAT();
        phaseCLOW();
        phaseAPWM();
        break;
    }
}
(b) 换相后旋转参数获取(6次换相时间,05us为间隔)
  • commutation_intervals[x]以0.5us为单位
  • e_com_time 以1us为单位
  • 控制输入值duty_cycle ,以us为单位?
  • input值的范围 47–2047,map 到 deadtime–max_arr
e_com_time = ((commutation_intervals[0] + commutation_intervals[1] + commutation_intervals[2] + commutation_intervals[3] + commutation_intervals[4] + commutation_intervals[5]) + 4) >> 1; // COMMUTATION INTERVAL IS 0.5US INCREMENTS

average_interval = e_com_time / 3;

duty_cycle = duty_cycle_setpoint;
            if (use_sin_start) {
                duty_cycle_setpoint = map(input, 137, 2047, minimum_duty_cycle, TIMER1_MAX_ARR);
            } else {
                duty_cycle_setpoint = map(input, 47, 2047, minimum_duty_cycle, TIMER1_MAX_ARR);
            }
uint16_t minimum_duty_cycle = DEAD_TIME;
#define DEAD_TIME 60
uint16_t TIMER1_MAX_ARR = TIM1_AUTORELOAD; // maximum auto reset register value
#define TIM1_AUTORELOAD 2667

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值