带有步进电机的拾放机器人平稳移动

问题描述 投票:0回答:1

我正在构建一个带有 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 
    }
}
robotics firmware stepper nucleo uistepper
1个回答
0
投票

您的代码中有一些可能的改进:您有一个字段

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 次,但您可以改变它那里也有!

© www.soinside.com 2019 - 2024. All rights reserved.