我正在构建一个带有 3 个步进电机的拾放机器人。我使用NUCLEO-F746ZG微控制器和C++编程来控制它。
现在的问题是手臂在开始和结束时会出现猛烈的运动(惯性),我想平滑运动。为此,我想在电机启动时加速,在电机停止时减速。我尝试了不同的方法,但都不起作用,电机仅以恒定速度移动。请帮我解决这个问题,让步进电机顺利移动。
#include "stepperMotor.h"
#include "mbed.h"
int motorSpeed; // stepper speed
const float acc = 100;
int mspeed;
sMotor::sMotor(PinName A0, PinName A1, PinName A2, PinName A3) : _A0(A0), _A1(A1), _A2(A2), _A3(A3)
{ // Defenition of motor pins
_A0 = 0;
_A1 = 0;
_A2 = 0;
_A3 = 0;
}
void sMotor::anticlockwise(int mspeed)
{ // rotate the motor 1 step anticlockwise
for (int i = 0; i < 8; i++) {
switch (i)
{ // activate the ports A0, A2, A3, A3 in a binary sequence for steps
case 0:
{
_A0 = 0;
_A1 = 0;
_A2 = 1;
_A3 = 0;
}
break;
case 1:
{
_A0 = 0;
_A1 = 0;
_A2 = 0;
_A3 = 0;
}
break;
case 2:
{
_A0 = 0;
_A1 = 0;
_A2 = 0;
_A3 = 1;
}
break;
case 3:
{
_A0 = 0;
_A1 = 1;
_A2 = 0;
_A3 = 1;
}
break;
case 4:
{
_A0 = 0;
_A1 = 1;
_A2 = 1;
_A3 = 1;
}
break;
case 5:
{
_A0 = 1;
_A1 = 1;
_A2 = 1;
_A3 = 1;
}
break;
case 6:
{
_A0 = 1;
_A1 = 0;
_A2 = 1;
_A3 = 1;
}
break;
case 7:
{
_A0 = 1;
_A1 = 0;
_A2 = 1;
_A3 = 0;
}
break;
}
wait_us(mspeed);
// wait_us(motorSpeed); // wait time defines the speed
}
}
void sMotor::clockwise(int mspeed)
{ // rotate the motor 1 step clockwise
for (int i = 7; i >= 0; i--) {
switch (i)
{
case 0:
{
_A0 = 0;
_A1 = 0;
_A2 = 0;
_A3 = 1;
}
break;
case 1:
{
_A0 = 0;
_A1 = 0;
_A2 = 1;
_A3 = 1;
}
break;
case 2:
{
_A0 = 0;
_A1 = 0;
_A2 = 1;
_A3 = 0;
}
break;
case 3:
{
_A0 = 0;
_A1 = 1;
_A2 = 1;
_A3 = 0;
}
break;
case 4:
{
_A0 = 0;
_A1 = 1;
_A2 = 0;
_A3 = 0;
}
break;
case 5:
{
_A0 = 1;
_A1 = 1;
_A2 = 0;
_A3 = 0;
}
break;
case 6:
{
_A0 = 1;
_A1 = 0;
_A2 = 0;
_A3 = 0;
}
break;
case 7:
{
_A0 = 1;
_A1 = 0;
_A2 = 0;
_A3 = 1;
}
break;
}
wait_us(mspeed);
}
}
void sMotor::step(int num_steps, int direction, int speed)
{// steper function: number of steps, direction (0- right, 1- left), speed (default 1200)
int count = 0; // initalize step count
float stepTime = 1.0 / speed; //aTry
int w = num_steps;
mspeed = 250;
int speedMultiplier = 10;
motorSpeed = speed; //set motor speed
if (direction == 0) // turn clockwise
do
{
clockwise(mspeed);
count++;
for (int i = 0; i < (w/4); i++)
{
while (mspeed != speed)
{
mspeed = mspeed - speedMultiplier;
}
}
for (int i = w/4; i < 3 * (w / 4); i++)
{
mspeed = speed;
}
for (int i = 3 * (w / 4); i < w; i++)
{
while (mspeed != 400)
{
mspeed = mspeed + speedMultiplier;
}
}
} while (count < num_steps); // turn number of steps applied
else if (direction == 1) // turn anticlockwise
{
count = 0;
do
{
anticlockwise(mspeed);
count++;
for (int i = 0; i < (w / 4); i++)
{
while (mspeed != speed)
{
mspeed = mspeed - speedMultiplier;
}
}
for (int i = w/4; i < 3 * (w / 4); i++)
{
mspeed = speed;
}
for (int i = 3 * (w / 4); i < w; i++)
{
while (mspeed != 400)
{
mspeed = mspeed + speedMultiplier;
}
}
} while (count < num_steps);// turn number of steps applied
}
}
您的代码中有一些可能的改进:您有一个字段
mspeed
,并且在两种方法中都有一个参数 mspeed
- 参数覆盖该字段。但是当您现在实现它时,该参数根本不是必需的,因为方法 clockwise
和 anticlockwise
可以访问字段 mspeed
。
您还分配了字段
motorspeed
,但您从未使用过它。
字段和参数的名称
mspeed
具有误导性,通常移动速度更快,但您将其用作等待时间,所以delay
会是一个更好的名称。
对于
clockwise
和anticlockwise
方法:您确定使用正确的值和正确的顺序来激活步进电机的线圈吗?根据我的理解,您应该有一个完整步骤的值列表,并且您可以在顺时针方向的一个方向上“播放”它,并在逆时针运动的相反方向上“播放”它。这样您就不必使用 switch
语句,并且对于两个方向也只有一种方法。
在方法
step
中,您应该为w
使用更好的名称,也许是position
?
此外,在该方法中,您有一个巨大的顺时针和逆时针运动代码块,它们完全相等,只是对 clockwise
和 anticlockwise
方法的调用不同。为了防止代码重复错误,您应该将外部 if
进一步移至内部,以便它仅决定对两个方法之一的实际调用。这是最重要的改进,因为它会影响您问题的解决!
针对您的实际问题: 在您的
step
方法中,您使用三个 for
循环将延迟(速度)从目标位置的 0 位置减少到 1/4,并从目标位置的 1/4 到 3/4 保持静止位置,最后再次将延迟从 3/4 增加到完整的目标位置。
在加速和减速 for
循环内,有一个 while
循环。
所有这些嵌套循环都包含在一个用于步进的外部 do
-while
循环中。
但是:您只需要外部
do
-while
循环。每一步都运行内循环,因此电机的每一步都会加速、保持恒定和减速。
相反,您应该在最外层循环内嵌套一个 if
,该循环决定每个周期:
count
位于目标范围的第一四分之一 (num_steps
),则进行加速count
位于目标范围的最后四分之一内,则进行减速step
方法中给出的延迟。请注意,为了实现更平滑的运动,您还必须在方法内处理加速和减速,以使电机移动一整步,因为实际上您对一步执行相同的延迟 8 次,但您可以改变它那里也有!