电机矢量控制(霍尔位置传感器)

1. 矢量控制常用的位置传感器
在电机磁场定向控制算法中,电机转子位置的获取是必要的,在高精度应用场合,通常使用编码器、旋转变压器进行位置反馈,这种方式需要较高的成本。对于一般的应用场合,如电动自行车等,通常可以使用低分辨率的Hall位置传感器,如果是使用于家用电器这种对成本十分敏感的场合,甚至可以使用无位置传感器算法(状态观测器)对位置信号进行提取。这里着重讨论通过Hall传感器的方式提取电机转子电角度。
2.Hall传感器的原理
通常,霍尔位置传感器在电机中按120度电角度位置放置,在这种放置下,电机旋转一个电周期会出现6种不同的状态,每种状态维持60度电角度。下图显示了霍尔信号与三相反电动势的关系,也是测试电角度补偿角的依据,图中所示的电角度偏移量为-90度电角度,电机角度增加的方向定义为电机旋转时反电势A相超前B相,B相超前C相的方向(注意:后面程序都是q轴与alpha轴夹角)。
同步电角度

3.STM32的Hall接口
STM32内部的定时器外设自带Hall传感器接口,可对三路Hall信号进行异或运算,只要有一路Hall信号产生变化,定时器可以及时捕获,通过软件更新电角度并计算当前电机的速度,具体的程序实现请看下节。
4.程序实现
(1)该程序的计数周期为10us,重载寄存器设定为0xFFFF,若产生更新中断(655ms),则认为电机的速度为零;
(2)实际应用中应该对速度进行滤波,本程序未对速度进行滤波,如果需要滤波,您可以自行实现。
(3)本程序和STM32电机库使用的电角度一致,即认为A相反电势最高点为电角度零点(q轴与alpha轴的夹角为零),您可以参阅STM32的UM0492用户手册中文版进行理解。
(4)有关Hall电角度的偏移量的测量请参考Hall同步电角度测量,请注意正方向为反电势A相超前B相,B相超前C相的方向,如果有不理解,可以留言。
(5)其中也有不少参考了STM32的电机库,如有不明白的地方,可以看UM0492用户手册,里面讲解比较详细。
以下是STM32定时器3的配置:

void TIM3_Init(void)
{
	RCC->APB1ENR |= 1<<1;
	RCC->APB2ENR |= 1<<0;
	RCC->APB2ENR |= 1<<4;
	AFIO->MAPR |= 3<<10;
	GPIOC->CRL &= 0x00FFFFFF;
	GPIOC->CRL |= 0x44000000;
	GPIOC->CRH &= 0xFFFFFFF0;
	GPIOC->CRH |= 0x00000004;
	TIM3->PSC = 719;
	TIM3->ARR = 0xFFFF;
	TIM3->CNT = 0;
	TIM3->CR1 = (0<<8)|(0<<7)|(0<<5)|(0<<4)|(0<<3)|(1<<2)|(0<<1)|(0<<0);
	TIM3->CR2 = (1<<7);
	TIM3->SMCR = (4<<0)|(4<<4);
	TIM3->CCMR1 = 0x0003;
	TIM3->CCER = 0x0001;
	TIM3->SR = 0;
	TIM3->DIER = (1<<0)|(1<<1);
	NVIC->ISER[TIM3_IRQn/32] |= 1<<(TIM3_IRQn%32);
	NVIC->IP[TIM3_IRQn] = 5<<4;
	TIM3->CR1 |= 0x01;
}

以下是STM32定时器3中断函数:

static void Hall_IRQHandler(AllVar_t *pA)
{
	uint8_t HallState_Last;
	int16_t Abs_Speed01Hz;
	HallVar_t *pH = &pA->HallVar;
	if( TIM3->SR & (1<<0) )
	{
		TIM3->SR &= ~(1<<0);
		if(pA->MState == MC_RUN)
		{
			pA->EState = STALLERROR; 
		}
		pH->EAngleDpp = 0;
		pH->IsFirstCap = 1;
		pH->Speed01Hz = 0;
	}
	else if( TIM3->SR & (1<<1) )
	{
		TIM3->SR &= ~(1<<1);
		HallState_Last = pH->HallState;
		pH->HallState = GetHallState();
		switch(pH->HallState)
		{
			case 5:
				if(HallState_Last == 4)
				{
					pH->RotorDir = 1;
					pH->EAngle = (int16_t)HALL_OFFSET;//0 degree
				}
				else if(HallState_Last == 1)
				{
					pH->RotorDir = -1;
					pH->EAngle = (int16_t)(HALL_OFFSET + (int16_t)(65536/6)); // 60 degree
				}
				else
				{
					pA->EState = FBKERROR;
				}
			break;
				
			case 1:
				if(HallState_Last == 5)
				{
					pH->RotorDir = 1;
					pH->EAngle = (int16_t)(HALL_OFFSET + (int16_t)(65536/6));
				}
				else if(HallState_Last == 3)
				{
					pH->RotorDir = -1;
					pH->EAngle = (int16_t)(HALL_OFFSET + (int16_t)(65536/3));
				}
				else
				{
					pA->EState = FBKERROR;
				}			
			break;
				
			case 3:
				if(HallState_Last == 1)
				{
					pH->RotorDir = 1;
					pH->EAngle = (int16_t)(HALL_OFFSET + (int16_t)(65536/3));
				}
				else if(HallState_Last == 2)
				{
					pH->RotorDir = -1;
					pH->EAngle = (int16_t)(HALL_OFFSET + (int16_t)(65536/3) + (int16_t)(65536/6));
				}
				else
				{
					pA->EState = FBKERROR;
				}					
			break;
				
			case 2:
				if(HallState_Last == 3)
				{
					pH->RotorDir = 1;
					pH->EAngle = (int16_t)(HALL_OFFSET + (int16_t)(65536/3) + (int16_t)(65536/6));
				}
				else if(HallState_Last == 6)
				{
					pH->RotorDir = -1;
					pH->EAngle = (int16_t)(HALL_OFFSET - (int16_t)(65536/3));
				}
				else
				{
					pA->EState = FBKERROR;
				}				
			break;
				
			case 6:
				if(HallState_Last == 2)
				{
					pH->RotorDir = 1;
					pH->EAngle = (int16_t)(HALL_OFFSET - (int16_t)(65536/3));
				}
				else if(HallState_Last == 4)
				{
					pH->RotorDir = -1;
					pH->EAngle = (int16_t)(HALL_OFFSET - (int16_t)(65536/6));
				}
				else
				{
					pA->EState = FBKERROR;
				}				
			break;
				
			case 4:
				if(HallState_Last == 6)
				{
					pH->RotorDir = 1;
					pH->EAngle = (int16_t)(HALL_OFFSET - (int16_t)(65536/6));
				}
				else if(HallState_Last == 5)
				{
					pH->RotorDir = -1;
					pH->EAngle = (int16_t)HALL_OFFSET;
				}
				else
				{
					pA->EState = FBKERROR;
				}				
				break;
				
				default:
					pA->EState = FBKERROR;				
				break;
			}
			if(pH->IsFirstCap == 1)
			{
				pH->EAngleDpp = 0;
				pH->IsFirstCap = 0;
			}
			else
			{
				pH->CapValue = TIM3->CCR1;
				pH->EAngleDpp = (int16_t)((uint32_t)72000000/(TIM3->PSC+1)/6*65536/pH->CapValue/PWM_FREQ);
				pH->EAngleDpp *= pH->RotorDir;
				pH->Speed01Hz = (int16_t)((int32_t)pH->EAngleDpp*PWM_FREQ*10/65536/POLEPAIR_NUM);
				if(pH->Speed01Hz>0)   
				{
					Abs_Speed01Hz = pH->Speed01Hz;
				}
				else
				{
					Abs_Speed01Hz = -pH->Speed01Hz;
				}
				if( Abs_Speed01Hz > (int16_t)SPEED_MAX/6)
				{
					pA->EState = FBKERROR;			
				}
			}
	}
}

转载请注明出处
--------------------------------------------------------------END------------------------------------------------------------------------------------

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值