612 lines
12 KiB
C++
612 lines
12 KiB
C++
#include "StepperControlAxis.h"
|
|
|
|
StepperControlAxis::StepperControlAxis()
|
|
{
|
|
lastCalcLog = 0;
|
|
|
|
pinStep = 0;
|
|
pinDirection = 0;
|
|
pinEnable = 0;
|
|
|
|
pin2Step = 0;
|
|
pin2Direction = 0;
|
|
pin2Enable = 0;
|
|
|
|
pinMin = 0;
|
|
pinMax = 0;
|
|
|
|
axisActive = false;
|
|
|
|
coordSourcePoint = 0;
|
|
coordCurrentPoint = 0;
|
|
coordDestinationPoint = 0;
|
|
coordHomeAxis = 0;
|
|
|
|
movementUp = false;
|
|
movementToHome = false;
|
|
movementAccelerating = false;
|
|
movementDecelerating = false;
|
|
movementCruising = false;
|
|
movementCrawling = false;
|
|
movementMotorActive = false;
|
|
movementMoving = false;
|
|
}
|
|
|
|
void StepperControlAxis::test()
|
|
{
|
|
Serial.print("R99");
|
|
Serial.print(" cur loc = ");
|
|
Serial.print(coordCurrentPoint);
|
|
//Serial.print(" enc loc = ");
|
|
//Serial.print(coordEncoderPoint);
|
|
//Serial.print(" cons steps missed = ");
|
|
//Serial.print(label);
|
|
//Serial.print(consMissedSteps);
|
|
Serial.print("\r\n");
|
|
}
|
|
|
|
unsigned int StepperControlAxis::calculateSpeed(long sourcePosition, long currentPosition, long destinationPosition, long minSpeed, long maxSpeed, long stepsAccDec)
|
|
{
|
|
|
|
int newSpeed = 0;
|
|
|
|
long curPos = abs(currentPosition);
|
|
|
|
long staPos;
|
|
long endPos;
|
|
|
|
movementAccelerating = false;
|
|
movementDecelerating = false;
|
|
movementCruising = false;
|
|
movementCrawling = false;
|
|
movementMoving = false;
|
|
|
|
if (abs(sourcePosition) < abs(destinationPosition))
|
|
{
|
|
staPos = abs(sourcePosition);
|
|
endPos = abs(destinationPosition);
|
|
;
|
|
}
|
|
else
|
|
{
|
|
staPos = abs(destinationPosition);
|
|
;
|
|
endPos = abs(sourcePosition);
|
|
}
|
|
|
|
unsigned long halfway = ((endPos - staPos) / 2) + staPos;
|
|
|
|
// Set the minimum speed if the position would be out of bounds
|
|
if (curPos < staPos || curPos > endPos)
|
|
{
|
|
newSpeed = minSpeed;
|
|
movementCrawling = true;
|
|
movementMoving = true;
|
|
}
|
|
else
|
|
{
|
|
if (curPos >= staPos && curPos <= halfway)
|
|
{
|
|
// accelerating
|
|
if (curPos > (staPos + stepsAccDec))
|
|
{
|
|
// now beyond the accelleration point to go full speed
|
|
newSpeed = maxSpeed + 1;
|
|
movementCruising = true;
|
|
movementMoving = true;
|
|
}
|
|
else
|
|
{
|
|
// speeding up, increase speed linear within the first period
|
|
newSpeed = (1.0 * (curPos - staPos) / stepsAccDec * (maxSpeed - minSpeed)) + minSpeed;
|
|
movementAccelerating = true;
|
|
movementMoving = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// decelerating
|
|
if (curPos < (endPos - stepsAccDec))
|
|
{
|
|
// still before the deceleration point so keep going at full speed
|
|
newSpeed = maxSpeed + 2;
|
|
movementCruising = true;
|
|
movementMoving = true;
|
|
}
|
|
else
|
|
{
|
|
// speeding up, increase speed linear within the first period
|
|
newSpeed = (1.0 * (endPos - curPos) / stepsAccDec * (maxSpeed - minSpeed)) + minSpeed;
|
|
movementDecelerating = true;
|
|
movementMoving = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (debugPrint && (millis() - lastCalcLog > 1000))
|
|
{
|
|
|
|
lastCalcLog = millis();
|
|
|
|
Serial.print("R99");
|
|
|
|
Serial.print(" sta ");
|
|
Serial.print(staPos);
|
|
Serial.print(" cur ");
|
|
Serial.print(curPos);
|
|
Serial.print(" end ");
|
|
Serial.print(endPos);
|
|
Serial.print(" half ");
|
|
Serial.print(halfway);
|
|
Serial.print(" len ");
|
|
Serial.print(stepsAccDec);
|
|
Serial.print(" min ");
|
|
Serial.print(minSpeed);
|
|
Serial.print(" max ");
|
|
Serial.print(maxSpeed);
|
|
Serial.print(" spd ");
|
|
|
|
Serial.print(" ");
|
|
Serial.print(newSpeed);
|
|
|
|
Serial.print("\r\n");
|
|
}
|
|
|
|
// Return the calculated speed, in steps per second
|
|
return newSpeed;
|
|
}
|
|
|
|
void StepperControlAxis::checkAxisDirection()
|
|
{
|
|
|
|
if (coordHomeAxis)
|
|
{
|
|
// When home is active, the direction is fixed
|
|
movementUp = motorHomeIsUp;
|
|
movementToHome = true;
|
|
}
|
|
else
|
|
{
|
|
// For normal movement, move in direction of destination
|
|
movementUp = (coordCurrentPoint < coordDestinationPoint);
|
|
movementToHome = (abs(coordCurrentPoint) >= abs(coordDestinationPoint));
|
|
}
|
|
|
|
if (coordCurrentPoint == 0)
|
|
{
|
|
// Go slow when theoretical end point reached but there is no end stop siganl
|
|
axisSpeed = motorSpeedMin;
|
|
}
|
|
}
|
|
|
|
void StepperControlAxis::setDirectionAxis()
|
|
{
|
|
|
|
if (((!coordHomeAxis && coordCurrentPoint < coordDestinationPoint) || (coordHomeAxis && motorHomeIsUp)) ^ motorMotorInv)
|
|
{
|
|
setDirectionUp();
|
|
}
|
|
else
|
|
{
|
|
setDirectionDown();
|
|
}
|
|
}
|
|
|
|
void StepperControlAxis::checkMovement()
|
|
{
|
|
|
|
checkAxisDirection();
|
|
|
|
// Handle movement if destination is not already reached or surpassed
|
|
if (
|
|
(
|
|
(coordDestinationPoint > coordSourcePoint && coordCurrentPoint < coordDestinationPoint) ||
|
|
(coordDestinationPoint < coordSourcePoint && coordCurrentPoint > coordDestinationPoint) ||
|
|
coordHomeAxis) &&
|
|
axisActive)
|
|
{
|
|
|
|
// home or destination not reached, keep moving
|
|
|
|
// If end stop reached or the encoder doesn't move anymore, stop moving motor, otherwise set the timing for the next step
|
|
if ((coordHomeAxis && !endStopAxisReached(false)) || (!coordHomeAxis && !endStopAxisReached(!movementToHome)))
|
|
{
|
|
|
|
// Get the axis speed, in steps per second
|
|
axisSpeed = calculateSpeed(coordSourcePoint, coordCurrentPoint, coordDestinationPoint,
|
|
motorSpeedMin, motorSpeedMax, motorStepsAcc);
|
|
|
|
// Set the moments when the step is set to true and false
|
|
if (axisSpeed > 0)
|
|
{
|
|
|
|
// Take the requested speed (steps / second) and divide by the interrupt speed (interrupts per seconde)
|
|
// This gives the number of interrupts (called ticks here) before the pulse needs to be set for the next step
|
|
stepOnTick = moveTicks + (1000.0 * 1000.0 / motorInterruptSpeed / axisSpeed / 2);
|
|
stepOffTick = moveTicks + (1000.0 * 1000.0 / motorInterruptSpeed / axisSpeed);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
axisActive = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Destination or home reached. Deactivate the axis.
|
|
axisActive = false;
|
|
}
|
|
|
|
// If end stop for home is active, set the position to zero
|
|
if (endStopAxisReached(false))
|
|
{
|
|
coordCurrentPoint = 0;
|
|
}
|
|
}
|
|
|
|
void StepperControlAxis::checkTiming()
|
|
{
|
|
|
|
//int i;
|
|
|
|
if (axisActive)
|
|
{
|
|
|
|
moveTicks++;
|
|
|
|
if (moveTicks >= stepOffTick)
|
|
{
|
|
|
|
// Negative flank for the steps
|
|
resetMotorStep();
|
|
checkMovement();
|
|
}
|
|
else
|
|
{
|
|
|
|
if (moveTicks == stepOnTick)
|
|
{
|
|
|
|
// Positive flank for the steps
|
|
setStepAxis();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void StepperControlAxis::setStepAxis()
|
|
{
|
|
|
|
if (movementUp)
|
|
{
|
|
coordCurrentPoint++;
|
|
}
|
|
else
|
|
{
|
|
coordCurrentPoint--;
|
|
}
|
|
|
|
// set a step on the motors
|
|
setMotorStep();
|
|
}
|
|
|
|
bool StepperControlAxis::endStopAxisReached(bool movement_forward)
|
|
{
|
|
|
|
bool min_endstop = false;
|
|
bool max_endstop = false;
|
|
bool invert = false;
|
|
|
|
if (motorEndStopInv)
|
|
{
|
|
invert = true;
|
|
}
|
|
|
|
// for the axis to check, retrieve the end stop status
|
|
|
|
if (!invert)
|
|
{
|
|
min_endstop = endStopMin();
|
|
max_endstop = endStopMax();
|
|
}
|
|
else
|
|
{
|
|
min_endstop = endStopMax();
|
|
max_endstop = endStopMin();
|
|
}
|
|
|
|
// if moving forward, only check the end stop max
|
|
// for moving backwards, check only the end stop min
|
|
|
|
if ((!movement_forward && min_endstop) || (movement_forward && max_endstop))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void StepperControlAxis::StepperControlAxis::loadPinNumbers(int step, int dir, int enable, int min, int max, int step2, int dir2, int enable2)
|
|
{
|
|
pinStep = step;
|
|
pinDirection = dir;
|
|
pinEnable = enable;
|
|
|
|
pin2Step = step2;
|
|
pin2Direction = dir2;
|
|
pin2Enable = enable2;
|
|
|
|
pinMin = min;
|
|
pinMax = max;
|
|
}
|
|
|
|
void StepperControlAxis::loadMotorSettings(
|
|
long speedMax, long speedMin, long stepsAcc, long timeOut, bool homeIsUp, bool motorInv,
|
|
bool endStInv, long interruptSpeed, bool motor2Enbl, bool motor2Inv, bool endStEnbl)
|
|
{
|
|
|
|
motorSpeedMax = speedMax;
|
|
motorSpeedMin = speedMin;
|
|
motorStepsAcc = stepsAcc;
|
|
motorTimeOut = timeOut;
|
|
motorHomeIsUp = homeIsUp;
|
|
motorMotorInv = motorInv;
|
|
motorEndStopInv = endStInv;
|
|
motorEndStopEnbl = endStEnbl;
|
|
motorInterruptSpeed = interruptSpeed;
|
|
motorMotor2Enl = motor2Enbl;
|
|
motorMotor2Inv = motor2Inv;
|
|
}
|
|
|
|
void StepperControlAxis::loadCoordinates(long sourcePoint, long destinationPoint, bool home)
|
|
{
|
|
|
|
coordSourcePoint = sourcePoint;
|
|
coordCurrentPoint = sourcePoint;
|
|
coordDestinationPoint = destinationPoint;
|
|
coordHomeAxis = home;
|
|
|
|
// Limit normal movmement to the home position
|
|
if (!motorHomeIsUp && coordDestinationPoint < 0)
|
|
{
|
|
coordDestinationPoint = 0;
|
|
}
|
|
|
|
if (motorHomeIsUp && coordDestinationPoint > 0)
|
|
{
|
|
coordDestinationPoint = 0;
|
|
}
|
|
|
|
// Initialize movement variables
|
|
moveTicks = 0;
|
|
axisActive = true;
|
|
}
|
|
|
|
void StepperControlAxis::enableMotor()
|
|
{
|
|
digitalWrite(pinEnable, LOW);
|
|
if (motorMotor2Enl)
|
|
{
|
|
digitalWrite(pin2Enable, LOW);
|
|
}
|
|
movementMotorActive = true;
|
|
}
|
|
|
|
void StepperControlAxis::disableMotor()
|
|
{
|
|
digitalWrite(pinEnable, HIGH);
|
|
if (motorMotor2Enl)
|
|
{
|
|
digitalWrite(pin2Enable, HIGH);
|
|
}
|
|
movementMotorActive = false;
|
|
}
|
|
|
|
void StepperControlAxis::setDirectionUp()
|
|
{
|
|
if (motorMotorInv)
|
|
{
|
|
digitalWrite(pinDirection, LOW);
|
|
}
|
|
else
|
|
{
|
|
digitalWrite(pinDirection, HIGH);
|
|
}
|
|
|
|
if (motorMotor2Enl && motorMotor2Inv)
|
|
{
|
|
digitalWrite(pin2Direction, LOW);
|
|
}
|
|
else
|
|
{
|
|
digitalWrite(pin2Direction, HIGH);
|
|
}
|
|
}
|
|
|
|
void StepperControlAxis::setDirectionDown()
|
|
{
|
|
if (motorMotorInv)
|
|
{
|
|
digitalWrite(pinDirection, HIGH);
|
|
}
|
|
else
|
|
{
|
|
digitalWrite(pinDirection, LOW);
|
|
}
|
|
|
|
if (motorMotor2Enl && motorMotor2Inv)
|
|
{
|
|
digitalWrite(pin2Direction, HIGH);
|
|
}
|
|
else
|
|
{
|
|
digitalWrite(pin2Direction, LOW);
|
|
}
|
|
}
|
|
|
|
void StepperControlAxis::setMovementUp()
|
|
{
|
|
movementUp = true;
|
|
}
|
|
|
|
void StepperControlAxis::setMovementDown()
|
|
{
|
|
movementUp = false;
|
|
}
|
|
|
|
void StepperControlAxis::setDirectionHome()
|
|
{
|
|
if (motorHomeIsUp)
|
|
{
|
|
setDirectionUp();
|
|
setMovementUp();
|
|
}
|
|
else
|
|
{
|
|
setDirectionDown();
|
|
setMovementDown();
|
|
}
|
|
}
|
|
|
|
void StepperControlAxis::setDirectionAway()
|
|
{
|
|
if (motorHomeIsUp)
|
|
{
|
|
setDirectionDown();
|
|
setMovementDown();
|
|
}
|
|
else
|
|
{
|
|
setDirectionUp();
|
|
setMovementUp();
|
|
}
|
|
}
|
|
|
|
unsigned long StepperControlAxis::getLength(long l1, long l2)
|
|
{
|
|
if (l1 > l2)
|
|
{
|
|
return l1 - l2;
|
|
}
|
|
else
|
|
{
|
|
return l2 - l1;
|
|
}
|
|
}
|
|
|
|
bool StepperControlAxis::endStopsReached()
|
|
{
|
|
return ((digitalRead(pinMin) == motorEndStopInv) || (digitalRead(pinMax) == motorEndStopInv)) && motorEndStopEnbl;
|
|
}
|
|
|
|
bool StepperControlAxis::endStopMin()
|
|
{
|
|
//return ((digitalRead(pinMin) == motorEndStopInv) || (digitalRead(pinMax) == motorEndStopInv));
|
|
return digitalRead(pinMin) && motorEndStopEnbl;
|
|
}
|
|
|
|
bool StepperControlAxis::endStopMax()
|
|
{
|
|
//return ((digitalRead(pinMin) == motorEndStopInv) || (digitalRead(pinMax) == motorEndStopInv));
|
|
return digitalRead(pinMax) && motorEndStopEnbl;
|
|
}
|
|
|
|
bool StepperControlAxis::isAxisActive()
|
|
{
|
|
return axisActive;
|
|
}
|
|
|
|
void StepperControlAxis::deactivateAxis()
|
|
{
|
|
axisActive = false;
|
|
}
|
|
|
|
void StepperControlAxis::setMotorStep()
|
|
{
|
|
digitalWrite(pinStep, HIGH);
|
|
if (pin2Enable)
|
|
{
|
|
digitalWrite(pin2Step, HIGH);
|
|
}
|
|
}
|
|
|
|
void StepperControlAxis::resetMotorStep()
|
|
{
|
|
movementStepDone = true;
|
|
digitalWrite(pinStep, LOW);
|
|
if (pin2Enable)
|
|
{
|
|
digitalWrite(pin2Step, LOW);
|
|
}
|
|
}
|
|
|
|
bool StepperControlAxis::pointReached(long currentPoint, long destinationPoint)
|
|
{
|
|
return (destinationPoint == currentPoint);
|
|
}
|
|
|
|
long StepperControlAxis::currentPosition()
|
|
{
|
|
return coordCurrentPoint;
|
|
}
|
|
|
|
void StepperControlAxis::setCurrentPosition(long newPos)
|
|
{
|
|
coordCurrentPoint = newPos;
|
|
}
|
|
|
|
void StepperControlAxis::setMaxSpeed(long speed)
|
|
{
|
|
motorSpeedMax = speed;
|
|
}
|
|
|
|
void StepperControlAxis::activateDebugPrint()
|
|
{
|
|
debugPrint = true;
|
|
}
|
|
|
|
bool StepperControlAxis::isStepDone()
|
|
{
|
|
return movementStepDone;
|
|
}
|
|
|
|
void StepperControlAxis::resetStepDone()
|
|
{
|
|
movementStepDone = false;
|
|
}
|
|
|
|
bool StepperControlAxis::movingToHome()
|
|
{
|
|
return movementToHome;
|
|
}
|
|
|
|
bool StepperControlAxis::movingUp()
|
|
{
|
|
return movementUp;
|
|
}
|
|
|
|
bool StepperControlAxis::isAccelerating()
|
|
{
|
|
return movementAccelerating;
|
|
}
|
|
|
|
bool StepperControlAxis::isDecelerating()
|
|
{
|
|
return movementDecelerating;
|
|
}
|
|
|
|
bool StepperControlAxis::isCruising()
|
|
{
|
|
return movementCruising;
|
|
}
|
|
|
|
bool StepperControlAxis::isCrawling()
|
|
{
|
|
return movementCrawling;
|
|
}
|
|
|
|
bool StepperControlAxis::isMotorActive()
|
|
{
|
|
return movementMotorActive;
|
|
}
|