之前的电机成功地转了起来,但其噪音非常大,因为之前尝试过自带细分功能的优质驱动器,关于其具体原理我没有系统学习,在使用L298N驱动电机时就感觉到有些吃力,于是在这里补一下步进电机微步细分原理的功课,以及用另一种控制电机的方法----定时器输出比较
微步细分原理
在我之前提到过的步进电机的工作原理中,我们知道电机定子的转动是通过不同线圈产生的磁场进而驱动电机转动一定步距角来实现的,但是市面上的电机步距角都是出厂时就已经配置好了的,一般为0.9°&1.8°,很明显这种过大的角度是很难满足用户的需求的,因此便有了细分
驱动器细分
以两相四线电机为例,驱动器一般的原理都是通过改变两相的电流差来对磁场的大小进行微操,进而精准地控制转子转过对应的角度,打个比方,如果我的步距角为1.8°,我设置为4细分,则实际上当电机收到一个脉冲时对应转过的角度应该为1.8°/4 = 0.45°
软件细分
如果出现了不带细分功能的驱动器(可能不是专门给步进电机使用的),就需要我们用到软件细分,具体的原理和硬件驱动类似,也是改变两相的电流大小进而产生不同的磁场控制转子转动,这个时候就需要用到定时器,结合上一篇提到的电机单步工作的代码,我们只需要将A-A+B-B+分别接到定时器的两个PWM通道分出四条线接到电机线组上即可,再通过控制输出的占空比和通道极性来实现传输到线圈上的极性和电流大小,具体操作可以参考这篇文章(14条消息) 用PWM实现仪表步进电机的微步细分驱动_张联利的博客-CSDN博客_微步细分
输出比较驱动
这个原理我之前提到了一下下,其实控制电机最基本的就是两点:方向&速度,前者翻转引脚实现,后者则是通过控制发送脉冲数的频率来实现,具体原理为:在输出比较模式下,重装载值ARR已经设定好了,在一个ARR周期中,计时器每记一次比较值CCR,TIM就通过对应的通道发送一次脉冲,举例来说,设定ARR = 1000,CCR = 250,则在一个ARR周期中定时器输出比较通道会发出1000/250 = 4个脉冲,如果此时我将CCR减50,那么定时器能发出的脉冲则变为1000/200 = 5个,电机速度就变快了,因为周期时长不变,脉冲数增多,代表脉冲发送频率增大,电机速度自然增大,下面我来说说如何用代码实现
工程搭建
代码实现
uint8 ccr; //设置初始比较值
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) //定时器比较回调函数
{
if(htim->Instance == TIM3)
{
__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,ccr);
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_2); //开启输出比较中断
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
Key = Key_on(); //检测按键
switch (Key) //对应模式
{
case 1:dir = !dir;Key = 0;break; //翻转方向
case 2:
ccr += 50;
Key = 0;break; //电机减速
}
Motor_Start(dir); //启动电机
}
/* USER CODE END 3 */
}
验证实现
结合细分操作,不出意外电机已经可以稳定的转起来了