AM32电调学习解读三:过零点判断

最近在学习AM32电调的2.18版本的源码,我用的硬件是AT32F421,整理了部分流程处理,内容的颗粒度是按自己的需要整理的,发出来给有需要的人参考。按自己的理解整理的,技术能力有限,可能理解有误,欢迎纠正。


注:lida2003博主是个大牛。写的无刷电调的理论和AM32相关知识点介绍的比较系统,介绍的很详细,有需要的同学可以去参考。我对电调这块是外行,只是刚入门学习。这里重点是代码理解的整理分析,他哪里写了很多原理性的知识。

https://blog.csdn.net/lida2003/category_12753961.html?spm=1001.2014.3001.5482
 

        这是第三篇,介绍AM32过零点判断处理。

1、过零点判断方法。

AM32的过零点判断使用的是比较器输出判断,下图是6步换相单片机6个管脚和比较器的输出。

A1和A2间相位是AH->BL,也就是AB相,此时比较器切换到C相和中性点。

比较器的波形从低电平切换到高电平的点就是过零点。AM32判断过零点的方法是:读比较器输出连续ilter_level次都是符合预期的值,则认为是过零点。

其中filter_level的值是在main函数中根据平均换相时间计算的

                //过零点门限filter_level计算:
                if (zero_crosses < 100 && commutation_interval > 500)
                {
                    filter_level        = 12;
                }
                else 
                {
                    filter_level        = map(average_interval, 100, 500, 3, 12);
                }

                if (commutation_interval < 50)
                {
                    filter_level        = 2;
                }

2、无感驱动比较器中断函数ADC1_CMP_IRQHandler

void ADC1_CMP_IRQHandler(void)
{
	if ((INTERVAL_TIMER->cval) > ((average_interval >> 1)))//平均换相时间一半后才会出现过零点
	{
		EXINT->intsts		= EXTI_LINE;
		interruptRoutine();
	}
	else //这个else代码分支感觉没意义,我把代码屏蔽了还能正常运行
	{
		if (getCompOutputLevel() == rising)
		{
			EXINT->intsts		= EXTI_LINE;
		}
	}
}

3、无感驱动interruptRoutine函数

void interruptRoutine()
{
	if (average_interval > 125)
	{	//启动初期低油门转速突变是不可能的,直接忽略
		if ((INTERVAL_TIMER_COUNT < 125) && (duty_cycle < 600) && (zero_crosses < 500))
		{ // should be impossible, desync?exit anyway
			return;
		}
		//main函数卡死判断保护
		stuckcounter++; 							// stuck at 100 interrupts before the main loop happens

		// again.
		if (stuckcounter > 100)
		{
			maskPhaseInterrupts();
			zero_crosses		= 0;
			return;
		}
	}
	//连续读取比较器输出符合预期filter_level次则判断为过零点
	for (int i = 0; i < filter_level; i++)
	{
#if defined(MCU_F031)					|| defined(MCU_G031)

		if (((current_GPIO_PORT->IDR & current_GPIO_PIN) == ! (rising)))
		{
#else

			if (getCompOutputLevel() == rising)
			{
#endif

				return;//连续读取正确次数不符合预期,不是过零点,跳过
			}
		}
		__disable_irq();
		maskPhaseInterrupts();		//关闭比较器中断
		lastzctime			= thiszctime;		
		thiszctime			= INTERVAL_TIMER_COUNT;  //更新本次换相时间
		SET_INTERVAL_TIMER_COUNT(0);				//换相时间计数器清零
		SET_AND_ENABLE_COM_INT(waitTime + 1);		// enable COM_TIMER interrupt 设置换相定时器等待时间并且使能定时器
		__enable_irq();	
	}

4、启动阶段过零点判断getBemfState函数

AM32 有两种启动方式,正弦启动、同步驱动启动。正弦启动阶段不需要过零点判断,同步驱动阶段需要过零点判断,过零点判断使用getBemfState函数

void getBemfState()
{
	uint8_t 		current_state = 0;

#if defined(MCU_F031)				|| defined(MCU_G031)

	if (step == 1 || step == 4)
	{
		current_state		= PHASE_C_EXTI_PORT->IDR & PHASE_C_EXTI_PIN;
	}

	if (step == 2 || step == 5)
	{ //		in phase two or 5 read from phase A Pf1
		current_state		= PHASE_A_EXTI_PORT->IDR & PHASE_A_EXTI_PIN;
	}

	if (step == 3 || step == 6)
	{ // phase B pf0
		current_state		= PHASE_B_EXTI_PORT->IDR & PHASE_B_EXTI_PIN;
	}

#else

	current_state		= !getCompOutputLevel();	// polarity reversed //读取比较器的值
#endif

	if (rising)
	{
		if (current_state)
		{
			bemfcounter++;   //比较器输出符合预期
		}
		else 
		{
			bad_count++;	//比较器读数不符合预期

			if (bad_count > bad_count_threshold)  //比较器读数不符合预期数累计大于门限值,则bemfcounter清零
			{
				bemfcounter 		= 0;
			}
		}
	}
	else 
	{
		if (!current_state)
		{
			bemfcounter++;
		}
		else 
		{
			bad_count++;

			if (bad_count > bad_count_threshold)
			{
				bemfcounter 		= 0;
			}
		}
	}
}

5、启动阶段过零点判断处理

启动阶段过零点和无感驱动阶段的过零点判断规则不一样,是定时50us调用一次

			if (old_routine && running)//在tenKhzRoutine函数中50us定时调用
			{
				//				send_LED_RGB(255, 0, 0);
				maskPhaseInterrupts();//启动阶段不使用比较器中断判断过零点,所以需要禁用比较器中断
				getBemfState();		//读取比较器输出计算bemfcounter

				if (!zcfound)
				{
					if (rising)
					{
						if (bemfcounter > min_bemf_counts_up) //bemfcounter满足门限,认为是过零点
						{
							zcfound 			= 1;	//找到过零点了,可以换相了
							zcfoundroutine();			//换相操作
						}
					}
					else 
					{
						if (bemfcounter > min_bemf_counts_down)//bemfcounter满足门限,认为是过零点
						{
							zcfound 			= 1;//找到过零点了,可以换相了
							zcfoundroutine();       //换相操作
						}
					}
				}
			}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hyhsandy1803

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值