单片机直驱两相四线步进电机研究

32 篇文章 2 订阅

【本文发布于https://blog.csdn.net/Stack_/article/details/132236329,未经允许不得转载,转载须注明出处】


双极性步进电机(两相四线步进电机),原理的东西就先不讲太多了,还没搞清楚,边查资料边写代码来理解吧。

此电路使用4片CMS6324去驱动2个H桥,每片CMS6324驱动的桥的同一侧,其自带硬件死区,所以不需要考虑死区插入的问题。如果不是这样的电路,则需要注意上下桥臂不能同时导通。


一、电机基本原理图 内部简化图


在这里插入图片描述

四拍,每个脉冲转 1.8°


在这里插入图片描述

八拍,每个脉冲转 0.9°


二、简单的驱动代码


#define MOTOR_A_P_PORT          PORT1   //P15 A+
#define MOTOR_A_P_PIN           PIN5
    
#define MOTOR_A_N_PORT          PORT1   //P14 A-
#define MOTOR_A_N_PIN           PIN4

#define MOTOR_B_P_PORT          PORT1   //P13 B+
#define MOTOR_B_P_PIN           PIN3

#define MOTOR_B_N_PORT          PORT1   //P12 B-
#define MOTOR_B_N_PIN           PIN2


#define MOTOR_A_P__SET()        PORT_SetBit(MOTOR_A_P_PORT, MOTOR_A_P_PIN)
#define MOTOR_A_P__RESET()      PORT_ClrBit(MOTOR_A_P_PORT, MOTOR_A_P_PIN)

#define MOTOR_A_N__SET()        PORT_SetBit(MOTOR_A_N_PORT, MOTOR_A_N_PIN)
#define MOTOR_A_N__RESET()      PORT_ClrBit(MOTOR_A_N_PORT, MOTOR_A_N_PIN)

#define MOTOR_B_P__SET()        PORT_SetBit(MOTOR_B_P_PORT, MOTOR_B_P_PIN)
#define MOTOR_B_P__RESET()      PORT_ClrBit(MOTOR_B_P_PORT, MOTOR_B_P_PIN)

#define MOTOR_B_N__SET()        PORT_SetBit(MOTOR_B_N_PORT, MOTOR_B_N_PIN)
#define MOTOR_B_N__RESET()      PORT_ClrBit(MOTOR_B_N_PORT, MOTOR_B_N_PIN)



    
    PORT_Init(MOTOR_A_P_PORT, MOTOR_A_P_PIN, OUTPUT); //P15 A+
    PORT_Init(MOTOR_A_N_PORT, MOTOR_A_N_PIN, OUTPUT); //P14 A-
    PORT_Init(MOTOR_B_P_PORT, MOTOR_B_P_PIN, OUTPUT); //P13 B+
    PORT_Init(MOTOR_B_N_PORT, MOTOR_B_N_PIN, OUTPUT); //P12 B-
    
    PORT_Init(PORT3, PIN0, OUTPUT); //P30 CMS6021 POWER_EN, 使能CMS6324供电
    PORT_SetBit(PORT3, PIN0);
    
	while(1)
	{
        #if (0) 													//四拍
            #if (0) 													//四拍正转
            //A+
            MOTOR_A_P__SET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //B+
            MOTOR_A_P__RESET();
            MOTOR_B_P__SET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //A-
            MOTOR_A_P__RESET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__SET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //B-
            MOTOR_A_P__RESET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__SET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            #else   													//四拍反转
            //A+
            MOTOR_A_P__SET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //B-
            MOTOR_A_P__RESET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__SET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //A-
            MOTOR_A_P__RESET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__SET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //B+
            MOTOR_A_P__RESET();
            MOTOR_B_P__SET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            #endif
        #else   													//八拍
            #if (0) 													//八拍正向
            //A+
            MOTOR_A_P__SET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //A+ B+
            MOTOR_A_P__SET();
            MOTOR_B_P__SET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //B+
            MOTOR_A_P__RESET();
            MOTOR_B_P__SET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //B+ A-
            MOTOR_A_P__RESET();
            MOTOR_B_P__SET();
            MOTOR_A_N__SET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //A-
            MOTOR_A_P__RESET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__SET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //A- B-
            MOTOR_A_P__RESET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__SET();
            MOTOR_B_N__SET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //B-
            MOTOR_A_P__RESET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__SET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //B- A+
            MOTOR_A_P__SET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__SET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            #else 														//八拍反向
            //A+
            MOTOR_A_P__SET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //B- A+
            MOTOR_A_P__SET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__SET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //B-
            MOTOR_A_P__RESET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__SET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //A- B-
            MOTOR_A_P__RESET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__SET();
            MOTOR_B_N__SET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //A-
            MOTOR_A_P__RESET();
            MOTOR_B_P__RESET();
            MOTOR_A_N__SET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //B+ A-
            MOTOR_A_P__RESET();
            MOTOR_B_P__SET();
            MOTOR_A_N__SET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //B+
            MOTOR_A_P__RESET();
            MOTOR_B_P__SET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            //A+ B+
            MOTOR_A_P__SET();
            MOTOR_B_P__SET();
            MOTOR_A_N__RESET();
            MOTOR_B_N__RESET();
            UserTimer_Reset(&timer_delay);
            while(UserTimer_Read(&timer_delay) < TIMEOUT_1MS);
            #endif
        #endif
	}

黄波形为A+ 蓝波形为B+ 紫波形为A- 绿波形为B-

在这里插入图片描述

四拍正转,每个正脉冲转1.8°,360°/1.8°=200个脉冲转一圈。一次循环A+ B+ A- B-四个脉冲,循环50次即转一圈。


在这里插入图片描述

四拍反转。四拍时,1ms切换太快了,会严重丢步,转动非常卡顿,将延时即切换时间适当拉长可获得较为平顺的效果。但导通时间过长会导致总电流很大。


在这里插入图片描述

八拍正转。拍数增加,转动相较于4拍平顺了不少


在这里插入图片描述

八拍反转



三、抓取步进电机驱动芯片/驱动器的四线波形进行对比


在这里插入图片描述

实际驱动时,不会像上面的那么“生硬”的,而是会不断调节输出的占空比的。例如下面抓取的波形




1、市面上驱动器驱动波形类型一。这种驱动方式横容易理解,跟上面相似


在这里插入图片描述

正转。可见,大体思路和上面的是一致的,只不过为了驱动更平顺以及功耗的考虑,各线通电时不是恒导通的,而是以PWM的方式进行输出


在这里插入图片描述

反转


在这里插入图片描述

每一相通电时,其正占空比都是先增后减,即电流先增后减


在这里插入图片描述

当速度提高,换相频率变高。一般地,功率也需要提高,速度不变负载增加,功率也需提高(需要接编码器),所以正占空比(平均)也变大了,电流变大




2、市面上驱动器驱动波形类型二。这种方式4根线上都是持续不断输出20kHz的波形的,分别控制A+和A-的占空比,以实现控制A相电流大小与方向的效果,如下列图中的红色波形。B+和B-同理。


① 正转


在这里插入图片描述

正转


在这里插入图片描述

A电流反向(A-流向A+)之前以及之后


在这里插入图片描述

A电流反向(A+流向A-)之前以及之后



② 反转


在这里插入图片描述

反转


在这里插入图片描述

A电流反向(A-流向A+)之前以及之后


在这里插入图片描述

A电流反向(A+流向A-)之前以及之后



以上为波形研究,待续

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用STC8G单片机驱动无源蜂鸣器的关键是使用PWM(脉冲宽度调制)技术产生可变频率的方波,通过改变方波的频率控制蜂鸣器发声的高低。 下面是一个简单的STC8G单片机PWM驱动无源蜂鸣器的程序示例: ```c #include <reg52.h> #define uint unsigned int #define uchar unsigned char //定义蜂鸣器控制IO口 sbit beep=P1^5; //PWM初始化函数 void InitPWM() { P1ASF=0x20; //设置P1.5口为可编程模拟口 PWMCR=PWMCR|0x80; //使能PWM模块 PWMCR=PWMCR&0xBF; //设置PWM时钟源为Fosc PWMCR=PWMCR&0xF8; //设置PWM分频系数为1 PWMCR=PWMCR|0x04; //设置PWM输出极性为正极性 PWMCR=PWMCR|0x01; //设置PWM工作方式为自动重载方式 PWMP=0; //初始化PWM占空比寄存器 PWM0DUTY=0; //初始化PWM0占空比寄存器 PWM0P=500; //设置PWM0周期寄存器值为500 } //延时函数 void Delayms(uint xms) { uint i,j; for(i=xms;i>0;i--) for(j=110;j>0;j--); } void main() { InitPWM(); //初始化PWM while(1) { //循环控制PWM输出频率和占空比 PWMP++; PWM0DUTY=PWMP; Delayms(10); if(PWMP>=500) PWMP=0; } } ``` 说明: 1. 程序中定义了一个蜂鸣器控制IO口beep,这里使用了P1.5口。 2. 在InitPWM()函数中,首先将P1.5口设置为可编程模拟口,然后使能PWM模块,并设置PWM时钟源为Fosc,PWM分频系数为1,PWM输出极性为正极性,PWM工作方式为自动重载方式,初始化PWM占空比寄存器、PWM0占空比寄存器和PWM0周期寄存器。 3. 在主函数中,循环控制PWM输出频率和占空比,通过改变PWMP的值来改变PWM输出频率,通过改变PWM0DUTY的值来改变PWM输出占空比。同时,使用Delayms()函数延时一段时间,以便听到蜂鸣器发出的声音。 4. 如果PWMP的值超过了500,就将其重置为0,以便循环控制PWM输出频率。 以上是一个简单的STC8G单片机PWM驱动无源蜂鸣器的程序示例,供参考。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值