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

news2025/2/25 11:48:55

【本文发布于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拍平顺了不少


在这里插入图片描述

八拍反转



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


在这里插入图片描述

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


在这里插入图片描述

反转


在这里插入图片描述

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


在这里插入图片描述

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


以上为波形研究,待续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/870156.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ARTS 挑战打卡的第一周,我学到了这些~

目录 前言 一、学习的内容 二、超时怎么办那就换种思路看题解 三、学习打卡成果展示 3.1 Github的小技巧 3.2 英文文章阅读 3.3 一篇很不错的Java面试题博客 四、学习技巧的总结 前言 关于 ARTS 的释义 ● Algorithm: 每周至少做一个 LeetCode 的算法题 ● Review: 阅读…

Javascript异步编程的4种方法

你可能知道&#xff0c;Javascript语言的执行环境是"单线程"&#xff08;single thread&#xff09;。 所谓"单线程"&#xff0c;就是指一次只能完成一件任务。如果有多个任务&#xff0c;就必须排队&#xff0c;前面一个任务完成&#xff0c;再执行后面一…

使用selenium如何实现自动登录

回顾使用requests如何实现自动登录一文中&#xff0c;提到好多网站在我们登录过后&#xff0c;在之后的某段时间内访问该网页时&#xff0c;不会给出请登录的提示&#xff0c;时间到期后就会提示请登录&#xff01;这样在使用爬虫访问网页时还要登录&#xff0c;打乱我们的节奏…

【Linux】以太网协议——数据链路层

链路层解决的问题 IP拥有将数据跨网络从一台主机送到另一台主机的能力&#xff0c;但IP并不能保证每次都能够将数据可靠的送到对端主机&#xff0c;因此IP需要上层TCP为其提供可靠性保证&#xff0c;比如数据丢包后TCP可以让IP重新发送数据&#xff0c;最终在TCP提供的可靠性机…

数据通信——网络层(ACL)

引言 在网络中会区分三个区域&#xff1a;&#xff08;Trust&#xff09;内网&#xff0c;&#xff08;UnTrust&#xff09;外网&#xff0c;&#xff08;DM2&#xff09;非军事化区域 防火墙在网络中可以阻止DM2对Trust的访问。同理&#xff0c;从Trust到UnTrust或者UnTrust到…

STM32 CubeMX (uart_IAP串口)简单示例

STM32 CubeMX [TOC]( STM32 CubeMX (uart_IAP串口)简单示例) 前言 单片机flash有两部分1.IAP程序和2.APP程序&#xff1b;IAP是烧录工具烧录的&#xff0c;App是串口烧录的 #1.IAP程序设置,程序地址 #2.APP程序设置&#xff0c;程序地址 生成bin文件 fromelf.exe --bin -o …

2023高教社杯数学建模A题 B题C题 D题 E题思路代码分析

文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 全国大学生数学建模…

指针的进阶--从入门到入土

指针--变态加强版 前言面试题字符指针指针数组数组指针函数指针函数指针数组指向函数指针数组的指针面试题解析结语 前言 掌握指针这块知识的重要性不言而喻&#xff0c;当你觉得自己已经差不多掌握指针的时候&#xff0c;不妨看看下面8道面试题&#xff08;题目从简单到困难&…

三级城市展示省市区树

展示效果 数据库展示 业务代码 /*** 省市区树*/VLicenseApiOperation("查询经纬度")ApiImplicitParam(name "FnCity", value "省市区树", dataType "FnCity")GetMapping("/districtlist")public AjaxResult districtlist…

STM32F429IGT6使用CubeMX配置IIC通信(AT2402芯片)

1、硬件电路 写地址&#xff1a;0xA0 读地址&#xff1a;0xA1 存储容量&#xff1a;256Byte 2、设置RCC&#xff0c;选择高速外部时钟HSE,时钟设置为180MHz 3、配置IIC 4、生成工程配置 5、部分代码 #define IIC_WRITE_ADDR 0xA0 // IIC写地址 #define IIC_READ_ADDR 0xA1 …

数据结构----哈夫曼树

这里写目录标题 基本概念引子基本概念各种路径长度各种带权路径长度结点的带权路径长度树的带权路径长度哈夫曼树 哈夫曼树的构造理论基础构造思想总结 一级目录二级目录二级目录二级目录 一级目录二级目录二级目录二级目录 一级目录二级目录二级目录二级目录 一级目录二级目录…

exec族函数

本节学习exec族函数&#xff0c;并大量参考了以下链接&#xff1a; linux进程---exec族函数(execl, execlp, execle, execv, execvp, execvpe)_云英的博客-CSDN博客 exec族函数函数的作用 我们用fork函数创建新进程后&#xff0c;经常会在新进程中调用exec函数去执行另外一个程…

从零构建深度学习推理框架-8 卷积算子实现

其实这一次课还蛮好理解的&#xff1a; 首先将kernel展平&#xff1a; for (uint32_t g 0; g < groups; g) {std::vector<arma::fmat> kernel_matrix_arr(kernel_count_group);arma::fmat kernel_matrix_c(1, row_len * input_c_group);for (uint32_t k 0; k < k…

【leetcode】前缀和

内容摘抄自&#xff1a; 小而美的算法技巧&#xff1a;前缀和数组 | labuladong 的算法小抄 一维数组的前缀和 看这个 preSum 数组&#xff0c;若想求索引区间 [1, 4] 内的所有元素之和&#xff0c; 就可以通过 preSum[5] - preSum[1] 得出。 class NumArray {private:// 前缀…

软件测试基础篇——Docker

1、docker技术概述 docker描述&#xff1a;docker是一项虚拟化的容器技术&#xff08;类似于虚拟机&#xff09;&#xff0c;docker技术给使用者提供一个平台&#xff0c;在该平台上可以利用提供的容器&#xff0c;对每一个应用程序进行单独的封装隔离&#xff0c;每一个应用程…

记录--用css画扇形菜单

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 1、效果图 用手机录屏再用小程序转换的gif&#xff0c;可能精度上有点欠缺。 2、实现过程 1、观察及思考 开始编码前我们首先观察展开后的结构&#xff1a;两个四分之一的圆加三个圆形菜单项。 文章名…

阿里云服务器部署Drupal网站教程基于CentOS系统

阿里云百科分享如何在CentOS 7操作系统的ECS实例上搭建Drupal电子商务网站。Drupal是使用PHP语言编写的开源内容管理框架&#xff08;CMF&#xff09;&#xff0c;它由内容管理系统&#xff08;CMS&#xff09;和PHP开发框架&#xff08;Framework&#xff09;共同构成。它用于…

【博客692】grafana如何解决step动态变化时可能出现range duration小于step

grafana如何解决step动态变化时可能出现range duration小于step 1、grafana中的step和resolution grafana中的 “step” grafana本身是没有提供step参数的&#xff0c;因为仪表盘根据查询数据区间以及仪表盘线条宽度等&#xff0c;对于不同查询&#xff0c;相同的step并不能…

编译redis-5.0.9报错zmalloc.h:50:31: 致命错误:jemalloc/jemalloc.h:没有那个文件或目录问题解决

上图 解决&#xff1a; make && make install MALLOClibc原因: 原因是jemalloc重载了Linux下的ANSI C的malloc和free函数。

RedisDesktopManage

RDM 简介下载安装 简介 RedisDesktopManager&#xff08;RDM&#xff09;是一个开源的跨平台图形界面工具&#xff0c;用于管理和操作 Redis 数据库。它提供了一个用户友好的界面&#xff0c;使用户能够轻松地连接、浏览、查询和修改 Redis 数据&#xff0c;而无需使用命令行界…