下面是我编写的 motordriver.c 代码。我的目标是执行一个特定场景,有时需要 3-4 个电机同时运行。我使用案例结构安排了这个场景。例如:
case 1200:
X_MotorSet(1, 40, 200, 14000, backward);
B_MotorSet(1, 40, 200, 2500, forward);
在这种情况下,我希望X和B电机同时运行。代码中的参数如下(从土耳其语翻译成英语):min_speed、max_speed、ramp、target、direction。
但是,该软件无法按预期运行。首先,X电机运行,完成后,B电机启动。我怎样才能防止这种情况发生?我真正想要的是 X 电机迈出一步,然后 B 电机迈出一步,依此类推,交替它们的运动。
你能帮我解决这个问题吗?我的代码中缺少什么吗?我怎样才能通过案例结构实现这一点?
/*
* MotorDriver.c
*
* Created on: Jan 11, 2023
* Author: ARGE
*/
#include "stm32f4xx.h"
#include "main.h"
#include "MotorDriver.h"
#include "RelayDriver.h"
#include "SPI_Transfer.h"
#include "Tarifler.h"
extern struct MotorName_t MotorName;
extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim2;
extern TIM_HandleTypeDef htim3;
void MotorDriver_Init(){
HAL_TIM_Base_Start_IT(&htim1);
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_Base_Start_IT(&htim3);
HAL_GPIO_WritePin(EN_X_GPIO_Port, EN_X_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(EN_Y_GPIO_Port, EN_Y_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(EN_A_GPIO_Port, EN_A_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(EN_B_GPIO_Port, EN_B_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CS_X_GPIO_Port, CS_X_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CS_Y_GPIO_Port, CS_Y_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CS_A_GPIO_Port, CS_A_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CS_B_GPIO_Port, CS_B_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CS_X_GPIO_Port, CS_X_Pin, GPIO_PIN_RESET);
ConfigDriver(XMotor, CS_X_GPIO_Port, CS_X_Pin);
HAL_GPIO_WritePin(CS_X_GPIO_Port, CS_X_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CS_Y_GPIO_Port, CS_Y_Pin, GPIO_PIN_RESET);
ConfigDriver(YMotor, CS_Y_GPIO_Port, CS_Y_Pin);
HAL_GPIO_WritePin(CS_Y_GPIO_Port, CS_Y_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CS_A_GPIO_Port, CS_A_Pin, GPIO_PIN_RESET);
ConfigDriver(AMotor, CS_A_GPIO_Port, CS_A_Pin);
HAL_GPIO_WritePin(CS_A_GPIO_Port, CS_A_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CS_B_GPIO_Port, CS_B_Pin, GPIO_PIN_RESET);
ConfigDriver(BMotor, CS_B_GPIO_Port, CS_B_Pin);
HAL_GPIO_WritePin(CS_B_GPIO_Port, CS_B_Pin, GPIO_PIN_SET);
}
//Motor Yonlerinde bir farklılık olduğunda senaryo ve sw konumları ile ilgili
//guncellemeye gereksinim bırakmaması için bu kısımdan değiştirilmelidir.
void MotorYon(uint8_t MotorNo, uint8_t Yon) {
switch (MotorNo) {
case XMotor:
if (Yon == geri)
HAL_GPIO_WritePin(DIR_X_GPIO_Port, DIR_X_Pin, GPIO_PIN_SET);
else if (Yon == ileri)
HAL_GPIO_WritePin(DIR_X_GPIO_Port, DIR_X_Pin, GPIO_PIN_RESET);
MotorName.X[yon] = Yon;
break;
case YMotor:
if (Yon == ileri)
HAL_GPIO_WritePin(DIR_Y_GPIO_Port, DIR_Y_Pin, GPIO_PIN_RESET);
else if (Yon == geri)
HAL_GPIO_WritePin(DIR_Y_GPIO_Port, DIR_Y_Pin, GPIO_PIN_SET);
MotorName.Y[yon] = Yon;
break;
case AMotor:
if (Yon == geri)
HAL_GPIO_WritePin(DIR_A_GPIO_Port, DIR_A_Pin, GPIO_PIN_SET);
else if (Yon == ileri)
HAL_GPIO_WritePin(DIR_A_GPIO_Port, DIR_A_Pin, GPIO_PIN_RESET);
MotorName.A[yon] = Yon;
break;
case BMotor:
if (Yon == ileri)
HAL_GPIO_WritePin(DIR_B_GPIO_Port, DIR_B_Pin, GPIO_PIN_SET);
else if (Yon == geri)
HAL_GPIO_WritePin(DIR_B_GPIO_Port, DIR_B_Pin, GPIO_PIN_RESET);
MotorName.B[yon] = Yon;
break;
}
}
void MotorEnable(int MotorNo, int Durum) {
switch (MotorNo) {
case XMotor:
if (Durum == ac)
HAL_GPIO_WritePin(EN_X_GPIO_Port, EN_X_Pin, GPIO_PIN_RESET);
else if (Durum == kapat)
HAL_GPIO_WritePin(EN_X_GPIO_Port, EN_X_Pin, GPIO_PIN_SET);
break;
case YMotor:
if (Durum == ac)
HAL_GPIO_WritePin(EN_Y_GPIO_Port, EN_Y_Pin, GPIO_PIN_RESET);
else if (Durum == kapat)
HAL_GPIO_WritePin(EN_Y_GPIO_Port, EN_Y_Pin, GPIO_PIN_SET);
break;
case AMotor:
if (Durum == ac)
HAL_GPIO_WritePin(EN_A_GPIO_Port, EN_A_Pin, GPIO_PIN_RESET);
else if (Durum == kapat)
HAL_GPIO_WritePin(EN_A_GPIO_Port, EN_A_Pin, GPIO_PIN_SET);
break;
case BMotor:
if (Durum == ac)
HAL_GPIO_WritePin(EN_B_GPIO_Port, EN_B_Pin, GPIO_PIN_RESET);
else if (Durum == kapat)
HAL_GPIO_WritePin(EN_B_GPIO_Port, EN_B_Pin, GPIO_PIN_SET);
break;
}
}
/*
rampa:1-500 arasında; 500 rampa fazla, 1 düşük rampa
min_hiz:1
max_hiz:1-100 arasında
motor_hedef:1-2.147483648 step adımı arasında
*/
void Ramp(int32_t Motor[6]){
if(Motor[rampa]>200){
Motor[rampa]-=(500/Motor[rampa]);//1 er 1 er veya 2şer azalt//Gecikme Azalır, Hız artar
delay_us(MotorName.X[rampa]);
}
else if(Motor[rampa]>20 && Motor[rampa]<200){
Motor[rampa]-=(1000/Motor[rampa]);//20Ms olana kadar hız artar
delay_us(Motor[rampa]);
}
else{//4000/40 = 10Ms maksimum hıza ayarlanmış olur.
Motor[rampa] = 4000/Motor[max_hiz];//max hız min gecikme
delay_us(Motor[rampa]);
}
}
void X_MotorDrive() {
while(MotorName.X[motor_konum] <= MotorName.X[motor_hedef]){
HAL_GPIO_TogglePin(STEP_X_GPIO_Port, STEP_X_Pin); //motor_hiz,motor_pulse,motor_konum,max_hiz,yon,rampa_egim
MotorName.X[motor_konum]++;
Ramp(MotorName.X);//Çağrılan motor parametreleriyle rampa hesaplanarak burada gecikme sağlanır.
}
HAL_GPIO_WritePin(EN_X_GPIO_Port, EN_X_Pin, GPIO_PIN_SET);
}
void Y_MotorDrive() {
while (MotorName.Y[motor_konum] <= MotorName.Y[motor_hedef]) {
HAL_GPIO_TogglePin(STEP_Y_GPIO_Port, STEP_Y_Pin); //motor_hiz,motor_pulse,motor_konum,max_hiz,yon,rampa_egim
MotorName.Y[motor_konum]++;
Ramp(MotorName.Y);//Çağrılan motor parametreleriyle rampa hesaplanarak burada gecikme sağlanır.
}
HAL_GPIO_WritePin(EN_Y_GPIO_Port, EN_Y_Pin, GPIO_PIN_SET);
}
//***************************************************************
void A_MotorDrive() {
while (MotorName.A[motor_konum] <= MotorName.A[motor_hedef]) {
HAL_GPIO_TogglePin(STEP_A_GPIO_Port, STEP_A_Pin); //motor_hiz,motor_pulse,motor_konum,max_hiz,yon,rampa_egim
MotorName.A[motor_konum]++;
Ramp(MotorName.A);//Çağrılan motor parametreleriyle rampa hesaplanarak burada gecikme sağlanır.
}
HAL_GPIO_WritePin(EN_A_GPIO_Port, EN_A_Pin, GPIO_PIN_SET);
}
void B_MotorDrive() {
while (MotorName.B[motor_konum] <= MotorName.B[motor_hedef]) {
HAL_GPIO_TogglePin(STEP_B_GPIO_Port, STEP_B_Pin); //motor_hiz,motor_pulse,motor_konum,max_hiz,yon,rampa_egim
MotorName.B[motor_konum]++;
Ramp(MotorName.B);//Çağrılan motor parametreleriyle rampa hesaplanarak burada gecikme sağlanır.
}
HAL_GPIO_WritePin(EN_B_GPIO_Port, EN_B_Pin, GPIO_PIN_SET);
}
void X_MotorSet(int32_t Min_Hiz, int32_t Max_Hiz, int32_t Rampa, int32_t Mesafe, uint8_t Yon) {
if (HAL_GPIO_ReadPin(LIMIT_X_GPIO_Port, LIMIT_X_Pin) == 0 && Yon == ileri) {
MotorName.Home[XMotor] = HomeYapildi;
} else {
MotorName.X[rampa] = Rampa;
MotorName.X[min_hiz] = Min_Hiz;
MotorName.X[max_hiz] = Max_Hiz;
MotorName.X[motor_hedef] = Mesafe;
MotorName.X[motor_konum] = 1;
MotorYon(XMotor, Yon);
MotorEnable(XMotor, ac);
X_MotorDrive();
}
}
void Y_MotorSet(int32_t Min_Hiz, int32_t Max_Hiz, int32_t Rampa, int32_t Mesafe, uint8_t Yon) {
if (HAL_GPIO_ReadPin(LIMIT_Y_GPIO_Port, LIMIT_Y_Pin) == 1 && Yon == ileri){
MotorName.Home[YMotor] = HomeYapildi;
} else {
MotorName.Y[rampa] = Rampa;
MotorName.Y[min_hiz] = Min_Hiz;
MotorName.Y[max_hiz] = Max_Hiz;
MotorName.Y[motor_hedef] = Mesafe;
MotorName.Y[motor_konum] = 1;
MotorYon(YMotor, Yon);
MotorEnable(YMotor, ac);
Y_MotorDrive();
}
}
//***************************************************************************
void A_MotorSet(int32_t Min_Hiz, int32_t Max_Hiz, int32_t Rampa, int32_t Mesafe, uint8_t Yon) {
if (HAL_GPIO_ReadPin(LIMIT_A_GPIO_Port, LIMIT_A_Pin) == 1 && Yon == ileri){
MotorName.Home[AMotor] = HomeYapildi;
} else {
MotorName.A[rampa] = Rampa;
MotorName.A[min_hiz] = Min_Hiz;
MotorName.A[max_hiz] = Max_Hiz;
MotorName.A[motor_hedef] = Mesafe;
MotorName.A[motor_konum] = 1;
MotorYon(AMotor, Yon);
MotorEnable(AMotor, ac);
A_MotorDrive();
}
}
void B_MotorSet(int32_t Min_Hiz, int32_t Max_Hiz, int32_t Rampa, int32_t Mesafe, uint8_t Yon) {
if (HAL_GPIO_ReadPin(LIMIT_B_GPIO_Port, LIMIT_B_Pin) == 1 && Yon == geri){
MotorName.Home[BMotor] = HomeYapildi;
} else {
MotorName.B[rampa] = Rampa;
MotorName.B[min_hiz] = Min_Hiz;
MotorName.B[max_hiz] = Max_Hiz;
MotorName.B[motor_hedef] = Mesafe;
MotorName.B[motor_konum] = 1;
MotorYon(BMotor, Yon);
MotorEnable(BMotor, ac);
B_MotorDrive();
}
}
//***************************************************************************
//****************************************************************************
我使用案例结构实现了该场景,其中多个电机配置为同时运行。例如:
case 1200:
X_MotorSet(1, 40, 200, 14000, backward);
B_MotorSet(1, 40, 200, 2500, forward);
我预计 X 和 B 电机会交替移动,一个电机迈出一步,然后另一个电机迈出一步。然而,实际上,软件按顺序执行命令,X 电机在 B 电机启动之前完成其整个运动。我期望两个电机交替或交错其步骤。
我期望两个电机交替或交错其步骤。
我使用案例结构实现了该场景,其中多个 电机配置为同时运行。例如:
case 1200:
X_MotorSet(1, 40, 200, 14000, backward);
B_MotorSet(1, 40, 200, 2500, forward);
执行第一个函数,然后执行第二个函数。这里没有什么是平行的。
您需要(如果您想要主循环)编写只做一件事而没有任何延迟的函数,并检查下一步要做什么。但等不及下一阶段了。
你需要实现这样一个非阻塞状态机。