转速公式
转速的计算我现在是通过一定时间内,霍尔信号的边沿数量来计算的。这里每隔50ms在滴答定时器中断服务函数里面计算一次。霍尔信号每变化一次,就产生一次霍尔触发中断。因为我的电机是2对极,所以在一圈内有12个霍尔状态,即电机转动一圈会触发12次中断。假设在50ms内,霍尔触发了 n 次中断,我们可以得到转速 x 的公式:
50ms内,
\[x=n/12 (rpms) \]则1ms内
\[x=n/12/50 (rpms) \]1s内
\[x=(n/12/50)*1000 (rps) \]1min内
\[x=(n/12/50)*1000*60=100n (rpm) \]根据这个式子就能计算出转速。
电机参数初始化
在头文件中声明电机参数结构体
typedef struct
{
int16_t MOTOR_POLE_NUM; //电机极对数
int16_t Speed_OPEN_LOOP; //开环电机转速
int16_t step_counter; //霍尔传感器脉冲数量,用于计算转速
uint32_t HallSpanTime; //霍尔两次状态之间时间
uint8_t HallGet; // 是否是hall触发中断
int32_t SpeedBck; //速度反馈值
}MOTOR_DEVICE;
宏定义
#define BLDC_POLE_NUM 2
对电机参数初始化
MOTOR_DEVICE bldc_dev; //电机参数结构体
void Motor_Init(void)
{
bldc_dev.MOTOR_POLE_NUM=BLDC_POLE_NUM; //极对数
bldc_dev.HallGet=0;
bldc_dev.HallSpanTime=0;
bldc_dev.SpeedBck=0;
bldc_dev.Speed_OPEN_LOOP=0;
bldc_dev.step_counter=0;
}
滴答定时器初始化
定时器初始化,每1ms中断一次
void SysTick_Init(void)
{
uint32_t prioritygroup = 0x00;
/* SystemFrequency / 1000 1ms中断一次
* SystemFrequency / 100000 10us中断一次
* SystemFrequency / 1000000 1us中断一次
*/
SysTick_Config(SystemCoreClock / 1000);
prioritygroup = NVIC_GetPriorityGrouping();
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(prioritygroup, 1, 0));
}
滴答定时器中断服务函数
编写滴答定时器中断服务函数,每50ms计算一次转速
void SysTick_Handler(void)
{
static uint16_t time_count=0;
time_count++;
if(time_count>50) // 50ms计算一次
{
uint16_t temp;
temp=bldc_dev.step_counter*200/bldc_dev.MOTOR_POLE_NUM; //计算转速
printf("Speed_OPEN_LOOP=%d\r\n",temp); //打印转速 (RPM)到串口调试助手
time_count=0; //清零,重新计数
bldc_dev.step_counter=0;
}
}
霍尔触发中断服务函数
在霍尔中断服务函数中加入计步参数,测量50ms内霍尔传感器脉冲数量,用于计算转速
void HALL_TIM_IRQHANDLER(void)
{
if(TIM_GetITStatus(HALL_TIMx,TIM_IT_Trigger)!=RESET)
{
HALL_TIMx_Callback(); //换相函数
bldc_dev.step_counter++; //计步
TIM_ClearITPendingBit (HALL_TIMx,TIM_IT_Trigger); //清除触发中断标志
}
}
测量转速
通过串口调试助手查看转速信息。
用的24V电机最高转速有33000rpm,这里在开环20%占空比下,有100rpm的波动。
后续将尝试另一种通过两个霍尔状态之间时间差计算转速的方式。