你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

教你让步进电机动起来

[复制链接]
gaosmile 发布时间:2020-9-29 22:37
步进电机特点:
  • 它是通过输入脉冲信号来进行控制的
  • 电机的总转动角度由输入脉冲数决定
  • 电机的转速由脉冲信号频率决定


步进电机主要用于一些有定位要求、进行精确控制的场合。特别适合要求运行平稳、低噪音、响应快、使用寿命长、高输出扭矩的应用场合。比如3D打印机、工业机器人等场景。

微信图片_20200929223406.gif
步进电机在工业机器人中的应用

步进电机相关概念:
  • 拍数
    完成一个磁场周期性变化所需脉冲数或导电状态用n表示,或指电机转过一个齿距角所需脉冲数,以四相电机为例,有四相四拍运行方式即AB-BC-CD-DA-AB,四相八拍运行方式即A-AB-B-BC-C-CD-D-DA-A。
  • 步距角
    控制系统每发一个步进脉冲信号,电机所转动的角度。现在市场上常规的二、四相混合式步进电机基本步距角都是1.8°。


相关问题:
问题:有一步进电机参数,如下:
[电压 12VDC  
相数 4  
减速比 1/64  
步距角 1.8° /64
驱动方式 四相八拍 ]
请问: 步距角1.8°/64 ,后面的 “/64”表示什么意思?此步进电机转一圈,要多少步?

答案:12VDC的步进电机,L298N的VS接12V直流电源。步进电机本身到电机轴之间是有一级齿轮减速的,64指减速比,即:电机本身的转子转64圈,输出的电机轴才转1圈。步距角1.8° /64表示,每走动64拍,转过角度为1.8度,转一圈共需要(360/1.8)*64=12800拍(步)


若是新手,不知道怎么设计电机驱动电路,可以直接购买电机驱动模块,市面上这种功能模块非常多,比如L298N电机驱动模块,只需要单片机6个IO外加一个电机供电电源即可驱动步进电机。

微信图片_20200929223410.png

L298N主要参数说明
  • 控制信号供电:直流5V;
  • 电机供电:直流3V~46V(建议使用36V以下)
  • 最大工作电流:2.5A
  • 额定功率:25W
  • 控制信号输入电压范围:

    • 低电平:-0.3V <= Vin <= 1.5V
    • 高电平:2.3V <= Vin <= Vss

  • 使能信号输入电压范围:

    • 低电平:-0.3V <= Vin <= 1.5V(控制信号无效)
    • 高电平:2.3V <= Vin <= Vss(控制信号有效)

  • L298N芯片的输入电压有两个:
    如果步进电机为5VDC供电,那么VSS和VS可以短接到一起;
    VSS和VS两个电源要共地;
    L298N使用的过程中,发热较大,最好添加散热片。


    • VSS:逻辑电压,提供逻辑器件的电源,允许4.5~7V,建议为5V。
    • VS:小于或等于46V,供给电机,和L298内部输出端的工作电源,根据电机的额定电压来接。

如果想自己设计电路实现电机的驱动,可以参考如下电路。

L298N原理图
微信图片_20200929223413.png

应用实例

驱动步进电机
驱动四线两相电机,四个状态为1、AB正电压;2、A-B正电压;3、A-B-正电压;4、AB-正电压。

程序中使能ENA和ENB之后,令StepMotor_OUT1~StepMotor_OUT4按四个状态变化,时序控制如下图所示,即可控制步进电机的方向:

微信图片_20200929223416.png

实现代码1. 驱动步进电机的引脚初始化

  1. void StepMotor_Init(void)
  2. {
  3.         GPIO_InitTypeDef  GPIO_InitStructure;
  4.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE);       //使能PB,PC端口时钟
  5.         
  6.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
  7.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  8.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  9.         GPIO_Init(GPIOC, &GPIO_InitStructure);
  10.         GPIO_SetBits(GPIOC,GPIO_Pin_6);
  11.         GPIO_SetBits(GPIOC,GPIO_Pin_7);
  12.         
  13.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
  14.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  15.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  16.         GPIO_Init(GPIOB, &GPIO_InitStructure);

  17.         L298D_1AA = 0;
  18.         L298D_2AA = 0;
  19.         L298D_3AA = 0;
  20.         L298D_4AA = 0;
  21.         L298D_12ENA = 0;
  22.         L298D_34ENA = 0;
  23. }
复制代码


2. 两相电机驱动代码,包括正转和反转

  1. void TwoPhaseMotor(unsigned char nInputData ,unsigned char nDirection)
  2. {
  3.         if(1 == nDirection)             //逆时针
  4.         {
  5.                 switch(nInputData)
  6.                 {
  7.                         case 1:
  8.                         {
  9.                                 L298D_1AA = 0;
  10.                                 L298D_2AA = 1;
  11.                                 L298D_3AA = 0;
  12.                                 L298D_4AA = 1;
  13.                         }
  14.                         break;
  15.                         case 2:
  16.                         {
  17.                                 L298D_1AA = 0;
  18.                                 L298D_2AA = 1;
  19.                                 L298D_3AA = 1;
  20.                                 L298D_4AA = 0;
  21.                         }
  22.                         break;
  23.                         case 3:
  24.                         {
  25.                                 L298D_1AA = 1;
  26.                                 L298D_2AA = 0;
  27.                                 L298D_3AA = 1;
  28.                                 L298D_4AA = 0;
  29.                         }
  30.                         break;
  31.                         case 4:
  32.                         {
  33.                                 L298D_1AA = 1;
  34.                                 L298D_2AA = 0;
  35.                                 L298D_3AA = 0;
  36.                                 L298D_4AA = 1;
  37.                         }
  38.                         break;
  39.                 }
  40.         }
  41.         else if(0 == nDirection)        //顺时针
  42.         {
  43.                 switch(nInputData)
  44.                 {
  45.                         case 1:
  46.                         {
  47.                                 L298D_1AA = 1;
  48.                                 L298D_2AA = 0;
  49.                                 L298D_3AA = 0;
  50.                                 L298D_4AA = 1;
  51.                         }
  52.                         break;
  53.                         case 2:
  54.                         {
  55.                                 L298D_1AA = 1;
  56.                                 L298D_2AA = 0;
  57.                                 L298D_3AA = 1;
  58.                                 L298D_4AA = 0;
  59.                         }
  60.                         break;
  61.                         case 3:
  62.                         {
  63.                                 L298D_1AA = 0;
  64.                                 L298D_2AA = 1;
  65.                                 L298D_3AA = 1;
  66.                                 L298D_4AA = 0;
  67.                         }
  68.                         break;
  69.                         case 4:
  70.                         {
  71.                                 L298D_1AA = 0;
  72.                                 L298D_2AA = 1;
  73.                                 L298D_3AA = 0;
  74.                                 L298D_4AA = 1;
  75.                         }
  76.                         break;
  77.                 }
  78.         }
  79. }
复制代码


上面函数调用一次,步进电机走一步,对上面函数进行封装,既得到走任意步,可控制方向的函数:

  1. void TwoPhaseMotorNCircle(int n,unsigned char direction)
  2. {
  3.     int i,j;
  4.         
  5.     L298D_12ENA = 1;    //只有转的时候使能,否则持续供电,芯片和电机过热。
  6.     L298D_34ENA = 1;
  7.    
  8.     for(i=0;i<n;i++)
  9.     {
  10.         for(j=1;j<=4;j++)
  11.         {
  12.             TwoPhaseMotor(j,direction);
  13.             delay_ms(2);
  14.         }
  15.     }
  16.    
  17.     L298D_12ENA = 0;
  18.     L298D_34ENA = 0;
  19. }
复制代码

3. 主函数中调用说明:
  • 硬件实现中串口2与ESP8266模块相连,使用cJSON解析收到的阿里云物联网的数据包;
  • 收到的{"owerSwitch":1),电机转动,{"owerSwitch":0},电机停止;
  • 收到电机转动指令之后,此程序让步进电机左转N圈之后,再右转N圈,如此反复,所以为了不影响程序对其他指令的响应,所以将控制步进电机转动的步进代码放到了定时器中执行,主程序中,只控制ENA和ENB的使能开关

JSON字符串解析参考之前的网文:Keil环境下STM32工程加入cJSON

主函数代码如下:

  1. int main(void)
  2. {
  3.         //解析payload数据包使用
  4.         cJSON *receive_json, *item_obj;
  5.          
  6.         u16 i;
  7.         u16 uart2Len=0;
  8.          
  9.         u8 dtbuf[50];   //打印缓存器
  10.                  
  11.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

  12.         USART2_RX_STA=0;
  13.         memset(USART2_RX_BUF, 0, sizeof(USART2_RX_BUF));
  14.         
  15.         memset(dtbuf,'\0',50);

  16.         //初始化
  17.         //延时函数初始化
  18.         delay_init();
  19.                   
  20.         uart_init(115200);                      //串口1:Debug,初始化为115200
  21.         uart2_init(115200);
  22.         
  23.         //定时器3,--步进电机使用
  24.         TIM3_Int_Init(99,7199);         //1ms中断
  25.         TIM3_Set(0);

  26.         StepMotor_Init();
  27.         
  28.         printf("System Init OK \r\n");
  29.         
  30.         //主循环
  31.         while(1)
  32.         {
  33.                 //ESP8266
  34.                 if(USART2_RX_STA&0x8000)
  35.                 {
  36.                         uart2Len=USART2_RX_STA&0x3f;
  37.                     
  38.                         receive_json = cJSON_Parse(USART2_RX_BUF);      //创建JSON解析对象,返回JSON格式是否正确
  39.                         if (!receive_json)
  40.                         {
  41.                                 printf("JSON格式错误:%s\r\n", cJSON_GetErrorPtr()); //输出json格式错误信息
  42.                         }
  43.                         else
  44.                         {
  45.                                 printf("JSON格式正确:\n%s\r\n",cJSON_Print(receive_json) );
  46.                                 item_obj = receive_json->child; //获取name键对应的值的信息
  47.                                 
  48.                                 while(item_obj)
  49.                                 {
  50.                                         char * string = item_obj->string;
  51.                                        
  52.                                         if(!strcmp(string,"PowerSwitch"))
  53.                                         {
  54.                                                 if(item_obj->valueint==1)
  55.                                                 {
  56.                                                         L298D_12ENA = 1;        //只有转的时候使能,否则持续供电,芯片和电机过热。
  57.                                                         L298D_34ENA = 1;
  58.                                                         
  59.                                                         TIM3_Set(1);
  60.                                                         
  61.                                                         nRotationCounting = 0;
  62.                                                         
  63.                                                         stuAliOSIoT.PowerSwitch = 1;
  64.                                                         
  65.                                                         printf("PowerSwitch:1\r\n");
  66.                                                 }
  67.                                                 else if(item_obj->valueint==0)
  68.                                                 {
  69.                                                         //步进电机运动停止
  70.                                                         L298D_12ENA = 0;
  71.                                                         L298D_34ENA = 0;
  72.                                                         
  73.                                                         TIM3_Set(0);
  74.                                                         
  75.                                                         stuAliOSIoT.PowerSwitch = 0;
  76.                                                         
  77.                                                         printf("PowerSwitch:0\r\n");
  78.                                                 }
  79.                                         }
  80.                                        
  81.                                         item_obj = item_obj->next;
  82.                                 }
  83.                                 
  84.                                 cJSON_Delete(receive_json);
  85.                                 
  86.                         }
  87.                         
  88.                         USART2_RX_STA=0;
  89.                         memset(USART2_RX_BUF, 0, sizeof(USART2_RX_BUF));   //清空数组
  90.                 }
  91.                                 
  92.                 delay_ms(10);
  93.         }
  94.         
  95. }
复制代码

定时器中代码如下:

  1. //定时器3中断服务程序
  2. void TIM3_IRQHandler(void)
  3. {
  4.         if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)//是更新中断
  5.         {
  6.                 TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIM3更新中断标志
  7.                
  8.                 nRotationCounting++;
  9.                 if(nRotationCounting > nSingleCycleDataPoints)
  10.                 {
  11.                         if(nRotationDirection==0)
  12.                         {
  13.                                 nRotationDirection=1;
  14.                         }
  15.                         else if(nRotationDirection==1)
  16.                         {
  17.                                 nRotationDirection=0;
  18.                         }
  19.                         
  20.                         nRotationCounting=0;
  21.                 }
  22.                
  23.                 if(stuAliOSIoT.PowerSwitch)
  24.                 {
  25.                         if(nRotationDirection==0)                       //正转
  26.                         {
  27.                                 TwoPhaseMotor(nRotationCounting%4+1,0);                         //顺时针
  28.                         }
  29.                         else if(nRotationDirection==1)          //反转
  30.                         {
  31.                                 TwoPhaseMotor(nRotationCounting%4+1,1);
  32.                         }
  33.                 }
  34.                
  35.                 //TIM_Cmd(TIM3, DISABLE);  //关闭TIM3
  36.         }
  37. }
复制代码


实物图
电源座用于提供外部VS供电;
微信图片_20200929223420.png


收藏 评论0 发布时间:2020-9-29 22:37

举报

0个回答

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版