Contents
  1. 1.1 Introduction to the A4988
  2. 1.2 Wiring
  3. 1.2 Program Design
  4. 1.3 Experiment

Hardware used: an STM32F103C8T6 minimum system board, an A4988 module, and a 42-series stepper motor (42BYGH39).

1.1 Introduction to the A4988

Introduction to the A4988 Introduction to the A4988 (2)

PinFunctionWiring
ENEnable input, active lowConnect to GND or MCU IOx1
MS1/2/3Step mode selectionLeave unconnected or use MCU IOx3
SLPSleep, active highShort to RST
STEPPulse input; one pulse produces one stepMCU IOx1
DIRDirection bit; 0/1 each represents a directionMCU IOx1
VMOT/GNDPower interface, 8~35V DC, maximum 2A12/24V power supply
1A/1B/2A/2BStepper motor wiringStepper motor
VDD/GNDConnect to the MCU’s 3.3V and GNDMCU power supply

1.2 Wiring

STM32 and USB-to-TTL

STM32USB-to-TTL
3.3V/5V3.3/5V
GNDGND
PA9RXD
PA10TXD

STM32 and A4988

STM32A4988
3.3V/5VVDD
GNDGND
PB6STEP (defined in motor.h)
PB7DIR (defined in motor.h)
Connect EN to GND
Connect SLP to RST

A4988 and the stepper motor

A4988Stepper motor
VMOT12V power supply +
GND12V power supply -
B2B-
A2B+
A1A+
B1A-

Pay attention to the phase sequence when wiring the stepper motor

On the A4988, the labels are 1A, 1B, 2A, and 2B. The numbers indicate the phase, while a and b indicate positive and negative.

On the stepper motor, the labels are A+, A-, B+, and B-. A and B indicate the phase, while + and - indicate positive and negative.

The corresponding wiring should therefore be: A+ and A- correspond to 1A and 1B, while B+ and B- correspond to 2A and 2B. For example, on my stepper motor, black is A+, green is A-, red is B+, and blue is B-. For the corresponding A4988 terminals B2 A2 A1 B1, the motor wire order is B- B+ A+ A- (blue-red-black-green).

Incorrect wiring may cause the motor to rotate in reverse or only vibrate without rotating.

1.2 Program Design

This program controls the stepper motor over the serial port. It is adapted from the development board’s serial-port example, with additional stepper motor driver functions.

The delay between GPIO transitions represents the speed. delay_ms(2) gives approximately 0.8s per revolution, while delay_ms(1) gives approximately 0.4s per revolution.

By default (full-step mode), one STEP pulse rotates the stepper motor by 90°.

//motor.h
#ifndef __MOTOR_H
#define __MOTOR_H	 
#include "delay.h"

//PF0-7,12-15

#define Motor_GPIO GPIOF				//PF
#define Motor_RCC RCC_APB2Periph_GPIOF
//第一个步进电机A4988的接线
#define Motor1_STEP	GPIO_Pin_1	//STEP - PF1
#define Motor1_DIR	GPIO_Pin_2	//DIR  - PF2
//第二个步进电机A4988的接线	//PB
#define Motor2_STEP	GPIO_Pin_3	//STEP - PF3
#define Motor2_DIR	GPIO_Pin_4	//DIR  - PF4

void MOTOR_Init(void);
void motor(unsigned int motor1_dir, unsigned int motor1_step, unsigned int motor2_dir, unsigned int motor2_step);



#endif
//motor.c
#include "motor.h"
/*GPIO_motornum和GPIOx用于选择电机,GPIO_direction用于选择电机方向,dir:0为逆1为正,k为90°的倍数*/
// GPIO

void MOTOR_Init()
{
	GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(Motor_RCC,ENABLE);
	
	//Motor初始化
	GPIO_InitStructure.GPIO_Pin = Motor1_STEP|Motor1_DIR|Motor2_STEP|Motor2_DIR;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(Motor_GPIO,&GPIO_InitStructure);	// 初始化GPIOB
	GPIO_ResetBits(Motor_GPIO,Motor1_STEP);			//初始化GPIOB_6输出低电平
	GPIO_ResetBits(Motor_GPIO,Motor1_DIR);			//初始化GPIOB_7输出低电平
	GPIO_ResetBits(Motor_GPIO,Motor2_STEP);			//初始化GPIOB_8输出低电平
	GPIO_ResetBits(Motor_GPIO,Motor2_DIR);			//初始化GPIOB_9输出低电平
}

void motor(unsigned int motor1_dir, unsigned int motor1_step, unsigned int motor2_dir, unsigned int motor2_step)
{
    unsigned int i;

		switch(motor1_dir)
		{
			case 0 : GPIO_SetBits(Motor_GPIO,Motor1_DIR); break; 
			case 1 : GPIO_ResetBits(Motor_GPIO,Motor1_DIR); break; 
			default : break; 
		}
		switch(motor2_dir)
		{
			case 0 : GPIO_SetBits(Motor_GPIO,Motor2_DIR); break; 
			case 1 : GPIO_ResetBits(Motor_GPIO,Motor2_DIR); break; 
			default : break; 
		}
		/*
		GPIO_SetBits(Motor_GPIO,Motor1_STEP);
		GPIO_SetBits(Motor_GPIO,Motor2_STEP);
		delay_ms(2);									//周期1.3ms
		GPIO_ResetBits(Motor_GPIO,Motor1_STEP);
		GPIO_ResetBits(Motor_GPIO,Motor2_STEP);
		delay_ms(2);
		*/
		for(i = 0;i < motor1_step || i < motor2_step; i++)
		{
			if(i<motor1_step)
			{
				GPIO_SetBits(Motor_GPIO,Motor1_STEP);
				delay_ms(2);									//周期1.3ms
				GPIO_ResetBits(Motor_GPIO,Motor1_STEP);
				delay_ms(2);
			}
			if(i<motor2_step)
			{
				GPIO_SetBits(Motor_GPIO,Motor2_STEP);
				delay_ms(2);									//周期1.3ms
				GPIO_ResetBits(Motor_GPIO,Motor2_STEP);
				delay_ms(2);
			}
		}

    //delay_ms(2);					//延时一会
}
//main.c
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "mbotLinuxUsart.h"//引用该头文件是使用,通信协议的前提
#include "motor.h"

#define IMAGE_WIDTH		640/2
#define IMAGE_HEIGHT	480/2

//测试发送变量
short testSend1   =1111;
short testSend2   =2222;
short testSend3   =3333;
unsigned char testSend4 = 0x05;

//测试接收变量
int testRece1     =400;
int testRece2     =300;
unsigned char testRece3 = 0x00;


int main(void)
{	
//=======================================变量定义=====================================================
	u8 dir1;
	u8 dir2;
	u16 step1;
	u16 step2;
//======================================硬件初始化====================================================
	delay_init();	    	                        //延时函数初始化	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组2
	uart_init(115200);	                            //串口初始化为115200
	MOTOR_Init();				 //初始化A4988驱动

//=======================================循环程序=====================================================
	while(1)
	{
		//将需要发送到ROS的数据,从该函数发出,前三个数据范围(-32768 - +32767),第四个数据的范围(0 - 255)
		usartSendData(testSend1,testSend2,testSend3,testSend4);
		if(testRece1>IMAGE_WIDTH)
		{
			dir1=1;
			step1=testRece1-IMAGE_WIDTH;
		}
		else
		{
			dir1=0;
			step1=IMAGE_WIDTH-testRece1;
		}
		if(testRece2>IMAGE_HEIGHT)
		{
			dir2=0;
			step2=testRece2-IMAGE_HEIGHT;
		}
		else
		{
			dir2=1;
			step2=IMAGE_HEIGHT-testRece2;
		}
		motor(dir1,step1,dir2,step2);
		//必须的延时
		delay_ms(13);
	} 
}

//====================================串口中断服务程序=================================================
void USART1_IRQHandler()
{
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
 	 {
		 USART_ClearITPendingBit(USART1,USART_IT_RXNE);//首先清除中断标志位
		 //从ROS接收到的数据,存放到下面三个变量中
		 usartReceiveOneData(&testRece1,&testRece2,&testRece3);
	 }
}
//===========================================END=======================================================

1.3 Experiment

The STM32 obtains the coordinates of the target center in the image from the ROS system. receiveData1 stores the target’s x value, while receiveData2 stores the target’s y value.

Because the ROS system continuously sends coordinate values, the STM32 receives data in real time for control. The A4988 uses 16× microstepping. Each drive operation (50 loops) steps 5.625°, or 0.1° per loop. Consider setting the step size for each command according to the target offset. For example, for each difference of 1 coordinate unit, add one 0.1° loop to each command.

Experiment