STM32F4 多电机带外壳

问题描述 投票:0回答:1

下面是我编写的 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 电机启动之前完成其整个运动。我期望两个电机交替或交错其步骤。

c arm stm32 stm32cubeide
1个回答
0
投票

我期望两个电机交替或交错其步骤。

我使用案例结构实现了该场景,其中多个 电机配置为同时运行。例如:

case 1200:
    X_MotorSet(1, 40, 200, 14000, backward);
    B_MotorSet(1, 40, 200, 2500, forward);

执行第一个函数,然后执行第二个函数。这里没有什么是平行的。

您需要(如果您想要主循环)编写只做一件事而没有任何延迟的函数,并检查下一步要做什么。但等不及下一阶段了。

你需要实现这样一个非阻塞状态机。

© www.soinside.com 2019 - 2024. All rights reserved.