基於案例2,對代碼進行了修改

我就是不理解,修改的代碼爲什麼電機不執行。我對案例2的代碼按照我的邏輯就行了修改驗證。

試驗證明程序會一直卡在while 循環裏,而且步進電機沒有任何動作。使用while循環是想讓程序更快速的調用stepperX.run(),以此獲得更高的速度,而不是整個程序過一遍調用一次,本身就用的減速電機。速度太慢實際應用是不是很理想,尤其是手動模式,太慢了。

  if (muoviX) {
    motoreX.setSpeed(speedX);
    stepperX.move(300);//相對運動300步,相對較短的時間,不會影響速度變化,只不過損失過渡順滑度
    while(stepperX.distanceToGo() != 0){//如果相對運動沒有完成,將始終卡在次循環裏直到運動完成
    stepperX.run();//電機運動一步

    }

跳不出循環說明stepperX.distanceToGo() != 0始終爲真。

看到有的案例是

    stepperX.moveTo(300);//相對運動300步,相對較短的時間,不會影響速度變化,只不過損失過渡順滑度
   if (stepperX.distanceToGo() != 0){//如果相對運動沒有完成,將始終卡在次循環裏直到運動完成
    stepperX.runToPosition();//電機運動一步

    }

這個代碼是可行的。但是是絕對位置,到達位置之後電機不會在動了。

扒出源代碼看看:

從以下代碼可以整理出邏輯順序,

move()->moveTo()->computeNewSpeed()->distanceToGo()計算出相應速度加速度參數;

run()->runSpeed()->step()-step1()->setOutputPins()-電機運動最多一步,調用一次走一步。

runSpeed()函數內對當前位置進行變更;

目前來看,我的代碼邏輯上是通的。

第一步:

void AccelStepper::move(long relative)
{
    moveTo(_currentPos + relative);//調用Moveto函數,目標位置爲現在位置+相對值
}

以上代碼計算出相對位置量對應的絕對位置,然後調用moveTo函數執行; 

第二步:

void AccelStepper::moveTo(long absolute)
{
    if (_targetPos != absolute)
    {
	_targetPos = absolute;
	computeNewSpeed();
	// compute new n?
    }
}

 以上函數,判斷給定的位置是否和現在的位置相等,如果不等就把現在的位置設置成目標位置,並進行速度計算;

速度計算見 第六步;

第三步:

long AccelStepper::distanceToGo()
{
    return _targetPos - _currentPos;//返回值爲目標位置減去現在的位置,如果現在位置和目標位置一樣,則爲0;
}

此代碼返回目標位置與現在位置的差值; 

 第四步:

boolean AccelStepper::run()
{
    if (runSpeed())
	computeNewSpeed();
    return _speed != 0.0 || distanceToGo() != 0;
}

此代碼如果速度沒有達到設定的速度就重新計算速度,返回值爲判斷式(如果速度沒到0並且現在位置沒到目標位置則返回0,否則返回1); 

 第五步:

boolean AccelStepper::runSpeed()
{
    // Dont do anything unless we actually have a step interval
    if (!_stepInterval)
	return false;

    unsigned long time = micros();   
    if (time - _lastStepTime >= _stepInterval)
    {
	if (_direction == DIRECTION_CW)
	{
	    // Clockwise
	    _currentPos += 1;
	}
	else
	{
	    // Anticlockwise  
	    _currentPos -= 1;
	}
	step(_currentPos);

	_lastStepTime = time; // Caution: does not account for costs in step()

	return true;
    }
    else
    {
	return false;
    }
}

第六步: 

void AccelStepper::computeNewSpeed()
{
    long distanceTo = distanceToGo(); // +ve is clockwise from curent location

    long stepsToStop = (long)((_speed * _speed) / (2.0 * _acceleration)); // Equation 16

    if (distanceTo == 0 && stepsToStop <= 1)
    {
	// We are at the target and its time to stop
	_stepInterval = 0;
	_speed = 0.0;
	_n = 0;
	return;
    }

    if (distanceTo > 0)
    {
	// We are anticlockwise from the target
	// Need to go clockwise from here, maybe decelerate now
	if (_n > 0)
	{
	    // Currently accelerating, need to decel now? Or maybe going the wrong way?
	    if ((stepsToStop >= distanceTo) || _direction == DIRECTION_CCW)
		_n = -stepsToStop; // Start deceleration
	}
	else if (_n < 0)
	{
	    // Currently decelerating, need to accel again?
	    if ((stepsToStop < distanceTo) && _direction == DIRECTION_CW)
		_n = -_n; // Start accceleration
	}
    }
    else if (distanceTo < 0)
    {
	// We are clockwise from the target
	// Need to go anticlockwise from here, maybe decelerate
	if (_n > 0)
	{
	    // Currently accelerating, need to decel now? Or maybe going the wrong way?
	    if ((stepsToStop >= -distanceTo) || _direction == DIRECTION_CW)
		_n = -stepsToStop; // Start deceleration
	}
	else if (_n < 0)
	{
	    // Currently decelerating, need to accel again?
	    if ((stepsToStop < -distanceTo) && _direction == DIRECTION_CCW)
		_n = -_n; // Start accceleration
	}
    }

    // Need to accelerate or decelerate
    if (_n == 0)
    {
	// First step from stopped
	_cn = _c0;
	_direction = (distanceTo > 0) ? DIRECTION_CW : DIRECTION_CCW;
    }
    else
    {
	// Subsequent step. Works for accel (n is +_ve) and decel (n is -ve).
	_cn = _cn - ((2.0 * _cn) / ((4.0 * _n) + 1)); // Equation 13
	_cn = max(_cn, _cmin); 
    }
    _n++;
    _stepInterval = _cn;
    _speed = 1000000.0 / _cn;
    if (_direction == DIRECTION_CCW)
	_speed = -_speed;

#if 0
    Serial.println(_speed);
    Serial.println(_acceleration);
    Serial.println(_cn);
    Serial.println(_c0);
    Serial.println(_n);
    Serial.println(_stepInterval);
    Serial.println(distanceTo);
    Serial.println(stepsToStop);
    Serial.println("-----");
#endif
}
void AccelStepper::step(long step)
{
    switch (_interface)
    {
        case FUNCTION:
            step0(step);
            break;

	case DRIVER:
	    step1(step);
	    break;
    
	case FULL2WIRE:
	    step2(step);
	    break;
    
	case FULL3WIRE:
	    step3(step);
	    break;  

	case FULL4WIRE:
	    step4(step);
	    break;  

	case HALF3WIRE:
	    step6(step);
	    break;  
		
	case HALF4WIRE:
	    step8(step);
	    break;  
    }
}

 

void AccelStepper::setOutputPins(uint8_t mask)
{
    uint8_t numpins = 2;
    if (_interface == FULL4WIRE || _interface == HALF4WIRE)
	numpins = 4;
    else if (_interface == FULL3WIRE || _interface == HALF3WIRE)
	numpins = 3;
    uint8_t i;
    for (i = 0; i < numpins; i++)
	digitalWrite(_pin[i], (mask & (1 << i)) ? (HIGH ^ _pinInverted[i]) : (LOW ^ _pinInverted[i]));
}
void AccelStepper::step1(long step)
{
    (void)(step); // Unused

    // _pin[0] is step, _pin[1] is direction
    setOutputPins(_direction ? 0b10 : 0b00); // Set direction first else get rogue pulses
    setOutputPins(_direction ? 0b11 : 0b01); // step HIGH
    // Caution 200ns setup time 
    // Delay the minimum allowed pulse width
    delayMicroseconds(_minPulseWidth);
    setOutputPins(_direction ? 0b10 : 0b00); // step LOW
}
/*
 
 * 用Arduino和操縱桿控制馬達,不同的模擬值對應不同的速度值

 */ 

//Inclusione delle librerie 包含一下庫
#include <AccelStepper.h>


// 引腳定義

const int pinSwEnable = 2;  //搖桿按鍵接線引腳
const int pinEnable = 8;  //A4988驅動使能引腳定義


const int jX = A0;  //搖桿X軸引腳定義
const int stepX = 3;  //步進電機X脈衝輸出引腳
const int dirX = 5; //步進電機X方向控制引腳
long speedX, valX, mapX;  //電機X相關變量

const int jY = A1;  //搖桿Y軸引腳定義
const int stepY = 4;  //步進電機Y脈衝輸出引腳
const int dirY = 6; //步進電機Y方向控制引腳
long speedY, valY, mapY;  //電機X相關變量

//AccelStepper 庫使用的變量
const int maxSpeed = 1000;  //Arduino UNO受晶振限制最大到4000
const int minSpeed = 0; //電機最小速度
const float accelerazione = 50.0; //加速度

const int treshold = 30;  //柵域
long tresholdUp, tresholdDown;  //變量

boolean abilitato, muoviX, muoviY, enable;  //移動變量


//AccelStepper庫電機定義 
AccelStepper motoreX(AccelStepper::DRIVER, stepX, dirX);
AccelStepper motoreY(AccelStepper::DRIVER, stepY, dirY);

void setup() {
  //變量初始化
  speedX = speedY = 0;
  enable = false;//電機可工作

  //引腳模式定義
  pinMode(ledEnable, OUTPUT);
  pinMode(pinEnable, OUTPUT);

  pinMode(pinSwEnable, INPUT_PULLUP); //按鍵定義輸入,並置高

  digitalWrite(ledEnable, enable);
  digitalWrite(pinEnable, !enable); //A4988拉高,步進電機不工作



  //確定搖桿的位置值
  tresholdDown = (maxSpeed / 2) - treshold;//之前treshold賦值30 470
  tresholdUp = (maxSpeed / 2) + treshold; //530

  //配置步進電機參數
  motoreX.setMaxSpeed(maxSpeed);//設置最大速度
  motoreX.setSpeed(minSpeed);//設置運行速度
  motoreX.setAcceleration(accelerazione);//設置加速度

  motoreY.setMaxSpeed(maxSpeed);
  motoreY.setSpeed(minSpeed);
  motoreY.setAcceleration(accelerazione);
}

void loop() {

  
 checkEnable();

  digitalWrite(ledEnable, enable);  //控制LED
  digitalWrite(pinEnable, !enable); //控制電機驅動使能端

  //獲取搖桿兩個方向的模擬變量值
  valX = analogRead(jX);
  valY = analogRead(jY);

  //對從搖桿上獲取的值進行速度變換
  mapX = map(valX, 0, 1023, minSpeed, maxSpeed);
  mapY = map(valY, 0, 1023, minSpeed, maxSpeed);

  
  pilotaMotori(mapX, mapY);

}

void pilotaMotori(long mapX, long mapY) {

  if (mapX <= tresholdDown) {
    //變換的X速度小於470
    speedX = -map(mapX, tresholdDown, minSpeed,   minSpeed, maxSpeed);//小於470爲負方向
    muoviX = true;
  } else if (mapX >= tresholdUp) {
    //變換的X速度大於530
    speedX = map(mapX,  maxSpeed, tresholdUp,  maxSpeed, minSpeed);//大於530爲正方向
    muoviX = true;
  } else {
    //電機不動
    speedX = 0;
    muoviX = false;
  }

  if (mapY <= tresholdDown) {
    
    speedY = -map(mapY, tresholdDown, minSpeed,   minSpeed, maxSpeed);
    muoviY = true;
  } else if (mapY >= tresholdUp) {
    
    speedY = map(mapY,  maxSpeed, tresholdUp,  maxSpeed, minSpeed);
    muoviY = true;
  } else {
   
    speedY = 0;
    muoviY = false;
  }

  if (muoviX) {
    motoreX.setSpeed(speedX);
    stepperX.move(300);//相對運動300步,相對較短的時間,不會影響速度變化,只不過損失過渡順滑度
    while(stepperX.distanceToGo() != 0){//如果相對運動沒有完成,將始終卡在次循環裏直到運動完成
    stepperX.run();//電機運動一步

}

    motoreX.run();
  } else {
    motoreX.stop();
  }

  if (muoviY) {
    motoreY.setSpeed(speedY);
    motoreY.run();
  } else {
    motoreY.stop();
  }
}


void checkEnable() {//按鍵檢測



  if (digitalRead(pinSwEnable)==0) {
    enable = !enable;
  }

}

stepperX.move(300);

while(stepperX.distanceToGo() != 0){

stepperX.run();

}

爲什麼電機會不運動。設計了以下代碼進行驗證

#include <AccelStepper.h>
#define SW 2
int n=0;

// Define a stepper and the pins it will use
AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5

void setup()
{ 
  pinMode(SW,INPUT); 
  digitalWrite(SW,HIGH);
  stepper.setMaxSpeed(3000);
  stepper.setAcceleration(50);
  Serial.begin(9600);
}

void loop()

{   
    if(digitalRead(SW) == 0){
    stepper.move(300);}
    while (stepper.distanceToGo() != 0)
    {
	// Random change to speed, position and acceleration
	// Make sure we dont get 0 speed or accelerations
	delay(100);
	

  n=stepper.distanceToGo();
  Serial.println("the internal distance remain steps:");
  Serial.println(n);
    
    stepper.run();
    }
  Serial.println("the external distance remain steps:");
  Serial.println(n);
}

通過串口檢測證明可以運行,電機不轉的原因可能是因爲脈衝的頻率太高了,設置的加速度與電機的電器特性不符,需要對最大速度和加速度等參數進行調試。

run()函數需要相對距離,如果現在的位置和目標位置一樣是不會運行的。它將通過距離來計算何時該加速何時該減速;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章