使用Proteus仿真STM32步进电机控制
1.步进电机的简介
步进电机(Stepper Motor)是一种电磁执行元件,它能够将电脉冲信号转换为角位移或线位移。步进电机通过接收一系列电脉冲来控制其转动的步数,每接收一个脉冲,电机转动一个步距角(Step Angle)。步进电机的工作原理是利用其内部的电磁线圈产生的磁场,与转子的永磁体相互作用,从而实现精确的步进转动。
2.步进电机的特点
-
精确控制:步进电机能够精确地控制其转动的角度,这使得它在需要精确定位的场合非常有用。
-
无需传感器:步进电机通常不需要位置反馈传感器,因为它的转动是直接由输入的脉冲序列控制的。
-
低速高扭矩:在低速运行时,步进电机可以提供较高的扭矩,适合于启动和精确控制。
-
控制简单:步进电机的控制相对简单,可以通过简单的脉冲和方向信号进行操作。
-
响应快速:步进电机可以快速响应控制信号,实现快速启动和停止。
-
使用寿命长:由于步进电机的转动不依赖于机械接触,因此它的使用寿命相对较长。
-
可变步距角:通过改变接收到的脉冲数量,步进电机可以实现不同的步距角,从而适应不同的应用需求。
3.步进电机的仿真
步进电机以及其驱动在proteus中的名字
(步进电机:MOTOR-STEPPER 驱动名字:ULN2003A)
四相步进电机有单四拍(A-B-C-D)和双四拍(AB-BC-CD-DA)和八拍(A-AB-B-BC-C-CD-D-DA)这三种工作方式。第一种工作方式扭矩小,功耗小,但震动大。第二种工作方式扭矩较大,功耗也大,震动小。第三种工作方式步距角小,输出更平滑,推荐采用这种方式(但这个在仿真中是无法精确的控制的,因为你并不知道仿真的齿轮比,无法精确的测出)。所以我们采用直接控制的方式来达到一个特殊的角度。
3.步进电机的仿真整体框架
4.cubemx的相关配置
第一种方法)4个引脚配置成上拉高速输出模式(我用了B1,B2,B3,B4)
第二种方法)直接写代码配置IO口
//可直接使用这个函数进行初始化,不需要在cubemx配置了
void bujin_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOB_CLK_ENABLE(); //开启GPIOB时钟
GPIO_Initure.Pin=GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4;
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOB,&GPIO_Initure);
}
5.相关代码和一些解释(仿真写法)
首先是一些相位的测定:根据测的数据 A相在45度 B相在-45度 C相在135度 D相在-135度
转的角度为90或者-90时=两相位之和除以2
+-45度可以直接根据一相得出
180度与0度相同(两相位之和除以2)
void control_motor(int angle)
{
if(angle==90)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,1);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,1);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
else if(angle==45)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,1);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
else if(angle==-90)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,1);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,1);//D
}
else if(angle==-45)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,1);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
else if(angle==0)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
else if(angle==180)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,1);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,1);//D
}
}
(仅供参考,不是很好)
/* USER CODE BEGIN 2 */
bujin_Init();//步进电机的初始化,保证在0位置
control_motor(180);
/* USER CODE END 2 */
6.最终效果
(其他角度也是类似)
7.实物的话建议采用四相八拍的模式
顺转:A-AB-B-BC-C-CD-D-DA
反转:将正转的顺序取反就行
//采用四相八拍(即八个节拍)
//顺转
void bujin_control(int count)
{
if(count==0)//A
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,1);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
if(count==1)//AB
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,1);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,1);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
if(count==2)//B
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,1);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
if(count==3)//BC
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,1);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,1);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
if(count==4)//C
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,1);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
if(count==5)//CD
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,1);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,1);//D
}
if(count==6)//D
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,1);//D
}
if(count==7)//DA
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,1);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,1);//D
}
}
//反转(将顺转反即可)
void bujin_control_fanzhuan(int count)
{
if(count==7)//A
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,1);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
if(count==6)//AB
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,1);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,1);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
if(count==5)//B
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,1);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
if(count==4)//BC
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,1);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,1);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
if(count==3)//C
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,1);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);//D
}
if(count==2)//CD
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,1);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,1);//D
}
if(count==1)//D
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,1);//D
}
if(count==0)//DA
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,1);//A
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);//B
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);//C
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,1);//D
}
}
void bujin_stop(void)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,0);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,0);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);
}
//控制电机正转还是反转某个角度
//direction方向,1为正转,0为反转
//angle角度,可为0-360具有实际意义
void bujin_control_angle(int direction, int angle)
{
u16 j,i;
if(direction == 1)
{
for(j=0;j<64*angle/45;j++)
{
for(i=0;i<8;i++)
{
bujin_control(i);
delay_ms(1);
}
}
bujin_stop();//停止
}
else
{
for(j=0;j<64*angle/45;j++)
{
for(i=0;i<8;i++)
{
bujin_control_fanzhuan(i);
delay_ms(1);
}
}
bujin_stop();//停止
}
}
仿真和实物实在是相差大,所有仿真用了仿真的方法,四相八拍在仿真中难以实现控制固定的角度。
作者:KSD星辰