STM32 controls multiple stepping motors: based on the HAL library single timer multi-channel interrupt precise control of the number of pulses + multi-timer single-channel interrupt precise control of the number of pulses


The previous article realized the closed-loop stepper motor drive based on the HAL library timer interrupt, and used the timer interrupt callback to realize the precise control of the stepper motor pulse number.
The principle and method of controlling multiple stepper motors are the same as those of a single stepper motor. It was introduced in the previous article, but there may be some problems in the implementation, so I plan to record it in this blog. Avoid stepping on the pit in the future.

Hardware used:
MCU: STM32F407ZGT6
stepper motor driver: Emm42_V4.0 stepper motor closed-loop driver
Stepper motor: 42 stepper motors
(plus power board and model aircraft battery)

1. Directly control multiple stepper motors

If you directly control multiple stepper motors, you only need to master the control method of the stepper motor driver.
If you want to know, you can jump directly to the previous article: STM32 control stepper motor: closed-loop stepper motor drive based on HAL library timer interrupt + precise control of pulse number .
The CubeMx configuration and program analysis are recorded in the linked article, and the code for controlling 4 stepper motors is attached. In the third part of the article, the STM32F407 timer interrupt control stepper motor program has the analysis of the main initialization program and logic program.

2. Single timer multi-channel interrupt precise control of pulse number

The effect achieved by the program is that the 4 stepper motors rotate at the same time, and stop after turning one circle every 3 seconds.

1. CubeMx configuration, single-turn pulse number and other issues

The single-timer multi-channel CubeMx configuration is the same as the previous article, so I won’t go into details here, and the link is above.
In addition, the calculation of the number of pulses required for one revolution of the stepper motor , timer initialization , enablement of the stepper motor, pulse, and direction function design are also analyzed in detail in the previous article.

2. Main program

Inheriting the program of the previous article 4. The closed-loop stepper motor accurately controls the number of pulses , and the interrupt callback function is modified. It should be noted here that I changed the basis of the timer judgment to channel judgment. If other timers are used, a precondition for judging the timer can be added before the channel judgment, that is,

if(htim->Instance == htim2.Instance)	// 确认是否为步进电机脉冲中断的回调。

Just write the channel judgment and internal logic program into this judgment condition.

Interrupt callback function program:

/* ============================== 步进电机PWM中断回调函数 ============================== */
int Motor1_PWM_num = 0;		// 电机1当前脉冲数
int Motor2_PWM_num = 0;		// 电机2当前脉冲数
int Motor3_PWM_num = 0;		// 电机3当前脉冲数
int Motor4_PWM_num = 0;		// 电机4当前脉冲数

int road_PWM_num = 3200 * 1;	// 步进电机目标脉冲数(一圈3200脉冲)

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
    
    
	if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)	// 通道1
	{
    
    
		Motor1_PWM_num ++;
		if(Motor1_PWM_num >= road_PWM_num)
		{
    
    
			Motor1_PWM_num = 0;	// 跑完目标圈数了,重置当前值
			HAL_TIM_PWM_Stop_IT(&htim2, TIM_CHANNEL_1);	// 停止输出PWM
			//HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10);	// 点灯(调试用的,不管)
		}
	}
	if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)	// 通道2
	{
    
    
		Motor2_PWM_num ++;
		if(Motor2_PWM_num >= road_PWM_num)
		{
    
    
			Motor2_PWM_num = 0;	// 跑完目标圈数了,重置当前值
			HAL_TIM_PWM_Stop_IT(&htim2, TIM_CHANNEL_2);	// 停止输出PWM
			//HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10);	// 点灯(调试用的,不管)
		}
	}
	if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)	// 通道3
	{
    
    
		Motor3_PWM_num ++;
		if(Motor3_PWM_num >= road_PWM_num)
		{
    
    
			Motor3_PWM_num = 0;	// 跑完目标圈数了,重置当前值
			HAL_TIM_PWM_Stop_IT(&htim2, TIM_CHANNEL_3);	// 停止输出PWM
			//HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10);	// 点灯(调试用的,不管)
		}
	}
	if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4)	// 通道4
	{
    
    
		Motor4_PWM_num ++;
		if(Motor4_PWM_num >= road_PWM_num)
		{
    
    
			Motor4_PWM_num = 0;	// 跑完目标圈数了,重置当前值
			HAL_TIM_PWM_Stop_IT(&htim2, TIM_CHANNEL_4);	// 停止输出PWM
			//HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10);	// 点灯(调试用的,不管)
		}
	}
}

Main program:
After the timer is initialized, I gave the microcontroller a 1s delay. If the stepper motor is directly driven without delay at this moment, some stepper motors may not be able to be woken up, so this delay is necessary. of. The functions realized by the program are mentioned above, and the program is as follows.

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();		// 定时器2初始化
	
  HAL_Delay(1000);		// 必须存在的延时,可长不可太短

  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
	Motor1_pwm_Set(50);
	HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_1);
	Motor1_course(1);
	Motor1_enable();

	Motor2_pwm_Set(50);
	HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_2);
	Motor2_course(1);
	Motor2_enable();

	Motor3_pwm_Set(50);
	HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_3);
	Motor3_course(1);
	Motor3_enable();

	Motor4_pwm_Set(50);
	HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_4);
	Motor4_course(1);
	Motor4_enable();

	HAL_Delay(3000);
  }
  /* USER CODE END 3 */
}

3. Multi-timer single-channel interrupt precisely controls the number of pulses

1. CubeMx configuration

The timer configuration is as follows:
insert image description hereinsert image description here
the configurations of timers 2, 3, 4, and 5 are the same, as shown in the figure above.
Also remember to turn on the external crystal oscillator:
insert image description here

The clock number configuration is as follows:
insert image description here
Then configure the pin high level output:
insert image description here insert image description hereinsert image description here
complete!

2. Program design idea and main program

Multi-timer single-channel realization of multi-stepping motor precise control pulse number is different from the above method, we do not use the PWM interrupt callback function of HAL_TIM_PWM_PulseFinishedCallback, but the interrupt callback function of the TIM timer count overflow of HAL_TIM_PeriodElapsedCallback.
This method uses the principle of timer to generate PWM, that is, each count after prescaler corresponds to a PWM square wave, that is to say, every time I send a pulse, a count overflow will occur, so in the case where this timer is used to generate PWM Down,Number of counter overflows = number of pulses. The timer initialization configuration of this method needs to clear the flag
after initialization , that is, add the following code:

__HAL_TIM_CLEAR_IT(&htimx, TIM_IT_UPDATE);	// 清空标志位
// htimx对应下文中的htim2、htim3、htim4、htim5

There are 4 timers in total, and the flag bits of 4 timers need to be added to clear.
Similarly, the start and stop functions of the timer interrupt must be replaced by the following two functions:

HAL_TIM_Base_Start_IT(&htimx);	// 中断开启
HAL_TIM_Base_Stop_IT(&htimx);	// 中断停止
// htimx对应下文中的htim2、htim3、htim4、htim5

Interrupt callback function program:

/* ============================== 步进电机PWM中断回调函数 ============================== */
int Motor1_PWM_num = 0;		// 电机1当前脉冲数
int Motor2_PWM_num = 0;		// 电机2当前脉冲数
int Motor3_PWM_num = 0;		// 电机3当前脉冲数
int Motor4_PWM_num = 0;		// 电机4当前脉冲数

int road_PWM_num = 3200 * 1;	// 步进电机目标脉冲数(一圈3200脉冲)

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    
    
	if(htim->Instance == TIM2)	// 定时器2(步进电机1PWM)
	{
    
    
		Motor1_PWM_num ++;
		if(Motor1_PWM_num >= road_PWM_num)
		{
    
    
			Motor1_PWM_num = 0;
			HAL_TIM_Base_Stop_IT(&htim2);
			HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);	// 停止输出PWM
			//HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10);	// 点灯(调试用的,不管)
		}
	}
	if(htim->Instance == TIM3)	// 定时器3(步进电机2PWM)
	{
    
    
		Motor2_PWM_num ++;
		if(Motor2_PWM_num >= road_PWM_num)
		{
    
    
			Motor2_PWM_num = 0;
			HAL_TIM_Base_Stop_IT(&htim3);
			HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);	// 停止输出PWM
			//HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10);	// 点灯(调试用的,不管)
		}
	}
	if(htim->Instance == TIM4)	// 定时器4(步进电机3PWM)
	{
    
    
		Motor3_PWM_num ++;
		if(Motor3_PWM_num >= road_PWM_num)
		{
    
    
			Motor3_PWM_num = 0;
			HAL_TIM_Base_Stop_IT(&htim4);
			HAL_TIM_PWM_Stop(&htim4, TIM_CHANNEL_1);	// 停止输出PWM
			//HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10);	// 点灯(调试用的,不管)
		}
	}
	if(htim->Instance == TIM5)	// 定时器5(步进电机4PWM)
	{
    
    
		Motor4_PWM_num ++;
		if(Motor4_PWM_num >= road_PWM_num)
		{
    
    
			Motor4_PWM_num = 0;
			HAL_TIM_Base_Stop_IT(&htim5);
			HAL_TIM_PWM_Stop(&htim5, TIM_CHANNEL_1);	// 停止输出PWM
			//HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10);	// 点灯(调试用的,不管)
		}
	}
}

Before writing the main function, you need to modify the stepper motor PWM setting function, taking stepper motor 1 as an example:

/* ============================== 步进电机脉冲设置 ============================== */

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

Main program:
Similarly, a small delay should be added after initialization to prevent the stepper motor from failing to activate.
The function realized by the program is the same as that of single timer multi-channel, the stepper motor rotates precisely one circle within 3 seconds and then stops, and the cycle continues.

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 */
  Motor1_TIM2_Init();
  Motor2_TIM3_Init();
  Motor3_TIM4_Init();
  Motor4_TIM5_Init();

  HAL_Delay(1000);
  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
		Motor1_pwm_Set(50);
		HAL_TIM_Base_Start_IT(&htim2);
		HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
		Motor1_enable();
		
		Motor2_pwm_Set(50);
		HAL_TIM_Base_Start_IT(&htim3);
		HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
		Motor2_course(1);
		Motor2_enable();
		
		Motor3_pwm_Set(50);
		HAL_TIM_Base_Start_IT(&htim4);
		HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1);
		Motor3_course(1);
		Motor3_enable();
		
		Motor4_pwm_Set(50);
		HAL_TIM_Base_Start_IT(&htim5);
		HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_1);
		Motor4_course(1);
		Motor4_enable();
		
		HAL_Delay(3000);
  }
  /* USER CODE END 3 */
}

4. Program link

The program has been packaged and uploaded to the resources of csdn.
CSDN: Based on the HAL library, the single-timer multi-channel interrupt accurately controls the number of pulses (4 stepper motors)
CSDN: The multi-timer single-channel interrupt based on the HAL library precisely controls the number of pulses (4 stepper motors)
can also be passed through the following Link to download:

Single-timer multi-channel interrupt precise control pulse number based on HAL library (4 stepper motors):
link: https://pan.baidu.com/s/1uQG8ll_PjbqnKCArs-p0lQ
Extraction code: 8rdk
multi-timer based on HAL library Single-channel interrupt precise control of pulse number (4 stepper motors):
Link: https://pan.baidu.com/s/1tYNfGQKdSbJEK-Tf7GAb9A
Extraction code: du7b

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/127201347
Recommended