无刷电机控制(三)如何通过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(&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, &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, &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(&TIM_ICInitStructure);
// NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&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 >= 6)
{
i = 0;
}
/*Hall change time capture*/
Motor_1st.HALL.HallTime = TMR2->CC1;
/*Read HALL value*/
ReadHallValue = HALL_JudgeState();
Motor_1st.HALL.RunHallValue = ReadHallValue;
Motor_1st.HALL.HallTimeSum = 0;
for(j=0;j<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 >= 200)
{
if(Motor_1st.BLDC.RPValue.s16Act < 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 >= 10)
{
TIMFlag.HallDelay = 0;
Motor_1st.HALL.SpeedTemp = 0;
SpeedFdk.Out = 0;
MovingAvgInit(&SpeedFdk);
}
TMR_ClearIntFlag(TMR2,TMR_INT_FLAG_UPDATE);
}
}
</code></pre>
<h2>四、总结</h2>
<p>通过定时器输出捕获,获取每次HALL状态时间差,从而计算出电机的速度,只可简单实现电机运行功能。实际应用中任存在一些问题,比如电机霍尔角度安装本身就会存在偏差,导致实际的角度并不是60度电角度;同时电机负载突变也会导致某段时间速度波动大,导致速度估算出现错误。</p>
页:
[1]