提问人:Anshul Lanjewar 提问时间:9/21/2023 最后编辑:cyberbrainAnshul Lanjewar 更新时间:9/22/2023 访问量:70
带步进电机的拾放机器人的平稳运动
Smooth movement of Pick and drop robot with stepper motor
问:
我正在构建一个具有 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
针对您的实际问题:
在您的方法中,您使用三个循环将延迟(速度)从目标位置的 0 降低到 1/4,将其保持静止从 1/4 到目标位置的 3/4,最后再次将延迟从 3/4 增加到完整的目标位置。
在加速和减速循环中,你有一个循环。
所有这些嵌套循环都包含在一个用于步进的外部循环中。step
for
for
while
do
while
但是:你只需要外层 - 循环。每一步都运行内部回路,因此电机的每一步都会加速、保持恒定和减速。
相反,你应该有一个嵌套在最外层的循环中,它决定每个周期:do
while
if
- 如果在目标范围()的第一个四分之一,则进行加速
count
num_steps
- 否则,如果在目标范围的最后四分之一,则进行减速
count
- 否则,请使用方法中给定的延迟。
step
请注意,为了获得更平稳的运动,您必须在方法中处理加速和减速,以将电机移动一整步,因为实际上您为一个步骤执行了 8 次相同的延迟,但您也可以在那里改变它!
这里有一些方法的代码 - 请注意,我的 C++ 知识已经好几年没有使用过了,我也无法测试这段代码,所以我不知道它是否能编译。必要时随时修复它;-)step
void sMotor::step(int num_steps, int direction, int delay)
{// stepper function: number of steps, direction (0- right, 1- left), waiting time (default 1200)
int speedMultiplier = 10;
// ensure that input delay param is used for the largest part.
mspeed = delay + speedMultiplier * num_steps / 4;
for (int step = 0; step < num_steps; ++step)
{
if (step < (num_steps / 4))
{
mspeed -= speedMultiplier;
}
else if (step > (3 * (num_steps / 4)))
{
mspeed += speedMultiplier;
}
else
{
mspeed = delay;
}
if (direction == 0)
{
clockwise(mspeed);
}
else if (direction == 1)
{
anticlockwise(mspeed);
}
}
}
此代码在步骤之间不使用加速和减速,因此优化由您决定。
评论