lc115647 发表于 2025-8-15 21:28

无刷电机控制(三)如何通过HALL传感器获取电机速度

本帖最后由 lc115647 于 2025-8-15 21:52 编辑

<h2>一、霍尔传感器与电机转动的本质关系</h2>
<ol>
<li>3个霍尔元件呈120°电角度分布(下图可看出相位差120°),检测转子磁极位置</li>
<li>电机每旋转60°电角度,霍尔组合状态变化一次</li>
<li>完整电周期(360°电角度)产生6次状态变化</li>
</ol>
<p>给出了三个传感器的输出和每相的相应反电动势( BEMF)电压波形。</p>
<p><img src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml2404\wps2.jpg" alt="" /><br />
<img src="data/attachment/forum/202508/15/214412p4aht423tg4ed362.png" alt="1.png" title="1.png" /></p>
<h2>二、速度计算公式的完整推导</h2>
<p>设:</p>
<p>l Δt:两次霍尔变化的时间间隔(秒)</p>
<p>l P:电机极对数(磁极数/2)</p>
<p>l f_m:机械转速(转/秒)</p>
<p>推导过程:</p>
<p>每个Δt对应60°电角度</p>
<p>l 完整电周期(360°)时间:T_e = 6 × Δt</p>
<p>l 机械转速:f_m = 1/(P × T_e) = 1/(P × 6 × Δt)</p>
<p>l RPM(转/分):RPM = 60 × f_m = 60/(6PΔt) = 10/(PΔt)</p>
<h2>三、软件实现</h2>
<p>1、定时器初始化,配置为输入捕获模式</p>
<pre><code>void Drv_Hall_Init(u32 arr, u16 psc)
{


    TMR_TimeBase_T   TIM_TimeBaseStructure;
    TMR_ICConfig_T   TIM_ICInitStructure;

    TMR_Reset(TMR2);
    TMR_ConfigTimeBaseStruct(&amp;TIM_TimeBaseStructure);

    /* Sets the value of the automatic reload register Period for the next update event load activity
   * Set the Prescaler value used as the divisor of the TIMx clock frequency
   * Set clock split :TDTS = TIM_CKD_DIV1
   * Up counting mode
   */
    TIM_TimeBaseStructure.period      = arr;
    TIM_TimeBaseStructure.div   = psc;
    TIM_TimeBaseStructure.clockDivision = TMR_CKD_DIV1;
    TIM_TimeBaseStructure.counterMode   = TMR_COUNTER_MODE_UP;
    TIM_TimeBaseStructure.repetitionCounter = 0;
    TMR_ConfigTimeBase(TMR2, &amp;TIM_TimeBaseStructure);

    /**
   * Initialize TIM2 input capture parameters
   * CC1S=01 selects the input terminal IC1 to be mapped to TI1
   * Set to double edge capture
   * Map to TI1
   * Configure input frequency division, no frequency division
   * Configure input filter IC1F to 8
   */
    TIM_ICInitStructure.channel   = TMR_CHANNEL_1;
    TIM_ICInitStructure.ICpolarity= TMR_IC_POLARITY_BOTHEDGE;
    TIM_ICInitStructure.ICselection = TMR_IC_SELECTION_DIRECT_TI;
    TIM_ICInitStructure.ICprescaler = TMR_ICPSC_DIV1;
    TIM_ICInitStructure.ICfilter    = 0x0f;
    TMR_ICConfig(TMR2, &amp;TIM_ICInitStructure);

    /** Enable the Hall sensor interface of TIM2 */
    TMR_EnableHallSensor(TMR2);

    /** Input trigger source selection TI1 Edge Detector */
    TMR_SelectInputTrigger(TMR2, TMR_TS_TI1F_ED);

    /** Select from mode to reset mode */
    TMR_SelectSlaveMode(TMR2, TMR_SLAVEMODE_RESET);

    TMR_EnableMasterSlaveMode(TMR2);

    /** Allow interrupts to be triggered    */
    TMR_EnableInterrupt(TMR2, TMR_INT_UPDATE);
    TMR_EnableInterrupt(TMR2, TMR_INT_CH1);
    TMR_ClearIntFlag(TMR2, TMR_INT_FLAG_UPDATE);
    TMR_ClearIntFlag(TMR2, TMR_INT_FLAG_CH1);
    TMR_ICConfigStructInit(&amp;TIM_ICInitStructure);

//    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
//    NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
//    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//    NVIC_Init(&amp;NVIC_InitStructure);

    TMR_Enable(TMR2);
}
</code></pre>
<p>2、定时器输入捕获中断,获取时间差,计算速度</p>
<pre><code>void TMR2_IRQHandler(void)
{
static uint8_t i = 0;
uint8_t j = 0;

if(TMR_ReadIntFlag(TMR2, TMR_INT_FLAG_CH1) != RESET)
{
    i++;
    if(i &gt;= 6)
    {
      i = 0;
    }
    /*Hall change time capture*/
    Motor_1st.HALL.HallTime = TMR2-&gt;CC1;
    /*Read HALL value*/
    ReadHallValue = HALL_JudgeState();
    Motor_1st.HALL.RunHallValue = ReadHallValue;

    Motor_1st.HALL.HallTimeSum = 0;
    for(j=0;j&lt;6;j++)
    {
      Motor_1st.HALL.HallTimeSum += Motor_1st.HALL.HallTime;
    }
    /*Motor speed calculation*/
    Motor_1st.HALL.SpeedTemp = SPEEDX/Motor_1st.HALL.HallTimeSum;

    if(SpeedFdk.Out &gt;= 200)
    {
      if(Motor_1st.BLDC.RPValue.s16Act &lt; 100)
      {
      PWMH_OFF_PWML_OFF
      }
      else
      {
      MotorDrive(ReadHallValue);
      }
    }

    TIMFlag.HallDelay = 0;

    TMR_ClearIntFlag(TMR2, TMR_INT_FLAG_CH1);
}

if(TMR_ReadIntFlag(TMR2, TMR_INT_FLAG_UPDATE) != RESET)
{
    TIMFlag.HallDelay++;
    if(TIMFlag.HallDelay &gt;= 10)
    {
      TIMFlag.HallDelay = 0;
      Motor_1st.HALL.SpeedTemp = 0;
      SpeedFdk.Out = 0;
      MovingAvgInit(&amp;SpeedFdk);
    }
    TMR_ClearIntFlag(TMR2,TMR_INT_FLAG_UPDATE);
}
}
</code></pre>
<h2>四、总结</h2>
<p>通过定时器输出捕获,获取每次HALL状态时间差,从而计算出电机的速度,只可简单实现电机运行功能。实际应用中任存在一些问题,比如电机霍尔角度安装本身就会存在偏差,导致实际的角度并不是60度电角度;同时电机负载突变也会导致某段时间速度波动大,导致速度估算出现错误。</p>
页: [1]
查看完整版本: 无刷电机控制(三)如何通过HALL传感器获取电机速度