STM32 driver stepper motor driver (HAL library)

! ! This article gives the driver source code, as well as frequently asked questions. Note that it is the HAL library! !
Supports forward and reverse rotation, braking, and the codes are all defined as macros to facilitate subsequent addition to the project.
Each time the motor rotates, it will continue to the previous step.

introduce

A stepper motor is a special type of motor whose movement is achieved by gradually turning a certain angle of step angle. The movement of the stepper motor is carried out in a discrete step manner. Each step rotates a fixed angle, which can achieve precise position control. A stepper motor consists of a fixed number of step angles, a rotor, windings and a drive circuit. There are generally two main types of stepper motors: single-phase stepper motors and two-phase stepper motors. Each type can be divided into different variants, but their basic working principle is the same. The working principle of stepper motors is based on the interaction of electromagnetism and magnetism. It consists of a rotating component (often called a rotor) and a stator. Windings on the stator generate a magnetic field based on the input current, while the rotor has permanent magnets. When current passes through the stator windings, the magnetic field interacts with the permanent magnets on the rotor, causing the rotor to rotate. The rotation of a stepper motor is measured in step angles, which depend on the design and construction of the motor. By applying appropriate current pulses in sequence, precise rotational motion can be achieved, while the speed and position of the motor can be controlled. Stepper motors are widely used in many applications, especially those that require precise position control or rotation to a specific angle, such as printers, CNC machine tools, robots, precision instruments, etc.
This article uses the most common and simplest 28BYJ-48, which is a five-wire four-terminal motor.
Insert image description here

principle

The working principle of a stepper motor is based on the interaction of electromagnetism and magnetism. It contains a stator and a rotor, as well as a drive circuit that controls the rotation of the rotor through current.
Stator and windings: The stator of a stepper motor usually contains several windings. These windings are connected to the power supply. The current flowing through the windings can generate a magnetic field on the stator. The arrangement and number of these windings affects the type and characteristics of the stepper motor.
Rotor and permanent magnets: Stepper motors usually have permanent magnets on their rotors, which produce a stable magnetic field. This magnetic field interacts with the magnetic field generated on the stator, causing the rotor to rotate.
Step angle and step motion: The rotation of the stepper motor is performed in fixed step angle units. The step angle is the angle at which the motor rotates each time it receives a pulse. This angle is determined by the mechanical design and electrical characteristics of the motor. By gradually applying pulse signals to the motor, step-by-step rotational motion can be achieved. The smaller the step angle, the higher the rotation accuracy of the motor.
Drive circuit and pulse control: In order to control the rotation of a stepper motor, a drive circuit is required to generate appropriate current pulses. The drive circuit generates a series of pulses based on the input control signal, and these pulses flow through the different windings of the stepper motor in sequence, thereby generating a magnetic field and rotation. Controlling the frequency and number of pulses can control the rotation speed and angle of the motor.
Full-step and half-step modes: Stepper motors can operate in full-step mode or half-step mode. In full-step mode, each step angle rotates a complete step angle. In half-step mode, each step angle turns half the step angle, allowing for finer control and smoother motion.

half step mode

Insert image description here

full step mode

Insert image description here
Since the output current of the IO port of the microcontroller is too small to drive the motor, we need to add another driver board, just use ULN2003, which is simple and cheap.

Experimental code

step_motor.h

/**
 ****************************************************************************************************
 * @file        step_motor.h
 * @author      Mr.wang
 * @version     V1.0
 * @date        2023-08-1
 * @brief       步进电机驱动代码
 ****************************************************************************************************
 */

#ifndef _STEP_MOTOR_H
#define _STEP_MOTOR_H
#include "./SYSTEM/sys/sys.h"
/******************************************************************************************/

//在这里配置引脚 A-D
#define MOTOR_GPIO_PORT                 GPIOB
#define MOTOR_GPIO_PIN_A                GPIO_PIN_3
#define MOTOR_GPIO_PIN_B                GPIO_PIN_4
#define MOTOR_GPIO_PIN_C                GPIO_PIN_5
#define MOTOR_GPIO_PIN_D                GPIO_PIN_6
#define MOTOR_GPIO_CLK_ENABLE()         do{
      
       __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)   


#define GPIO_A_ON() HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR_GPIO_PIN_A, GPIO_PIN_SET);
#define GPIO_A_OFF() HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR_GPIO_PIN_A, GPIO_PIN_RESET);
#define GPIO_B_ON() HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR_GPIO_PIN_B, GPIO_PIN_SET);
#define GPIO_B_OFF() HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR_GPIO_PIN_B, GPIO_PIN_RESET);
#define GPIO_C_ON() HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR_GPIO_PIN_C, GPIO_PIN_SET);
#define GPIO_C_OFF() HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR_GPIO_PIN_C, GPIO_PIN_RESET);
#define GPIO_D_ON() HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR_GPIO_PIN_D, GPIO_PIN_SET);
#define GPIO_D_OFF() HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR_GPIO_PIN_D, GPIO_PIN_RESET);


/******************************************************************************************/
/* 外部接口函数*/
void step_motor_init(void);
void Move_StopNow(void);
void stepMotor_8(uint8_t dir);
void Move_Step_8(uint8_t dir, uint16_t Step);

#endif

step_motor.c

/**
 ****************************************************************************************************
 * @file        step_motor.c
 * @author      Mr.wang
 * @version     V1.0
 * @date        2023-08-1
 * @brief       步进电机驱动代码
 ****************************************************************************************************
 */

#include "./BSP/LED/step_motor.h"
#include "./SYSTEM/delay/delay.h"


uint8_t motorSequence_8[] = {
    
    0x01, 0x03, 0x02, 0x06, 0x04, 0x0c, 0x08, 0x09};   // 步进电机八拍序列
uint16_t currentStep_8 = 0; // 目前处于哪一拍
uint8_t stepx = 0;
uint8_t step = 0;

/**
 * @brief       步进电机初始化
 * @param       无
 * @retval      无
 */
void step_motor_init(void)
{
    
    
    GPIO_InitTypeDef GPIO_InitStruct;
    MOTOR_GPIO_CLK_ENABLE();

    GPIO_InitStruct.Pin = MOTOR_GPIO_PIN_A | MOTOR_GPIO_PIN_B | MOTOR_GPIO_PIN_C | MOTOR_GPIO_PIN_D; //  选择引脚
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出模式
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速输出
    HAL_GPIO_Init(MOTOR_GPIO_PORT, &GPIO_InitStruct);
}



/**
 * @brief       刹车
 * @param       无
 * @retval      无
 */
void Move_StopNow(void)
{
    
    
    uint8_t stop = 0x0F;
    if (stop & 0x01)
    {
    
    
        GPIO_A_ON();
    }
    else
    {
    
    
        GPIO_A_OFF();
    }
    if (stop & 0x02)
    {
    
    
        GPIO_B_ON();
    }
    else
    {
    
    
        GPIO_B_OFF();
    }
    if (stop & 0x04)
    {
    
    
        GPIO_C_ON();
    }
    else
    {
    
    
        GPIO_C_OFF();
    }
    if (stop & 0x08)
    {
    
    
        GPIO_D_ON();
    }
    else
    {
    
    
        GPIO_D_OFF();
    }
}
/**
 * @brief       步进电机转动 连续转动没有抖动
 * @param       dir 方向 1是正向 0是反向
 * @retval      无
 */
void stepMotor_8(uint8_t dir)
{
    
    
		if (dir == 1)
				stepx = (stepx + 1) % 8;
    else if (dir == 0)
        stepx = (stepx + 7) % 8;
    step = motorSequence_8[stepx];
    if (step & 0x01)
    {
    
    	
				GPIO_A_ON();
    }
    else
    {
    
    
        GPIO_A_OFF();
    }
    if (step & 0x02)
    {
    
    
        GPIO_B_ON();
    }
    else
    {
    
    
        GPIO_B_OFF();
    }
    if (step & 0x04)
    {
    
    
        GPIO_C_ON();
    }
    else
    {
    
    
        GPIO_C_OFF();
    }
    if (step & 0x08)
    {
    
    
        GPIO_D_ON();
    }
    else
    {
    
    
				GPIO_D_OFF();
    }
}
/**
 * @brief       步进电机转动 连续转动没有抖动
 * @param       dir 方向  方向 1是正向 0是反向
 * @param       Step 步数
 * @retval      里面用到了delay_ms阻塞函数
 */
void Move_Step_8(uint8_t dir, uint16_t Step)
{
    
    
    uint16_t Count = Step; // 步数
    while (Count--)
    {
    
    
        stepMotor_8(dir);
        delay_ms(1);
    }
}

main.c test

int main(void)
{
    
    
    HAL_Init();                                 /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟,72M */
    delay_init(72);                             /* 初始化延时函数 */
    step_motor_init();                          /* 初始化步进电机 */
    while(1)
    {
    
    
				Move_Step_8(1, 2500); //步进电机正转2500步
        delay_ms(500);
				Move_Step_8(0, 2500); //步进电机反转2500步
        delay_ms(500);
    }
}

Insert image description here

conclusion of issue

1. If a problem occurs, please check the pin definition, pin clock definition and group definition.

//在这里配置引脚 A-D
#define MOTOR_GPIO_PORT                 GPIOB
#define MOTOR_GPIO_PIN_A                GPIO_PIN_3
#define MOTOR_GPIO_PIN_B                GPIO_PIN_4
#define MOTOR_GPIO_PIN_C                GPIO_PIN_5
#define MOTOR_GPIO_PIN_D                GPIO_PIN_6
#define MOTOR_GPIO_CLK_ENABLE()         do{
      
       __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) 

2. If the motor jitters, just change the delay and increase or decrease it.

void Move_Step_8(uint8_t dir, uint16_t Step)
{
    
    
    uint16_t Count = Step; // 步数
    while (Count--)
    {
    
    
        stepMotor_8(dir);
        delay_ms(1);    <--------更改这里
    }
}
``

Guess you like

Origin blog.csdn.net/Systemmax20/article/details/132251981