自带减速器,五线四相单极性,直径为28mm。一般有五根线。红色是公共的VCC(5v),A相蓝色,B相粉色,C相黄色,D相橙色。如果采用单双拍如图所示:

第一步:先D相导通接GND,其他接高电平。第二部:D,C相导通接GND其他接高电平。一次走完8步。如果对应MCU那么红色接VCC(5V),其他四相接MCU的普通I/o并且选择推挽输出。如果让电机反转则把步数反过来。注意每一步的切换都要延时一段时间。

首先相电阻就是公共端与每相之间的电阻。 步距角有两种情况。没有加减速比的时候。5.625度。
加减速比就是5.625/ 64。 因为减速比是1:64。启动频率>=500。
一个脉冲电机转5.625度。一圈(360)= 360/ 5.625 = 64个脉冲。那么减速后轴转一圈需要64 *64 = 4096.当然减速比不可能精确1:64.总有误差存在。28BYJ-48步进电机实际上是:减速齿轮+步进电机组成。内部减速齿轮如下:

由于MCU的端口的电流很小对于驱动电流大的外设需要驱动板(放大电流)。
电机需要驱动的电流 VCC/ 相电阻 = 5 / 300 =16.7mA。
ULN2003是大电流达林顿晶体管阵列系列产品,具有电流增益高、工作电压高、温度范围宽、带负载能力强等特点,适应于各类要求高速大功率驱动的系统。ULN2003A由7组达林顿晶体管阵列和相应的电阻网络以及钳位二极管网络构成,具有同时驱动7组负载的能力,为单片双极型大功率高速集成电路。ULN2003可用于小型步进电机驱动。

下面如图接线方法:

ULN2003_IN1, ULN2003_IN2,ULN2003_IN3,ULN2003_IN4左边接MCU的I/o口,经过ULN2003AD后电流就放大了从而去驱动电机。
uln2003.h
#ifndef __BSP_ULN2003_H__
#define __BSP_ULN2003_H__
#include "stm32f4xx_hal.h"
#define ULN2003_RCC_CLK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE()
#define ULN2003_GPIO_PIN (GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6)
#define ULN2003_GPIO_PORT GPIOF
#define A_ON HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_3,GPIO_PIN_SET)
#define A_OFF HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_3,GPIO_PIN_RESET)
#define B_ON HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_4,GPIO_PIN_SET)
#define B_OFF HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_4,GPIO_PIN_RESET)
#define C_ON HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_5,GPIO_PIN_SET)
#define C_OFF HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_5,GPIO_PIN_RESET)
#define D_ON HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_6,GPIO_PIN_SET)
#define D_OFF HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_6,GPIO_PIN_RESET)
void ULN2003_GPIO_Init(void);
#endif // __BSP_ULN2003_H__
uln2003.c
#include "StepMotor/bsp_uln2003.h"
void ULN2003_GPIO_Init(void)
{
/* 定义IO硬件初始化结构体变量 */
GPIO_InitTypeDef GPIO_InitStruct;
/* 使能(开启)端口时钟 */
ULN2003_RCC_CLK_ENABLE();
/* 一开始设置为低电平 */
HAL_GPIO_WritePin(ULN2003_GPIO_PORT,ULN2003_GPIO_PIN,GPIO_PIN_RESET);
/* 设定引脚IO编号 */
GPIO_InitStruct.Pin = ULN2003_GPIO_PIN;
/* 设定引脚IO为输出模式 */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
/* 设定引脚IO操作速度 */
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
/* 初始化引脚IO */
HAL_GPIO_Init(ULN2003_GPIO_PORT, &GPIO_InitStruct);
}
main.c
#include "stm32f4xx_hal.h"
#include "StepMotor/bsp_uln2003.h"
#define STEPMOTOR_SPEED 10 // 定义步进电机速度,值越小,速度越快
void SystemClock_Config(void);
/**
* 函数功能: 系统时钟配置
* 输入参数: 无
* 返 回 值: 无
* 说 明: 无
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE(); // 使能PWR时钟
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); // 设置调压器输出电压级别1
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 外部晶振,8MHz
RCC_OscInitStruct.HSEState = RCC_HSE_ON; // 打开HSE
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // 打开PLL
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // PLL时钟源选择HSE
RCC_OscInitStruct.PLL.PLLM = 8; // 8分频MHz
RCC_OscInitStruct.PLL.PLLN = 336; // 336倍频
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // 2分频,得到168MHz主时钟
RCC_OscInitStruct.PLL.PLLQ = 7; // USB/SDIO/随机数产生器等的主PLL分频系数
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 系统时钟:168MHz
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB时钟: 168MHz
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // APB1时钟:42MHz
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // APB2时钟:84MHz
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
HAL_RCC_EnableCSS(); // 使能CSS功能,优先使用外部晶振,内部时钟源为备用
// HAL_RCC_GetHCLKFreq()/1000 1ms中断一次
// HAL_RCC_GetHCLKFreq()/100000 10us中断一次
// HAL_RCC_GetHCLKFreq()/1000000 1us中断一次
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); // 配置并启动系统滴答定时器
/* 系统滴答定时器时钟源 */
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* 系统滴答定时器中断优先级配置 */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/**
* 函数功能: 主函数.
* 输入参数: 无
* 返 回 值: 无
* 说 明: 无
*/
int main(void)
{
uint8_t i=0;
/* 复位所有外设,初始化Flash接口和系统滴答定时器 */
HAL_Init();
/* 配置系统时钟 */
SystemClock_Config();
ULN2003_GPIO_Init();
/* 无限循环 */
while (1)
{
// 8个节拍控制:A->AB->B->BC->C->CD->D->DA 正转 如果反过来可以反转 2.这个可以控制方向
switch(i)
{
case 0:
A_ON; B_OFF; C_OFF; D_OFF;
break;
case 1:
A_ON; B_ON; C_OFF; D_OFF;
break;
case 2:
A_OFF; B_ON; C_OFF; D_OFF;
break;
case 3:
A_OFF; B_ON; C_ON; D_OFF;
break;
case 4:
A_OFF; B_OFF; C_ON; D_OFF;
break;
case 5:
A_OFF; B_OFF; C_ON; D_ON;
break;
case 6:
A_OFF; B_OFF; C_OFF; D_ON;
break;
case 7:
A_ON; B_OFF; C_OFF; D_ON;
break;
}
i++; // 步进加1
if(i==8) i=0; // 重新开始循环步进
HAL_Delay(STEPMOTOR_SPEED); // 延时一小段时间,时间长短决定电机转速 1.这个延时可以控制速度
}
}
这里公共端是接GDN,所以某相接高低平就接通,并且这里采用单双拍工作方式。每一步切换都有一个延时,这个延时可以控制速度。改变步数的顺序可以控制方向。
uln2003.h uln2003.c跟上面一样,只是main.c不同,并且加了按键控制。
main.c
#include "stm32f4xx_hal.h"
#include "StepMotor/bsp_uln2003.h"
#include "key/bsp_key.h"
#define STEPMOTOR_SPEED 1 // 定义步进电机速度,值越小,速度越快
#define STEPMOTOR_CIRCLE_NUMBER 10 // 转动圈数
#define STEPMOTOR_DIRECTION 1 // 1:顺时针 0:逆时针
uint8_t speed = STEPMOTOR_SPEED; // 用一个变量保存速度
// 转动圈数:28BYJ-48步进电机的步距角度为5.625/64,即每64个脉冲转5.625度
// 要转一圈需要360/5.625*64=4096个脉冲。 // 没有减速:一个脉冲 转 5.625 如果转360 要64个脉冲 减速后:因为减速比是1:64 轴需要 64 *64 =4096个脉冲
uint32_t Circle_number= 0; // 圈数
// 选择方向控制
uint8_t direction = STEPMOTOR_DIRECTION; // 用一个变量保存方向
void SystemClock_Config(void);
/**
* 函数功能: 系统时钟配置
* 输入参数: 无
* 返 回 值: 无
* 说 明: 无
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE(); // 使能PWR时钟
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); // 设置调压器输出电压级别1
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 外部晶振,8MHz
RCC_OscInitStruct.HSEState = RCC_HSE_ON; // 打开HSE
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // 打开PLL
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // PLL时钟源选择HSE
RCC_OscInitStruct.PLL.PLLM = 8; // 8分频MHz
RCC_OscInitStruct.PLL.PLLN = 336; // 336倍频
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // 2分频,得到168MHz主时钟
RCC_OscInitStruct.PLL.PLLQ = 7; // USB/SDIO/随机数产生器等的主PLL分频系数
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 系统时钟:168MHz
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB时钟: 168MHz
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // APB1时钟:42MHz
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // APB2时钟:84MHz
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
HAL_RCC_EnableCSS(); // 使能CSS功能,优先使用外部晶振,内部时钟源为备用
// HAL_RCC_GetHCLKFreq()/1000 1ms中断一次
// HAL_RCC_GetHCLKFreq()/100000 10us中断一次
// HAL_RCC_GetHCLKFreq()/1000000 1us中断一次
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); // 配置并启动系统滴答定时器
/* 系统滴答定时器时钟源 */
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* 系统滴答定时器中断优先级配置 */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/**
* 函数功能: 输出一个数据给ULN2003从而实现向步进电机发送一个脉冲
* 输入参数: step:指定步进序号,可选值0~7
* direction:方向选择
* 可选值:1:顺时针
* 0:逆时针
* 返 回 值: 无
* 说 明: 无
*/
static void step_motor_pulse(uint8_t step,uint8_t direction)
{
uint8_t temp=step;
if(direction==0) // 如果为逆时针旋转
{
temp=7-step; // 调换节拍信号
}
switch(temp)
{
// 8个节拍控制:A->AB->B->BC->C->CD->D->DA
case 0:
A_ON; B_OFF; C_OFF; D_OFF;
break;
case 1:
A_ON; B_ON; C_OFF; D_OFF;
break;
case 2:
A_OFF; B_ON; C_OFF; D_OFF;
break;
case 3:
A_OFF; B_ON; C_ON; D_OFF;
break;
case 4:
A_OFF; B_OFF; C_ON; D_OFF;
break;
case 5:
A_OFF; B_OFF; C_ON; D_ON;
break;
case 6:
A_OFF; B_OFF; C_OFF; D_ON;
break;
case 7:
A_ON; B_OFF; C_OFF; D_ON;
break;
}
}
/**
* 函数功能: 主函数.
* 输入参数: 无
* 返 回 值: 无
* 说 明: 无
*/
int main(void)
{
/* 复位所有外设,初始化Flash接口和系统滴答定时器 */
HAL_Init();
/* 配置系统时钟 */
SystemClock_Config();
KEY_GPIO_Init();
ULN2003_GPIO_Init();
/* 无限循环 */
while (1)
{
if(KEY1_StateRead()==KEY_DOWN)
{
direction=1; // 顺时针方向
Circle_number=STEPMOTOR_CIRCLE_NUMBER;//赋值给目标旋转圈数,重新开始旋转
}
if(KEY2_StateRead()==KEY_DOWN)
{
direction=0; // 逆时针方向
Circle_number=STEPMOTOR_CIRCLE_NUMBER;//赋值给目标旋转圈数,重新开始旋转
}
if(KEY3_StateRead() == KEY_DOWN) // 加速
{
speed --;
if(speed <= STEPMOTOR_SPEED)
speed = STEPMOTOR_SPEED;
}
if(KEY4_StateRead() == KEY_DOWN) // 减速
{
speed ++;
}
}
}
/**
* 函数功能: 滴答定时器回调函数.
* 输入参数: 无
* 返 回 值: 无
* 说 明: 每隔一定的时间就输出新节拍信号
*/
void HAL_SYSTICK_Callback(void)
{
static uint8_t count=0; // 用于旋转速度控制
static uint8_t step=0; // 当前步进节拍
static uint16_t pulse_count=0; // 脉冲计数,4096个脉冲电机旋转一圈
if(Circle_number) // 如果等待旋转圈数不为0
{
count++; // 增加时间计数
if(count==speed) // 时间计数与目标速度相对时执行下一节拍输出 // 旋转一圈要 4096ms *speed
{
step_motor_pulse(step,direction); // 输出新节拍信号
pulse_count++; // 脉冲输出数增加
step++; // 节拍数增加
if(step==8) step=0; // 循环开始输出节拍
count=0; // 清零时间计数
}
if(pulse_count==4096) // 如果已经输出了4096个脉冲信号,已经转动了一圈
{
pulse_count=0; // 脉冲计数清零
Circle_number--; // 等待旋转圈数减1
}
}
else // 转完设置的圈数停止旋转
{
A_OFF; B_OFF; C_OFF; D_OFF; // 停机
}
}
目录前言一、定时器部分和按键部分二、PWM调速三、电机驱动部分三、编码器接口部分(测速)四.主函数总结推荐STM32学习课程:[6-8]编码器接口测速_哔哩哔哩_bilibili[6-8]编码器接口测速是STM32入门教程-2022持续更新中的第20集视频,该合集共计30集,视频收藏或关注UP主,及时了解更多相关视频内容。https://www.bilibili.com/video/BV1th411z7sn/?p=20&spm_id_from=pageDriver&vd_source=ed36b2700bbc2bac7746c270bc391540OLED显示屏代码
最近玩步进电机时候,发现步进电机驱动种类多;A4988,drv8825,tb6600,lv8731……;tb6600驱动电流可达4A,1600细分,十分强大,但是体积大,用在平衡车上不太合适。drv8825加散热器驱动电流可达2.5A,32细分,还不错。芯片介绍这里的介绍只介绍其引脚连接。如图是它的说明书中对引脚的解释在这里把它翻译成中文。 为了方便大家使用,说明书还给出了一种典型的连接方式 这样初始化好之后,将AOUT1、AOUT2、BOUT1、BOUT2分别连接到步进电机对应信号线,AOUT1与AOUT2同相,BOUT1与BOUT2同相。判断步进电机信号线是否同相的一个方法是将其中两条接
电动势,是导体内电子运动的必要条件,也是电子运动趋势的一种表现,因而具有一定的方向性。电动势的方向,规定为从电源的负极,经过电源内部指向电源的正极,即与电源两端电压的方向相反。反电动势,是指由反抗电流发生改变的趋势而产生电动势。反电动势一般出现在电磁线圈中,如继电器线圈、电磁阀、接触器线圈、电动机、电感等。对于电动机产品,定子部分是电能的输入端,而转子部分则是电机做功的输出端;通过定子部分输入的电能,一部分用于转子部分做功,另一部分则会消耗于线路内阻,以及其他损耗。转子部分产生的反电动势,即电动机做功的要素。反电动势消耗了电路中的电能,但它并不是一种“损耗”,与反电动势对应的那部分电能,将转
性能指标一、性能测试指标性能测试是通过测试工具模拟多种正常、峰值及异常负载条件来对系统的各项性能指标进行测试。目的:验证软件系统是否能够达到用户提出的性能指标,发现系统中存在的性能瓶颈并加以优化。二、指标分为两大类:软件指标:术语释义TPS:(每秒事务数)在每秒时间内系统可处理完毕的事务数。TPS很大程度体现系统性能能力。TPS(TransactionPerSecond)是指单位时间(每秒)系统处理的事务量。事务可以是用户自定义的一系列操作或者动作的集合,比如“用户注册“事务是点击注册按钮,填写用户注册信息,点击提交按钮,以及加载注册成功页面的动作集合。这3个个公式都是对的第1个公式计算的是绝
目录l298n模块详解l298n芯片简介 在嵌入式领域中l298n属于最常用的电机驱动模块,该模块稳定,耐用,操作简单备受广大电子爱好者的喜爱,今天小编结合自己开发的经验来给初学者门聊聊如何使用这款模块及芯片的用法l298n模块详解如图所示,模块左右两侧的2P的端子是接入电机的,左右两端分别可以接入一个直流电机。由于直流电机不分正负所以怎样接都是可以的。中间3P的端子分别接12V,GND,5V。黑色排针部分左右两端的跳帽插上代表使能,l298n有两个通道,所以有两个使能跳帽。中间的四个排针是逻辑输入,左边两个为一组,右边两个为另一组,真值表如下图所示下图附带了l298n模块的原理图,想自己di
jpm版本为1.1.3npm版本为2.15.8节点版本为4.4.7火狐版本为48.0index.js的内容:varself=require("sdk/self");console.log("************************************");“jpmrun”命令的输出JPM[info]StartingjpmrunonMyJetpackAddonJPM[info]Creatinganewprofile根据index.js文件的内容,控制台应该输出一行*符号。但是,愿望输出不在控制台中。代码有问题吗?我的package.json文件的内容:{"title":"My
我被赋予了将Java的Java.util.Random()移植到JavaScript的任务,并且我在足够大的Javascript中使用按位运算符遇到了巨大的性能损失/不准确数字。一些粗略的研究指出“JavaScript中的按位运算符本质上很慢”,因为在内部看来JavaScript会将其所有double值转换为带符号的32位整数来执行按位运算(seehere了解更多信息。)因为其中,我无法直接移植Java随机数生成器,我需要获得与Java.util.Random()相同的数值结果。写类似的东西this.next=function(bits){if(!bits){bits=48;}this
数据规模->时间复杂度10^8内容二维数组中的路径问题买卖股票的最佳时机lc62【剑指098】【top100】:不同路径https://leetcode.cn/problems/unique-paths/提示:1题目数据保证答案小于等于2*10^9#方案一:dfs+记忆化classSolution:defuniquePaths(self,m:int,n:int)->int:memo=[[-1]*nfor_inrange(m)]defdfs(i,j):ifi==m-1andj==n-1:return1ifi>=morj>=n:return0ifmemo[i][j]!=-1:returnmemo[
只是探索node.js并遇到了express;在npm存储库站点上https://www.npmjs.com/package/express它清楚地表明安装是$npminstallexpress但是如果我向下滚动提到快速启动$npminstall-gexpress-generator@4谁能详细解释一下这是怎么回事?我用谷歌搜索并了解到在expressv3中两者被捆绑在一起,但在expressv4中发电机被拉出。所以我需要同时安装两者吗?生成器是否自动安装express而不是相反?我已经有JS疲劳了,我才刚刚开始:-(补充问题:然后让事情更加困惑,我看到另一个问题,问我应该从“npmi
文章目录参考链接概述L298NTB6612FNG参考链接单片机控制直流电机基于L9110S、L298N、TB6612FNG驱动-简书概述 从上面那篇教程我们可以看出,直流电机控制时,只需要给它输入一个PWM波即可,占空比越大,电机运行速度越快。但是一般来说单片机工作电压为5V,且电流较小,而电机运行需要较大的电流,因此往往控制电机运行时,都需要在单片机与电机之间连接一个驱动,即所谓的电机驱动。 目前市面上比较常见的小型车的电机驱动一般有两种:L298N和TB6612FNG,下面分别介绍。L298N引脚定义电气特性 L298N使用时需要用12V供电(9V也行),然后其内部带有稳压模块,如果