STM32 control stepper motor: closed-loop stepper motor drive based on HAL library timer interrupt + precise control of pulse number

1. Stepper motor closed-loop driver

The stepper motor closed-loop driver used in this article is the Emm42_V4.0 stepper motor closed-loop driver. The closed-loop driver has its own FOC vector closed-loop control algorithm, which can realize three-loop control of torque, speed and position.
As shown in the figure below, the A+, A-, B+, and B- of the 42-step closed-loop motor driver are connected to the stepper motor, and the stepper motor is driven and controlled through the enable, pulse, and direction terminals on the right.

Two, CubeMx configuration

Clock configuration is required first.

1、Clock Configuration

insert image description here
Before configuring the clock, you must first open the RCC in Pinout & Configuration, select Crystal/Ceramic Resonator to open the external crystal oscillator.
Then set the parameters according to the external crystal oscillator frequency of your microcontroller, as shown in the figure below.
insert image description here

2. Pulse terminal timer configuration

Go back to Pinout & Configuration again, select a timer you want in Timers, here I choose timer 2, and then turn on the internal clock (Clock Source: Internal Clock).
Configure the channel function as PWM output (PWM Generation). Here I used 4 stepper motors, so 4 channels were selected. (The following video only demonstrates a stepper motor, and the same is true for other stepper motors. The wiring and supplementary program will be ok.)
Then open the NVIC Settings to enable the timer interrupt. As shown below.
insert image description here
Next, set the frequency of the timer according to the clock you set in the previous step and the frequency your drive can carry.
For example, the maximum pulse frequency of the driver I use is 120KHZ, and the maximum speed is 2200+ revolutions, that is, if I want to achieve the highest speed, I can configure a stepper motor with a step angle of 1.8° to be 16 subdivisions, that is, (360 ÷ 1.8) × 16 = 3200 pulses for one revolution ( the number of control pulses will be mentioned below), and then use 120K ÷ 3200 = 37.5 revolutions/s, that is, 2250 revolutions per minute. As shown in the figure below, my tim2 belongs to APB1, and the clock setting is 84MHZ.
insert image description here
The microcontroller I use is STM32F407, so the APB1 bus here corresponds to the general timers tim2 ~ 5, the basic timers tim6, tim7, and the general timers tim12 ~ 14. The APB2 bus corresponds to advanced timers tim1, tim8, and general-purpose timers tim9 ~ 11.
So be careful not to misuse the APB1 timer clock frequency as the APB2 clock frequency .
Therefore, taking my configuration as an example, use 84M ÷ 120K = 700, and then use this 700 to allocate the prescaler coefficient and counting period, as shown in the figure below. Here, for the convenience of setting the PWM duty cycle later, the counting period is set to 100, then the PSC is 7.
Formula: PWM output frequency = timer clock frequency ÷ ((psc+1) × (arr + 1)).
insert image description here

Use an oscilloscope to check if there is any problem with the frequency and waveform. The program used here will be described in detail below, with a duty cycle of 50% and a frequency of 120KHZ.
insert image description here

3. Enable and direction terminal pin configuration

As shown in the figure below, left-click the pin you want to use to configure it as an output, which is very simple. Here I use PC0-4 as the enable terminal and PG0-4 as the direction terminal. You can choose the pins that will not occupy the functions you need as simple high and low level output pins according to your needs.
insert image description here
Then enter the Project Manager to configure the project name and compilation environment, generate .c, .h files, etc., and it will be ok.

Three, STM32F407 timer interrupt control stepper motor program

First put the pin configuration diagram, the program looks a little clearer.

0. Pin configuration diagram

The pin configuration is shown below.
insert image description here

1. The HAL library function used

The function of these two functions will be explained below.

HAL_TIM_PWM_Stop(&htimx,TIM_CHANNEL_x);
HAL_TIM_PWM_Start(&htimx,TIM_CHANNEL_x);

2. Pulse trigger timer initialization configuration

In the project generated by CubeMx, you only need to find the initialization program according to the previously set timer, and then add the following program at the end of the program, but you need to configure the parameters according to the timer and channel you configure . If it is set to timer 2, just press Ctrl F to search for MX_TIM2_Init.

// 添加程序
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_3);
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);

The HAL_TIM_PWM_Start function is a function to start the PWM output, which corresponds to the 4 channels of timer 2 as shown above. The following is the initial modified initialization function I generated based on the HAL library. The sConfigOC is proposed for the convenience of writing the PWM setting function below. Both steps are necessary.

/* ============================== 步进电机脉冲触发定时器初始化 ============================== */

TIM_HandleTypeDef htim2;
TIM_OC_InitTypeDef Motor_PWM_sConfigOC = {
    
    0};

/* TIM2 init function */
void Motor_PWM_MX_TIM2_Init(void)
{
    
    

  TIM_ClockConfigTypeDef sClockSourceConfig = {
    
    0};
  TIM_MasterConfigTypeDef sMasterConfig = {
    
    0};

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 7-1;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 100-1;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    
    
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    
    
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    
    
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    
    
    Error_Handler();
  }
  Motor_PWM_sConfigOC.OCMode = TIM_OCMODE_PWM1;
  Motor_PWM_sConfigOC.Pulse = 0;
  Motor_PWM_sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  Motor_PWM_sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &Motor_PWM_sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    
    
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &Motor_PWM_sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    
    
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &Motor_PWM_sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    
    
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &Motor_PWM_sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    
    
    Error_Handler();
  }

  HAL_TIM_MspPostInit(&htim2);
	
  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_3);
  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);

}

3. Stepping motor pulse setting

As shown below, take stepping motor 1 as an example, first stop the PWM output of channel 1 of timer 2, then set the duty cycle, configure the channel and turn on the PWM again. HAL_TIM_PWM_Stop is a function to stop the PWM output of timer x channel x.

void Motor1_pwm_Set(int motor1_n)
{
    
    
   HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
   Motor_PWM_sConfigOC.Pulse = motor1_n;
   HAL_TIM_PWM_ConfigChannel(&htim2, &Motor_PWM_sConfigOC, TIM_CHANNEL_1);
   HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}

4. Enable, disable and change the direction of the stepper motor

As shown below, configure the high and low levels.

void Motor1_enable(void)			// 电机1使能
{
    
    
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);
}
void Motor1_disable(void)			// 电机1失能
{
    
    
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);
}
void Motor1_course(char course_mod)			// 电机1改变方向
{
    
    
	if(course_mod == 1){
    
    HAL_GPIO_WritePin(GPIOG, GPIO_PIN_0, GPIO_PIN_SET);}		// 正转
	else if(course_mod == 0){
    
    HAL_GPIO_WritePin(GPIOG, GPIO_PIN_0, GPIO_PIN_RESET);}			// 反转
}

5. Stepping motor forward rotation main.c program

Start the stepper motor 1, set the duty cycle to 50%, and rotate forward.

int main(void)
{
    
    
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
	Motor_PWM_MX_TIM2_Init();
	Motor_PWM_MX_TIM2_Init();	// 定时器初始化

	Motor1_pwm_Set(50);		// 设置占空比为50%(50/100)
	Motor1_course(1);		// 正转
	Motor1_enable();		// 使能
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */
}

6. Demonstration of video effects

stepper motor control

4. Closed-loop stepper motor accurately controls the number of pulses

1. The HAL library function used

Similarly, the functions of these three functions will be explained below.

HAL_TIM_PWM_Start_IT(&htimx, TIM_CHANNEL_x);
HAL_TIM_PWM_Stop_IT(&htimx, TIM_CHANNEL_x);
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim);

2. Change the stepper motor drive pulse frequency

First, set the number of subdivision steps of the stepper motor to 16, as shown in the figure below, a stepper motor with a step angle of 1.8° is used here. With this parameter configuration, 16 pulses are sent to rotate 1.8°, so the pulses required to make one revolution are (360° ÷ 1.8°) × 16 = 3200 pulses.
insert image description here
Based on the stepper motor driver above, I want to change the speed to about 5 revolutions/s, so we should change the pulse frequency to 120KHZ. Using the above-mentioned 3200 pulses per revolution, then 16000 pulses are required for 5 revolutions, so change 120KHZ to 16KHZ. Then calculate the PSC again, which is (84M ÷ 16K) ÷ 100 = 52.5.
Change the PSC in the above stepper motor pulse trigger timer initialization Motor_PWM_MX_TIM2_Init to 53:

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 53-1;

At the same time, the previous HAL_TIM_PWM_Start() function should be deleted, that is, the following program should be deleted:

  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_3);
  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);

3. Change the stepper motor pulse setting program

Because we no longer use HAL_TIM_PWM_Start and HAL_TIM_PWM_Stop, these two functions should also be deleted when changing the program. Take stepping motor 1 as an example, change to the following program:

void Motor1_pwm_Set(int motor1_n)
{
    
    
   Motor_PWM_sConfigOC.Pulse = motor1_n;
   HAL_TIM_PWM_ConfigChannel(&htim2, &Motor_PWM_sConfigOC, TIM_CHANNEL_1);
}

Of course, it is worth noting that the function we defined now does not have a program to stop PWM, so we must remember to call HAL_TIM_PWM_Stop_IT to turn off the timer output PWM before changing the PWM .

4. Timer PWM interrupt callback function

Before using the timer interrupt, remember to redefine the timer callback function in your program.
Optionally add the following program to your stm32f4xx_it.c:

/* USER CODE BEGIN 1 */
int PWM_num = 0;	// 脉冲数
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
    
    
	if(htim->Instance == htim2.Instance)	// 确认是否为步进电机脉冲中断的回调
	{
    
    
		PWM_num ++;
		if(PWM_num >= 3200)		// 第3200次(一圈)
		{
    
    
			PWM_num = 0;
			HAL_TIM_PWM_Stop_IT(&htim2, TIM_CHANNEL_1);		// 停止输出PWM
			//HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10);		// 翻转led灯电平 
		}
	}
}
/* USER CODE END 1 */

In the above program, you can see that PWM_num is accumulating, and it will be accumulated once every time the callback function is called. We will call the HAL_TIM_PWM_Start_IT function once in the main function. You can guess it by guessing. The purpose of this function is to enable the timer to output PWM. And the callback function is called every time a pulse is sent .
As shown in the figure below, the function HAL library pointed to by the arrow has been written for us, and it will call our above-mentioned interrupt callback function.
insert image description here

5. The stepper motor rotates one circle forward and the closed-loop main.c program

The following is the main function program:

int main(void)
{
    
    
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
	Motor_PWM_MX_TIM2_Init();
	
	Motor1_pwm_Set(50);
	HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_1);
	Motor1_course(1);
	Motor1_enable();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

6. Demonstration of video effects

Closed-loop stepper motor - precise control of pulse number

5. Program link

The program has been packaged and uploaded to the resources of csdn.
CSDN: HAL library STM32F407 timer interrupt control stepper motor program
CSDN: HAL library STM32F407 timer interrupt control closed-loop stepper motor precise control pulse number
can also be downloaded through the following link:

STM32F407 timer interrupt control stepper motor program :
link: https://pan.baidu.com/s/1svRzVW_7elkHg7wwQ4AN5A
extraction code: hpzq
STM32F407 timer interrupt control closed-loop stepper motor precision control pulse number :
link: https://pan .baidu.com/s/1QIyusKAbusqyMl_VTkjKxg
Extraction code: 4rml

I am a student and I am currently studying. This article can be regarded as my study notes. Please correct me if I am wrong.

Guess you like

Origin blog.csdn.net/xztli/article/details/127179256