STM32 development project: stepping motor drive library

Project background

In the development of various projects, we often involve the control of stepping motor. Generally, the single chip microcomputer controls the stepping motor by operating the stepping motor driver or driving chip. Stepper motor drivers (chips) generally have three interfaces En, dir and pul. En is the enabling (or offline) signal of the stepping motor. At high level, the stepping motor will be powered off and offline. Dir is the steering signal of stepping motor. High level and low level represent forward rotation and reverse rotation. Pul is the pulse signal of stepper motor movement. Every time a pulse is received, the stepper motor runs one step (or a fine step).

Introduction to driver library

The stepping motor drive library mainly realizes the control of the above three signals of the stepping motor driver, and also encapsulates the three motion modes of motor inching, long motion and reciprocating motion. By abstracting the stepper motor package into a structure type, we can easily realize the motion control of multiple asynchronous stepper motors. At the same time, the application guide of this library function also gives the matching use routines of stepper motor and photocell.

Source code analysis

Header file

The structure type of stepper motor is defined in the header file. It is an abstraction of stepper motor (driver) control, which is independent of the platform. There is a description of each member in the code comments. In particular, void StepMotor_TryMove(StepMotor_Struct* StepMotor_P) is the core function of motor motion control. It is mainly responsible for realizing three motion modes of motor. This function needs to be called periodically in the update interrupt service function of the timer.

/*
 * stepmotor.h
 *
 *  Created on: 2020 August 31
 *      Author: Tao
 */

#ifndef SOURCE_ALWHALESLIB_HARDWARE_INC_STEPMOTOR_H_
#define SOURCE_ALWHALESLIB_HARDWARE_INC_STEPMOTOR_H_

#define USE_STEPMOTOR

#ifdef USE_STEPMOTOR

#include "stepmotor.h"
#include "stm32f10x_conf.h"

#define SETPMOTOR_NUM		4

/***Control pin mapping of stepping motor***/
#define STEPMOTOR_1_EN			GPIOB_OUT(15)
#define STEPMOTOR_1_DIR			GPIOB_OUT(13)
#define STEPMOTOR_1_PUL			GPIOB_OUT(14)

#define STEPMOTOR_2_EN			GPIOD_OUT(10)
#define STEPMOTOR_2_DIR			GPIOD_OUT(8)
#define STEPMOTOR_2_PUL			GPIOD_OUT(9)

#define STEPMOTOR_3_EN			GPIOD_OUT(13)
#define STEPMOTOR_3_DIR			GPIOD_OUT(11)
#define STEPMOTOR_3_PUL			GPIOD_OUT(12)

#define STEPMOTOR_4_EN			GPIOC_OUT(6)
#define STEPMOTOR_4_DIR			GPIOD_OUT(14)
#define STEPMOTOR_4_PUL			GPIOD_OUT(15)
/*******************************/


typedef void (*SetState_FP)(uint8_t state);
typedef void (*SetParam_FP)(uint32_t param);

/**
 * @brief Structure packaging of stepping motor
 * 			triggerCount Is the number of edges of the motor in one step, 1: single, i.e. level jump, 2: double, i.e. pulse
 * 			SetPulse It is a function pointer to drive the motor movement. Generally, it should be registered with a pointer to operate the GPIO port level
 * 			Generally, SetPulse will be called in the update interrupt service function of the timer. Each call will flip the port level
 * 			triggerCount = 1 Timer update frequency = stepper motor speed (step / s)
 * 			triggerCount = 2 Timer update frequency / 2 = stepper motor speed (step / s)
 *
 *			Generally, the movement of stepping motor is driven by timer. The start and stop of timer is the start and stop of motor, and the frequency of timer is the speed of motor
 * 			SetExec Set the function pointer of motor motion start and stop. Generally, a function that can open and close the drive timer should be registered for it
 * 			SetSpeed It is a function pointer to set the motor speed. Generally, it should be registered with a function that can set the update cycle of the drive timer
 */
typedef struct
{
	//Is the motor moving
	uint8_t IsRun;

	//Edge times of single step movement of motor (1: single, i.e. level jump, 2: double, i.e. pulse)
	uint8_t triggerNum;

	//Step count of motor operation
	uint32_t StepCount;

	//Motor cycle count (effective only when the operating mode is reciprocating)
	uint8_t LoopCount;

	//Motor set movement steps
	uint32_t StepSV;

	//Working mode of motor (0: inching, 1: reciprocating, 2: long-term)
	uint8_t WorkMode;

	//Hardware timer pointer for driving stepping motor,
	//This member is related to hardware. The main purpose of setting it is to facilitate the writing of processing functions
//	TIM_TypeDef* DriveTimer;

	//Set the function pointer of the active motor (after activating the motor, the motor will be locked, equivalent to power on)
	//Only active motors can be controlled
	SetState_FP SetEn;

	//Function pointer for setting motor movement direction (0: positive direction, 1: reverse direction, 2: turning direction)
	SetState_FP SetDir;

	//Function pointer of motor single step movement (0: low level, 1: high level, 2: flip level)
	SetState_FP SetPulse;

	//Function pointer for setting motor speed
	SetParam_FP SetSpeed;

	//Set the function pointer of motor motion start and stop
	SetState_FP SetExec;
} StepMotor_Struct;

extern StepMotor_Struct StepMotor[SETPMOTOR_NUM];

void StepMotor_Init();
void StepMotor_SetWorkMode(StepMotor_Struct* StepMotor_P, uint8_t mode);
void StepMotor_SetLoopCount(StepMotor_Struct* StepMotor_P, uint32_t loopCount);
void StepMotor_SetStep(StepMotor_Struct* StepMotor_P, uint32_t step);
void StepMotor_TryMove(StepMotor_Struct* StepMotor_P);

#endif
#endif /* SOURCE_ALWHALESLIB_HARDWARE_INC_STEPMOTOR_H_ */

source file

In the source file, the static function static void StepMotor_1_SetEn_Handler(uint8_t state),…,static void StepMotor_4_SetExec_Handler(uint8_t state) is platform related code, which is used to register function pointers of stepper motor structure members.

StepMotor_ The struct stepmotor [setpmotor_num] structure array is initialized directly when declared. Of course, you can also use void StepMotor_Init() function (not implemented in this source code) realizes the initialization of the above structure array. The platform related codes are mainly in static functions, which are the concrete implementation of abstract motor control.

After initializing the structure array, all the control of the stepping motor is expanded around the members of the operation structure. Of course, the members of the structure can be operated directly, but the author recommends using the encapsulated common stepper motor operation functions to control the stepper motor, such as void StepMotor_SetWorkMode(StepMotor_Struct* StepMotor_P, uint8_t mode),void StepMotor_SetStep(StepMotor_Struct* StepMotor_P, uint32_t step), etc.

/*
 * stepmotor.c
 *
 *  Created on: 2020 August 31
 *      Author: Tao
 */

#include "stepmotor.h"

#ifdef USE_STEPMOTOR

/**********************************/
static void StepMotor_1_SetEn_Handler(uint8_t state)
{
	STEPMOTOR_1_EN = state;
}

static void StepMotor_2_SetEn_Handler(uint8_t state)
{
	STEPMOTOR_2_EN = state;
}

static void StepMotor_3_SetEn_Handler(uint8_t state)
{
	STEPMOTOR_3_EN = state;
}

static void StepMotor_4_SetEn_Handler(uint8_t state)
{
	STEPMOTOR_4_EN = state;
}

/**********************************/
static void StepMotor_1_SetDir_Handler(uint8_t state)
{
	if(state < 2)
	{
		STEPMOTOR_1_DIR = state;
	}
	else
	{
		STEPMOTOR_1_DIR = ~STEPMOTOR_1_DIR;
	}
}

static void StepMotor_2_SetDir_Handler(uint8_t state)
{
	if(state < 2)
	{
		STEPMOTOR_2_DIR = state;
	}
	else
	{
		STEPMOTOR_2_DIR = ~STEPMOTOR_2_DIR;
	}
}

static void StepMotor_3_SetDir_Handler(uint8_t state)
{
	if(state < 2)
	{
		STEPMOTOR_3_DIR = state;
	}
	else
	{
		STEPMOTOR_3_DIR = ~STEPMOTOR_3_DIR;
	}
}

static void StepMotor_4_SetDir_Handler(uint8_t state)
{
	if(state < 2)
	{
		STEPMOTOR_4_DIR = state;
	}
	else
	{
		STEPMOTOR_4_DIR = ~STEPMOTOR_4_DIR;
	}
}

/**********************************/
static void StepMotor_1_SetPulse_Handler(uint8_t state)
{
	if(state < 2)
	{
		STEPMOTOR_1_PUL = state;
	}
	else
	{
		STEPMOTOR_1_PUL = ~STEPMOTOR_1_PUL;
	}
}

static void StepMotor_2_SetPulse_Handler(uint8_t state)
{
	if(state < 2)
	{
		STEPMOTOR_2_PUL = state;
	}
	else
	{
		STEPMOTOR_2_PUL = ~STEPMOTOR_2_PUL;
	}
}

static void StepMotor_3_SetPulse_Handler(uint8_t state)
{
	if(state < 2)
	{
		STEPMOTOR_3_PUL = state;
	}
	else
	{
		STEPMOTOR_3_PUL = ~STEPMOTOR_3_PUL;
	}
}

static void StepMotor_4_SetPulse_Handler(uint8_t state)
{
	if(state < 2)
	{
		STEPMOTOR_4_PUL = state;
	}
	else
	{
		STEPMOTOR_4_PUL = ~STEPMOTOR_4_PUL;
	}
}

/**********************************/
static void StepMotor_1_SetSpeed_Handler(uint32_t speed)
{
	speed = speed * StepMotor[0].triggerNum;

	//frequency < 1k, psc = 7200
	if (speed < 1000)
	{
		TIM5->PSC = 7200 - 1;
	}
	//frequency < 10k, psc = 720
	else if (speed < 10000)
	{
		TIM5->PSC = 720 - 1;
	}
	else
	{
		return;
	}

	//Set the update frequency of the timer.
	TIM5->ARR = 72000000.0 / (TIM5->PSC + 1) / speed - 1;

	return;
}

static void StepMotor_2_SetSpeed_Handler(uint32_t speed)
{
	speed = speed * StepMotor[1].triggerNum;

	//frequency < 1k, psc = 7200
	if (speed < 1000)
	{
		TIM6->PSC = 7200 - 1;
	}
	//frequency < 10k, psc = 720
	else if (speed < 10000)
	{
		TIM6->PSC = 720 - 1;
	}
	else
	{
		return;
	}

	//Set the update frequency of the timer.
	TIM6->ARR = 72000000.0 / (TIM6->PSC + 1) / speed - 1;

	return;
}

static void StepMotor_3_SetSpeed_Handler(uint32_t speed)
{
	speed = speed * StepMotor[2].triggerNum;

	//frequency < 1k, psc = 7200
	if (speed < 1000)
	{
		TIM7->PSC = 7200 - 1;
	}
	//frequency < 10k, psc = 720
	else if (speed < 10000)
	{
		TIM7->PSC = 720 - 1;
	}
	else
	{
		return;
	}

	//Set the update frequency of the timer.
	TIM7->ARR = 72000000.0 / (TIM7->PSC + 1) / speed - 1;

	return;
}

static void StepMotor_4_SetSpeed_Handler(uint32_t speed)
{
	speed = speed * StepMotor[3].triggerNum;

	//frequency < 1k, psc = 7200
	if (speed < 1000)
	{
		TIM8->PSC = 7200 - 1;
	}
	//frequency < 10k, psc = 720
	else if (speed < 10000)
	{
		TIM8->PSC = 720 - 1;
	}
	else
	{
		return;
	}

	//Set the update frequency of the timer.
	TIM8->ARR = 72000000.0 / (TIM8->PSC + 1) / speed - 1;

	return;
}

/**********************************/
static void StepMotor_1_SetExec_Handler(uint8_t state)
{
	TIM_Cmd(TIM5, state);
}

static void StepMotor_2_SetExec_Handler(uint8_t state)
{
	TIM_Cmd(TIM6, state);
}

static void StepMotor_3_SetExec_Handler(uint8_t state)
{
	TIM_Cmd(TIM7, state);
}

static void StepMotor_4_SetExec_Handler(uint8_t state)
{
	TIM_Cmd(TIM8, state);
}

StepMotor_Struct StepMotor[SETPMOTOR_NUM] =
{
		//Initialization of step motor 1
		{
				.IsRun = 0,
				.triggerNum = 2,
				.StepCount = 0,
				.LoopCount = 0,
				.StepSV = 100,
				.WorkMode = 0,

				.SetEn = StepMotor_1_SetEn_Handler,
				.SetDir = StepMotor_1_SetDir_Handler,
				.SetPulse = StepMotor_1_SetPulse_Handler,
				.SetSpeed = StepMotor_1_SetSpeed_Handler,
				.SetExec = StepMotor_1_SetExec_Handler,
		},

		//Initialization of step motor 2
		{
				.IsRun = 0,
				.triggerNum = 2,
				.StepCount = 0,
				.LoopCount = 0,
				.StepSV = 100,
				.WorkMode = 0,

				.SetEn = StepMotor_2_SetEn_Handler,
				.SetDir = StepMotor_2_SetDir_Handler,
				.SetPulse = StepMotor_2_SetPulse_Handler,
				.SetSpeed = StepMotor_2_SetSpeed_Handler,
				.SetExec = StepMotor_2_SetExec_Handler,
		},

		//Initialization of step motor 3
		{
				.IsRun = 0,
				.triggerNum = 2,
				.StepCount = 0,
				.LoopCount = 0,
				.StepSV = 100,
				.WorkMode = 0,

				.SetEn = StepMotor_3_SetEn_Handler,
				.SetDir = StepMotor_3_SetDir_Handler,
				.SetPulse = StepMotor_3_SetPulse_Handler,
				.SetSpeed = StepMotor_3_SetSpeed_Handler,
				.SetExec = StepMotor_3_SetExec_Handler,
		},

		//Initialization of step motor 4
		{
				.IsRun = 0,
				.triggerNum = 2,
				.StepCount = 0,
				.LoopCount = 0,
				.StepSV = 100,
				.WorkMode = 0,

				.SetEn = StepMotor_4_SetEn_Handler,
				.SetDir = StepMotor_4_SetDir_Handler,
				.SetPulse = StepMotor_4_SetPulse_Handler,
				.SetSpeed = StepMotor_4_SetSpeed_Handler,
				.SetExec = StepMotor_4_SetExec_Handler,
		},
};


/**
 * @brief Complete the initialization of stepping motor
 */
void StepMotor_Init()
{

}


/**
 * @brief Sets the number of motion steps of the stepper motor
 * 			The relationship between the number of motion steps and the internal stepcount and stepsv mainly depends on the trigger num, that is, how many times the motor is triggered to actually run one step.
 * 			In the form of driving signal, i.e. single edge trigger (triggerNum = 1, jump signal) or double edge trigger (triggerNum = 2, pulse signal)
 * 	@param StepMotor_P: Stepper motor structure pointer
 * 	@param step: Motor movement steps
 */
void StepMotor_SetStep(StepMotor_Struct* StepMotor_P, uint32_t step)
{
	StepMotor_P->StepSV = step * StepMotor_P->triggerNum;
	StepMotor_P->StepCount = StepMotor_P->StepSV;
}


/**
 * @brief Set the working mode of the stepper motor
 * @param StepMotor_P: Stepper motor structure pointer
 * @param mode: Motor operating mode
 * 		@arg 0: Inching
 * 		@arg 1: Reciprocate
 * 		@arg 2: Long movement
 */
void StepMotor_SetWorkMode(StepMotor_Struct* StepMotor_P, uint8_t mode)
{
	StepMotor_P->WorkMode = mode;
}

/**
 * @brief Sets the number of cycles of the stepper motor
 * @param StepMotor_P: Stepper motor structure pointer
 * @param loopCount: Number of motor cycles (effective only when the working mode is reciprocating)
 */
void StepMotor_SetLoopCount(StepMotor_Struct* StepMotor_P, uint32_t loopCount)
{
	StepMotor_P->LoopCount = loopCount;
}

/**
 * @brief This function is called periodically in the update interrupt service function of the timer
 * @param StepMotor_P: Stepper motor structure pointer
 * 			It should be noted that the SetSpeed and SetExec pointers of the incoming stepper motor structure depend on the drive timer
 * 			It should be consistent with the drive timer calling this function, otherwise an error will occur
 */
void StepMotor_TryMove(StepMotor_Struct* StepMotor_P)
{
	//Normal operating mode
	if (StepMotor_P->WorkMode == 0)
	{
		if (StepMotor_P->StepCount != 0)
		{
			//Flip primary pulse port level
			StepMotor_P->SetPulse(2);
			StepMotor_P->StepCount--;
		}
		else
		{
			//Stop stepper motor
			StepMotor_P->SetExec(0);
			StepMotor_P->IsRun = 0;
		}
	}
	//Reciprocating working mode
	else if (StepMotor_P->WorkMode == 1)
	{
		if (StepMotor_P->LoopCount != 0)
		{
			if (StepMotor_P->StepCount != 0)
			{
				StepMotor_P->SetPulse(2);
				StepMotor_P->StepCount--;
			}
			else
			{
				StepMotor_P->LoopCount--;
				StepMotor_P->StepCount = StepMotor_P->StepSV;
				//Flip direction
				StepMotor_P->SetDir(2);
			}
		}
		else
		{
			StepMotor_P->SetExec(0);
			StepMotor_P->IsRun = 0;
		}
	}
	//Continuous working mode
	else if (StepMotor_P->WorkMode == 2)
	{
		//Flip primary pulse port level
		StepMotor_P->SetPulse(2);
	}
	else
	{

	}
}


#endif

Application Guide

  1. Implement the callback function of each function pointer (SetState_FP SetEn,SetState_FP SetDir,SetState_FP SetPulse,SetParam_FP SetSpeed,SetState_FP SetExec,) in the structure member according to the hardware platform. These callback functions either operate the level output of GPIO, or control the frequency and start and stop of hardware timer. Take STM32F103 platform as an example:
//Callback function of SetEn
static void StepMotor_1_SetEn_Handler(uint8_t state)
{
	STEPMOTOR_1_EN = state;
}

//Callback function of SetDir
static void StepMotor_1_SetDir_Handler(uint8_t state)
{
	if(state < 2)
	{
		STEPMOTOR_1_DIR = state;
	}
	else
	{
		STEPMOTOR_1_DIR = ~STEPMOTOR_1_DIR;
	}
}

//Callback function of SetPulse
static void StepMotor_1_SetPulse_Handler(uint8_t state)
{
	if(state < 2)
	{
		STEPMOTOR_1_PUL = state;
	}
	else
	{
		STEPMOTOR_1_PUL = ~STEPMOTOR_1_PUL;
	}
}

//Callback function of SetSpeed
static void StepMotor_1_SetSpeed_Handler(uint32_t speed)
{
	speed = speed * StepMotor[0].triggerNum;

	//frequency < 1k, psc = 7200
	if (speed < 1000)
	{
		TIM5->PSC = 7200 - 1;
	}
	//frequency < 10k, psc = 720
	else if (speed < 10000)
	{
		TIM5->PSC = 720 - 1;
	}
	else
	{
		return;
	}

	//Set the update frequency of the timer.
	TIM5->ARR = 72000000.0 / (TIM5->PSC + 1) / speed - 1;

	return;
}

//Callback function of SetExec
static void StepMotor_1_SetExec_Handler(uint8_t state)
{
	TIM_Cmd(TIM5, state);
}

  1. Initialize the stepper motor structure variable (array). You can initialize the structure variable (array) directly when declaring, or you can use void stepmotor_ The init() function initializes structural variables (arrays).
StepMotor_Struct StepMotor[SETPMOTOR_NUM] =
{
		//Initialization of step motor 1
		{
				.IsRun = 0,
				.triggerNum = 2,
				.StepCount = 0,
				.LoopCount = 0,
				.StepSV = 100,
				.WorkMode = 0,

				.SetEn = StepMotor_1_SetEn_Handler,
				.SetDir = StepMotor_1_SetDir_Handler,
				.SetPulse = StepMotor_1_SetPulse_Handler,
				.SetSpeed = StepMotor_1_SetSpeed_Handler,
				.SetExec = StepMotor_1_SetExec_Handler,
		},

		//Initialization of step motor 2
		{
				.IsRun = 0,
				.triggerNum = 2,
				.StepCount = 0,
				.LoopCount = 0,
				.StepSV = 100,
				.WorkMode = 0,

				.SetEn = StepMotor_2_SetEn_Handler,
				.SetDir = StepMotor_2_SetDir_Handler,
				.SetPulse = StepMotor_2_SetPulse_Handler,
				.SetSpeed = StepMotor_2_SetSpeed_Handler,
				.SetExec = StepMotor_2_SetExec_Handler,
		},

		//Initialization of step motor 3
		{
				.IsRun = 0,
				.triggerNum = 2,
				.StepCount = 0,
				.LoopCount = 0,
				.StepSV = 100,
				.WorkMode = 0,

				.SetEn = StepMotor_3_SetEn_Handler,
				.SetDir = StepMotor_3_SetDir_Handler,
				.SetPulse = StepMotor_3_SetPulse_Handler,
				.SetSpeed = StepMotor_3_SetSpeed_Handler,
				.SetExec = StepMotor_3_SetExec_Handler,
		},

		//Initialization of step motor 4
		{
				.IsRun = 0,
				.triggerNum = 2,
				.StepCount = 0,
				.LoopCount = 0,
				.StepSV = 100,
				.WorkMode = 0,

				.SetEn = StepMotor_4_SetEn_Handler,
				.SetDir = StepMotor_4_SetDir_Handler,
				.SetPulse = StepMotor_4_SetPulse_Handler,
				.SetSpeed = StepMotor_4_SetSpeed_Handler,
				.SetExec = StepMotor_4_SetExec_Handler,
		},
};
  1. Configure the timer relied on in the callback function of the control function at the appropriate position of the project, and configure the update interrupt of the timer
void Timer_Config()
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);

	TIM_DeInit(TIM5);
	TIM_TimeBaseInitStructure.TIM_Prescaler = TIM5_Prescaler - 1;
	TIM_TimeBaseInitStructure.TIM_Period = TIM5_Period - 1;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM5, &TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM5, TIM_FLAG_Update);
	TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);
	//	TIM_ARRPreloadConfig(TIM5, ENABLE);
}


void NVIC_Config()
{
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

	//Timer5 is used for drive step motor 1.
	NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}
  1. Call void stepmotor in the update interrupt service function of the timer_ TryMove(StepMotor_Struct* StepMotor_P).
void TIM5_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM5,TIM_IT_Update)!=RESET)
	{
		StepMotor_TryMove(&StepMotor[0]);
		
		TIM_ClearFlag(TIM5,TIM_FLAG_Update);
		TIM_ClearITPendingBit(TIM5,TIM_IT_Update);
	}
}

  1. Set the starting parameters of the motor and start the motor.
void StepMotor_RunM1(void)
{
	//Set motion parameters
	StepMotor_SetStep(&StepMotor[0], 1200);
	StepMotor_SetWorkMode(&StepMotor[0], 1);
	StepMotor_SetLoopCount(&StepMotor[0], 50);
	StepMotor[0].SetSpeed(3000);

	//Start the motor and set the flag bit
	StepMotor[0].SetExec(1);
	StepMotor[0].IsRun = 1;
}
  1. To stop the motor, it is usually called in the external interrupt service function triggered by the photocell.
void StepMotor_StopM1(void)
{
	//Stop the motor and set the flag bit
	StepMotor[0].SetExec(0);
	StepMotor[0].IsRun = 0;
	StepMotor[0].StepCount = 0;
}
  1. Special note 1: when calling the stop motor function in the external interrupt service function triggered by the photocell, attention should be paid to software filtering to eliminate jitter, or the motor can be turned off after appropriate delay to get rid of the critical point triggered by the photocell.
void EXTI0_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line0) != RESET)
	{
		//Delay to eliminate jitter
		delay_ms(1);
		
		if(MOTOR_LIMIT_SWITCH_1_1 == 0)
		{
			//Stop motor 1
			StepMotor[0].SetExec(0);
			StepMotor[0].IsRun = 0;
			StepMotor[0].StepCount = 0;
		}
		
		EXTI_ClearITPendingBit(EXTI_Line0);
	}
}
  1. Special note 2: after triggering the photocell, the motor needs directional protection to restart and cannot continue to move in the original direction, otherwise the motor will be out of control because the photocell cannot be triggered again. The judgment of photocell status can be added to the business code controlling the start and stop of motor:
void StepMotor_RunM1(void)
{
	//Set motion parameters
	StepMotor_SetStep(&StepMotor[0], 1200);
	StepMotor_SetWorkMode(&StepMotor[0], 1);
	StepMotor_SetLoopCount(&StepMotor[0], 50);
	StepMotor[0].SetSpeed(3000);

	if((MOTOR_LIMIT_SWITCH_1_1 ==0) &&(STEPMOTOR_1_DIR == 0))
	{
		return;
	}
	else if((MOTOR_LIMIT_SWITCH_1_2 ==0) &&(STEPMOTOR_1_DIR == 1))
	{
		return;
	}
	else
	{
		//Start the motor and set the flag bit
		StepMotor[0].SetExec(1);
		StepMotor[0].IsRun = 1;
	}
}

Posted by timecatcher on Wed, 18 May 2022 15:16:55 +0300