c++ - 编译和 SPI 电机驱动器屏蔽单独工作——但不能一起工作

标签 c++ motordriver

我使用的是 STM32F767 MCU 以及两个扩展板:IHM02A1 双步进电机驱动器。我还没有调试器,但我的公司正在准备一个...

与此同时,我一直在取消/注释掉部分 Mbed 代码。他们的 Hello World 程序可以从这个网站获得,点击“导入程序”可以直接在他们的在线 IDE 中使用:https://os.mbed.com/components/X-NUCLEO-IHM02A1/

#include "mbed.h"
#include "DevSPI.h"
#include "XNucleoIHM02A1.h"

#define MPR_1 4 /* Number of movements per revolution. */

#define STEPS_1 (200 * 128)   /* 1 revolution given a 200 steps motor configured at 1/128 microstep mode. */
#define STEPS_2 (STEPS_1 * 2)

/* Delay in milliseconds. */
#define DELAY_1 1000
#define DELAY_2 2000
#define DELAY_3 3000

/* Motor Control Expansion Board. */
XNucleoIHM02A1 *x_nucleo_ihm02a1;
XNucleoIHM02A1 *x_nucleo_ihm02a1two;

/* Initialization parameters of the motors connected to the expansion board. */
L6470_init_t init[L6470DAISYCHAINSIZE] = {
    /* First Motor. */
    {
        24.0,                          /* Motor supply voltage in V. */
        200,                           /* Min number of steps per revolution for the motor. */
        1.7,                           /* Max motor phase voltage in A. */
        3.06,                          /* Max motor phase voltage in V. */
        300.0,                         /* Motor initial speed [step/s]. */
        500.0,                         /* Motor acceleration [step/s^2] (comment for infinite acceleration mode). */
        500.0,                         /* Motor deceleration [step/s^2] (comment for infinite deceleration mode). */
        992.0,                         /* Motor maximum speed [step/s]. */
        0.0,                           /* Motor minimum speed [step/s]. */
        602.7,                         /* Motor full-step speed threshold [step/s]. */
        3.06,                          /* Holding kval [V]. */
        3.06,                          /* Constant speed kval [V]. */
        3.06,                          /* Acceleration starting kval [V]. */
        3.06,                          /* Deceleration starting kval [V]. */
        61.52,                         /* Intersect speed for bemf compensation curve slope changing [step/s]. */
        392.1569e-6,                   /* Start slope [s/step]. */
        643.1372e-6,                   /* Acceleration final slope [s/step]. */
        643.1372e-6,                   /* Deceleration final slope [s/step]. */
        0,                             /* Thermal compensation factor (range [0, 15]). */
        3.06 * 1000 * 1.10,            /* Ocd threshold [ma] (range [375 ma, 6000 ma]). */
        3.06 * 1000 * 1.00,            /* Stall threshold [ma] (range [31.25 ma, 4000 ma]). */
        StepperMotor::STEP_MODE_1_128, /* Step mode selection. */
        0xFF,                          /* Alarm conditions enable. */
        0x2E88                         /* Ic configuration. */
    },

    /* Second Motor. */
    {
        24.0,                           /* Motor supply voltage in V. */
        200,                           /* Min number of steps per revolution for the motor. */
        1.7,                           /* Max motor phase voltage in A. */
        3.06,                          /* Max motor phase voltage in V. */
        300.0,                         /* Motor initial speed [step/s]. */
        500.0,                         /* Motor acceleration [step/s^2] (comment for infinite acceleration mode). */
        500.0,                         /* Motor deceleration [step/s^2] (comment for infinite deceleration mode). */
        992.0,                         /* Motor maximum speed [step/s]. */
        0.0,                           /* Motor minimum speed [step/s]. */
        602.7,                         /* Motor full-step speed threshold [step/s]. */
        3.06,                          /* Holding kval [V]. */
        3.06,                          /* Constant speed kval [V]. */
        3.06,                          /* Acceleration starting kval [V]. */
        3.06,                          /* Deceleration starting kval [V]. */
        61.52,                         /* Intersect speed for bemf compensation curve slope changing [step/s]. */
        392.1569e-6,                   /* Start slope [s/step]. */
        643.1372e-6,                   /* Acceleration final slope [s/step]. */
        643.1372e-6,                   /* Deceleration final slope [s/step]. */
        0,                             /* Thermal compensation factor (range [0, 15]). */
        3.06 * 1000 * 1.10,            /* Ocd threshold [ma] (range [375 ma, 6000 ma]). */
        3.06 * 1000 * 1.00,            /* Stall threshold [ma] (range [31.25 ma, 4000 ma]). */
        StepperMotor::STEP_MODE_1_128, /* Step mode selection. */
        0xFF,                          /* Alarm conditions enable. */
        0x2E88                         /* Ic configuration. */
    }
};

int main()
{
    /* Initializing SPI bus. */
#ifdef TARGET_STM32F429
    DevSPI dev_spi(D11, D12, D13);

#else
    DevSPI dev_spi(D11, D12, D13);
#endif

    /* Initializing Motor Control Expansion Board. */
    x_nucleo_ihm02a1 =    new XNucleoIHM02A1(&init[0], &init[1], A4, A5, D4, D2, &dev_spi);
    x_nucleo_ihm02a1two = new XNucleoIHM02A1(&init[0], &init[1], A4, A5, D4, A2, &dev_spi);  

    /* Building a list of motor control components. */
    L6470 **motors = x_nucleo_ihm02a1->get_components();
    L6470 **motorstwo = x_nucleo_ihm02a1two->get_components();

    /* Setting the home position. */
    //motorstwo[1]->set_home();
//    wait_ms(DELAY_1);
    int position = motorstwo[1]->get_position();
    wait_ms(DELAY_1);

//      motors[1]->move(StepperMotor::FWD, STEPS_2);
//      motors[0]->move(StepperMotor::FWD, STEPS_2);    
//    wait_ms(DELAY_2);
      motorstwo[1]->move(StepperMotor::FWD, STEPS_2);
      motorstwo[0]->move(StepperMotor::FWD, STEPS_2);

    position = motorstwo[1]->get_position();
    wait_ms(DELAY_1); 

}

这是完整程序的最小可重现示例。如果您想自己尝试一下,只需将其复制/粘贴到 main.cpp 中(在上面提到的在线 IDE 中)。

一切都符合要求,没有警告。下面的任何一行(及其匹配的指针等)都是通过移动电机来工作的。即,motorstwo[x] 和 motors[x] 都自行运行。但是当两条线都加载到电路板上时......没有任何作用,电机不会移动。步进器甚至不会发出非常柔和的声音。

x_nucleo_ihm02a1 =    new XNucleoIHM02A1(&init[0], &init[1], A4, A5, D4, D2, &dev_spi);
x_nucleo_ihm02a1two = new XNucleoIHM02A1(&init[0], &init[1], A4, A5, D4, A2, &dev_spi);

为什么这两行不能一起上传呢?如何解决?


编辑

该类包括“XNucleoIHM02A1”的两个函数。有七个周长的那个是要剖析的……倒数第二个参数听起来要改变 (sel:) enter image description here

查看 Nucleo 原理图,您会注意到 L6470_1_SDO(串行数据输出)连接到 L6470_0_SDI(串行数据输入)。这是菊花链配置。还要注意桥接 SB7 如何连接到电路板上的 D2 引脚。

enter image description here

查看零件数据表,当/CS为低电平时,它会开始读取数据,并会一直移出数据,直到/CS为高电平。

enter image description here

通过堆叠第二 block 板,可以得到这种配置——它是上述菊花链和单独寻址版本的组合:

enter image description here


硬件文档

Short datasheet . Long datasheet .

最佳答案

你说你有两个盾牌?每个盾牌上都有一个 IHM02A1 驱动程序吗?请详细说明...

如果是这种情况,您可以使用相同的 SPI 总线,但每个屏蔽需要单独的片选线。

我不是 Arduino 用户,所以我不太熟悉他们的驱动程序。我下载了示例项目并快速浏览了一下:

对于 IHM02A1 类,构造函数如下所示:

XNucleoIHM02A1(L6470_init_t *init_0, L6470_init_t *init_1, uint8_t flag_irq, uint8_t busy_irq, uint8_t standby_reset, uint8_t ssel, SPIClass *spi);

其中参数有如下说明:

/**
 * @brief Constructor.
 * @param init_0        pointer to the initialization structure of the first motor.
 * @param init_1        pointer to the initialization structure of the second motor.
 * @param flag_irq      pin name of the FLAG pin of the component.
 * @param busy_irq      pin name of the BUSY pin of the component.
 * @param standby_reset pin name of the STBY\RST pin of the component.
 * @param ssel          pin name of the SSEL pin of the SPI device to be used for communication.
 * @param spi           SPI device to be used for communication.
 */

第6个参数是选择引脚。这是您必须为每个屏蔽指定选择引脚的地方。

然后您将需要 XNucleoIHM02A1 类的两个实例,每个防护罩一个。它不是每个电机的实例。该类(class)已经为两个电机做好了准备。

XNucleoIHM02A1 *x_nucleo_ihm02a1_shield1; // Class for shield 1
XNucleoIHM02A1 *x_nucleo_ihm02a1_shield2; // Class for shield 2

x_nucleo_ihm02a1_shield1 = new XNucleoIHM02A1(&init[0], &init[1], FLAG1, BUSY1, STBY_RST1, SS1, &dev_spi);
x_nucleo_ihm02a1_shield2 = new XNucleoIHM02A1(&init[0], &init[1], FLAG2, BUSY2, STBY_RST2, SS2, &dev_spi);

其中 SS1 和 SS2 是片选引脚。注意:您必须用实际的 PIN 码填写这些内容。

您还必须确保正确定义其余参数。您很可能需要为每个屏蔽的 FLAG、BUSY 和 STBY/RST 单独的引脚。因此我定义了参数,FLAG1,FLAG2,BUSY1,BUSY2,STBY_RST1,STBY_RST2。注意:您必须用实际的 PIN 码填写这些内容。

附录:

如果您需要为每个电机设置不同的参数,那么您将需要四种不同的初始化结构:

L6470_init_t init_shield1[L6470DAISYCHAINSIZE] = {...};
L6470_init_t init_shield2[L6470DAISYCHAINSIZE] = {...};

x_nucleo_ihm02a1_shield1 = new XNucleoIHM02A1(&init_shield1[0], &init_shield1[1], FLAG1, BUSY1, STBY_RST1, SS1, &dev_spi);
x_nucleo_ihm02a1_shield2 = new XNucleoIHM02A1(&init_shield2[0], &init_shield2[1], FLAG2, BUSY2, STBY_RST2, SS2, &dev_spi);

但是如果所有的电机都有相同的参数和/或要求,那么你只需要一个初始化结构

L6470_init_t init[L6470DAISYCHAINSIZE] = {...};

x_nucleo_ihm02a1_shield1 = new XNucleoIHM02A1(&init[0], &init[1], FLAG1, BUSY1, STBY_RST1, SS1, &dev_spi);
x_nucleo_ihm02a1_shield2 = new XNucleoIHM02A1(&init[0], &init[1], FLAG2, BUSY2, STBY_RST2, SS2, &dev_spi);

您需要为每个盾牌调用“get_components”:

// For easier reading
#define L6470_S1M1 (0u) // Index of shield1 motor1
#define L6470_S1M2 (1u) // Index of shield1 motor2
#define L6470_S2M1 (0u) // Index of shield2 motor1
#define L6470_S2M2 (1u) // Index of shield2 motor2

L6470 **motors_shield1 = x_nucleo_ihm02a1_shield1->get_components();
L6470 **motors_shield2 = x_nucleo_ihm02a1_shield2->get_components();

然后按以下方式操作电机:

motors_shield1[L6470_S1M1]->set_home(); // Home motor1 on shield1
motors_shield1[L6470_S1M2]->set_home(); // Home motor2 on shield1
motors_shield2[L6470_S2M1]->set_home(); // Home motor1 on shield2
motors_shield2[L6470_S2M2]->set_home(); // Home motor2 on shield2

关于c++ - 编译和 SPI 电机驱动器屏蔽单独工作——但不能一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57434935/

相关文章:

c++ - 具有递归继承和使用声明的可变参数模板

c++ - 使用 4 个 16 位定时器实现 400hz PWM

c++ - 通过 USB 命令步进电机 Controller

c - 步进电机控制时序

c++ - 构建 .dll 时出现问题 (Visual C++)

c++ - 钻石层次结构中的低落

c++ - 使用 C++ 处理 firefox 错误消息 “Cannot load XPCOM”

java - 返回字符串的函数的 C++ 执行顺序