使用指针迭代 AccelStepper 实例数组 (Arduino)

Using pointers to iterate over an array of AccelStepper instances (Arduino)

我正在为 Arduino 设备编写步进电机设备。在我的头文件中,我声明了 AccelStepper 库的实例。稍后我想使用指针数组迭代步进器。我发现这些实例有不同的地址。你能解释一下这里出了什么问题并提示我如何解决这个问题吗?

文件: bender.h

typedef char arg_t[32];    // string type with defined length for passing args from cmd line to the methods
class Bender
{
    public:
        Bender();
        int init(arg_t []);
        int feed(arg_t []);
                int setStepperMaxSpeed(arg_t []);
    private:
        char strbuf[128];
        AccelStepper feederStepper;
        AccelStepper rotationStepper;
        AccelStepper benderStepper;
        AccelStepper *steppers[3];
        arg_t stepperNames[3];
        float stepperMaxSpeeds[3]; 
        MessageControl msg_h; 
        int _setBenderPin(int);
        int _setStpMaxSpd(int, float);
};

文件 bender.cpp


#include <settings.h>
#include "BenderControl.h"
#include <Arduino.h>

Bender::Bender()
{
    sprintf(strbuf, "MESSAGE 1: &feederStepper=%p", &feederStepper);
    msg_h.say(strbuf, L_ALWAYS);
    AccelStepper feederStepper(1, P_FEED_STEP, P_FEED_DIR); // (Type:driver, STEP, DIR)
    AccelStepper rotationStepper(1, P_ROT_STEP, P_ROT_DIR);
    AccelStepper benderStepper(1, P_BEND_STEP, P_BEND_DIR);
    steppers[0] = &feederStepper;
    steppers[1] = &rotationStepper;
    steppers[2] = &benderStepper;
    sprintf(strbuf, "MESSAGE 2: &feederStepper=%p", &feederStepper);
    msg_h.say(strbuf, L_ALWAYS);
    stepperMaxSpeeds[0] = (float)FEEDER_MAX_SPEED;
    stepperMaxSpeeds[1] = (float)BENDER_MAX_SPEED;
    stepperMaxSpeeds[2] = (float)ROTATION_MAX_SPEED;
    strcpy(stepperNames[0], "feed");
    strcpy(stepperNames[1], "bend");
    strcpy(stepperNames[2], "rot");

    benderServo.attach(P_SERVO);
}

int Bender::init(arg_t args[])
{
    int result = -1;
    msg_h.say("Bender initializing\n", L_INFO);    
    result = _setStpMaxSpd(0, stepperMaxSpeeds[0]);
/*will evaluate result later, work in progress here*/
    _setStpMaxSpd(1, stepperMaxSpeeds[1]);
    _setStpMaxSpd(2, stepperMaxSpeeds[2]);
    msg_h.say("Bender initialized\n", L_INFO);    
    return 0;
}


int Bender::_setStpMaxSpd(int idx, float val)
{
    //sprintf(strbuf, "PRIVATE _setStpMaxSpd set to ");
    //dtostrf(val, 4,1, &strbuf[strlen(strbuf)]);
    //strncat(strbuf, "\n", 2);
    //msg_h.say(strbuf, L_INFO);
    //delay(50);
    int ret = -1;
    sprintf(strbuf, "MESSAGE3: &feederstepper %p\n", &feederStepper);
    msg_h.say(strbuf, L_INFO);
    sprintf(strbuf, "MESSAGE4: &benderstepper %p\n", &benderStepper);
    msg_h.say(strbuf, L_INFO);
    sprintf(strbuf, "MESSAGE5: &rotationstepper %p\n", &rotationStepper);
    msg_h.say(strbuf, L_INFO);
    sprintf(strbuf, "MESSAGE6: steppers[idx] %p\n", steppers[idx]);
    msg_h.say(strbuf, L_INFO);
    delay(100);
    //feederStepper.setMaxSpeed(val);
    steppers[idx]->setMaxSpeed(val);
    delay(100);
    float maxs = steppers[idx]->maxSpeed();
    
    sprintf(strbuf, "Setpoint / real value: ");
    dtostrf((double)val, 4,2, &strbuf[strlen(strbuf)]);
    strncat(strbuf, " / ", 3);
    dtostrf((double)maxs, 4,2, &strbuf[strlen(strbuf)]);
    strncat(strbuf, "\n", 2);
    msg_h.say(strbuf, L_INFO);
    delay(50);

    if (abs(maxs - val) > 0.01)
    {
        msg_h.say("SET FAIL", L_INFO);
        sprintf(strbuf, "Could not set max speed of stepper %s to ", stepperNames[idx]);
        dtostrf(val, 4,1, &strbuf[strlen(strbuf)]);
        strncat(strbuf, "\n", 2);
        msg_h.say(strbuf, L_ERROR);
        ret = -1;
    }
    else
    {
        sprintf(strbuf, "Stepper %s max speed = ", stepperNames[idx]);
        dtostrf(maxs, 4, 1, &strbuf[strlen(strbuf)]);
        strncat(strbuf, "\n", 2);
        msg_h.say(strbuf, L_INFO);
        ret = 0;
        delay(50);

    }
    return ret;

}



请忽略 msg_h.say() 方法,它只是一个 Serial.print 取决于调试级别。

我希望 feederStepper 的地址保持不变,但实际上我得到了不同的地址。 我用 MESSAGE x 前缀标记了输出行。 从 MSG1 到 MSG2,地址不同。是什么原因?我期望 bender.h 中的声明保留地址(并保留)。

输出:


MESSAGE1: &feederStepper=0x1e11 
MESSAGE2: &feederStepper=0x21aa // why has the address changed here?
MESSAGE3: &feederstepper 0x1e11 // and why is here the old address from MSG1?
MESSAGE4: &benderstepper 0x1e99
MESSAGE5: &rotationstepper 0x1e55
MESSAGE6: steppers[idx] 0x21aa 

我的程序中是否可能有两个 feederStepper(和其他步进器)实例?解决这个问题的正确方法是什么? 我应该在 bender.h 文件中的声明处初始化指针数组吗?

干杯,斯特凡

在 user17732522 的评论后编辑: 这样做是否正确:

//file: bender.h
//...
    AccelStepper *steppers[3];
//...

//file: bender.cpp
//...
    steppers[0] = &AccelStepper(1, P_FEED_STEP, P_FEED_DIR); 
    steppers[1] = &AccelStepper(1, P_BEND_STEP, P_BEND_DIR); 
    steppers[2] = &AccelStepper(1, P_ROT_STEP, P_ROT_DIR); 
//...

这个解决方案更好吗?

是的,您正在声明多个 AccelStepper 对象。要创建指向步进电机对象的指针数组,如上所述,您可以从 Bender Class 中完全删除对象,并且 保存三个指向数组中的对象。例如:

#define FEED_IDX 0
#define ROT_IDX 1
#define BEND_IDX 2

    steppers[FEED_IDX] = new AccelStepper(1, P_FEED_STEP, P_FEED_DIR);
    steppers[ROT_IDX] = new AccelStepper(1, P_ROT_STEP, P_ROT_DIR);
    steppers[BEND_IDX] = new AccelStepper(1, P_BEND_STEP, P_BEND_DIR);

那么在代码中使用_IDX常量来区分就可以了

如果您想将三个对象保留在 Bender 对象中,另一种方法是完全删除 Bender 构造函数中的步进电机声明,并添加一个 初始化程序列表 到设置三个步进器的构造函数。代码应如下所示:

Bender::Bender() :
    // initializer list to setup stepper motor objects
    feederStepper(1, P_FEED_STEP, P_FEED_DIR), // (Type:driver, STEP, DIR)
    rotationStepper(1, P_ROT_STEP, P_ROT_DIR),
    benderStepper(1, P_BEND_STEP, P_BEND_DIR)
{
    sprintf(strbuf, "MESSAGE 1: &feederStepper=%p", &feederStepper);
    msg_h.say(strbuf, L_ALWAYS);
    steppers[0] = &feederStepper;
    steppers[1] = &rotationStepper;
    steppers[2] = &benderStepper;

两个代码示例在 Arduino 1.8.12 中都可以正常编译,但是我没有合适的硬件,而且你的代码也不完整,所以我不能 运行 它们。