使用指针迭代 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 中都可以正常编译,但是我没有合适的硬件,而且你的代码也不完整,所以我不能 运行 它们。
我正在为 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 中都可以正常编译,但是我没有合适的硬件,而且你的代码也不完整,所以我不能 运行 它们。