farmbot-arduino-firmware/src/Movement.cpp

1846 lines
50 KiB
C++

#include "Movement.h"
#include "Debug.h"
#include "Config.h"
static Movement *instance;
Movement *Movement::getInstance()
{
if (!instance)
{
instance = new Movement();
};
return instance;
};
void Movement::reportEncoders()
{
Serial.print(COMM_REPORT_ENCODER_SCALED);
Serial.print(" X");
Serial.print((float)encoderX.currentPosition() / (float)stepsPerMm[0]);
Serial.print(" Y");
Serial.print((float)encoderY.currentPosition() / (float)stepsPerMm[1]);
Serial.print(" Z");
Serial.print((float)encoderZ.currentPosition() / (float)stepsPerMm[2]);
CurrentState::getInstance()->printQAndNewLine();
Serial.print(COMM_REPORT_ENCODER_RAW);
Serial.print(" X");
Serial.print(encoderX.currentPositionRaw());
Serial.print(" Y");
Serial.print(encoderY.currentPositionRaw());
Serial.print(" Z");
Serial.print(encoderZ.currentPositionRaw());
CurrentState::getInstance()->printQAndNewLine();
}
void Movement::getEncoderReport()
{
serialBuffer += COMM_REPORT_ENCODER_SCALED;
serialBuffer += " X";
serialBuffer += (float)encoderX.currentPosition() / (float)stepsPerMm[0];
serialBuffer += " Y";
serialBuffer += (float)encoderY.currentPosition() / (float)stepsPerMm[1];
serialBuffer += " Z";
serialBuffer += (float)encoderZ.currentPosition() / (float)stepsPerMm[2];
serialBuffer += CurrentState::getInstance()->getQAndNewLine();
serialBuffer += COMM_REPORT_ENCODER_RAW;
serialBuffer += " X";
serialBuffer += encoderX.currentPositionRaw();
serialBuffer += " Y";
serialBuffer += encoderY.currentPositionRaw();
serialBuffer += " Z";
serialBuffer += encoderZ.currentPositionRaw();
serialBuffer += CurrentState::getInstance()->getQAndNewLine();
}
void Movement::reportStatus(MovementAxis *axis, int axisStatus)
{
serialBuffer += COMM_REPORT_CMD_STATUS;
serialBuffer += " ";
serialBuffer += axis->channelLabel;
serialBuffer += axisStatus;
serialBuffer += CurrentState::getInstance()->getQAndNewLine();
//Serial.print(COMM_REPORT_CMD_STATUS);
//Serial.print(" ");
//Serial.print(axis->label);
//Serial.print(axisStatus);
//CurrentState::getInstance()->printQAndNewLine();
}
void Movement::reportCalib(MovementAxis *axis, int calibStatus)
{
Serial.print(COMM_REPORT_CALIB_STATUS);
Serial.print(" ");
Serial.print(axis->channelLabel);
Serial.print(calibStatus);
CurrentState::getInstance()->printQAndNewLine();
}
void Movement::checkAxisSubStatus(MovementAxis *axis, int *axisSubStatus)
{
int newStatus = 0;
bool statusChanged = false;
if (axis->isAccelerating())
{
newStatus = COMM_REPORT_MOVE_STATUS_ACCELERATING;
}
if (axis->isCruising())
{
newStatus = COMM_REPORT_MOVE_STATUS_CRUISING;
}
if (axis->isDecelerating())
{
newStatus = COMM_REPORT_MOVE_STATUS_DECELERATING;
}
if (axis->isCrawling())
{
newStatus = COMM_REPORT_MOVE_STATUS_CRAWLING;
}
// if the status changes, send out a status report
if (*axisSubStatus != newStatus && newStatus > 0)
{
statusChanged = true;
}
*axisSubStatus = newStatus;
if (statusChanged)
{
reportStatus(axis, *axisSubStatus);
}
}
//const int MOVEMENT_INTERRUPT_SPEED = 100; // Interrupt cycle in micro seconds
Movement::Movement()
{
// Initialize some variables for testing
motorMotorsEnabled = false;
motorConsMissedSteps[0] = 0;
motorConsMissedSteps[1] = 0;
motorConsMissedSteps[2] = 0;
motorLastPosition[0] = 0;
motorLastPosition[1] = 0;
motorLastPosition[2] = 0;
motorConsEncoderLastPosition[0] = 0;
motorConsEncoderLastPosition[1] = 0;
motorConsEncoderLastPosition[2] = 0;
// Create the axis controllers
axisX = MovementAxis();
axisY = MovementAxis();
axisZ = MovementAxis();
axisX.channelLabel = 'X';
axisY.channelLabel = 'Y';
axisZ.channelLabel = 'Z';
// Create the encoder controller
encoderX = MovementEncoder();
encoderY = MovementEncoder();
encoderZ = MovementEncoder();
// Load settings
loadSettings();
motorMotorsEnabled = false;
}
void Movement::loadSettings()
{
/**/ //Serial.println("== load pin numbers ==");
// Load motor settings
axisX.loadPinNumbers(X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, E_STEP_PIN, E_DIR_PIN, E_ENABLE_PIN);
axisY.loadPinNumbers(Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, 0, 0, 0);
axisZ.loadPinNumbers(Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, 0, 0, 0);
axisSubStep[0] = COMM_REPORT_MOVE_STATUS_IDLE;
axisSubStep[1] = COMM_REPORT_MOVE_STATUS_IDLE;
axisSubStep[2] = COMM_REPORT_MOVE_STATUS_IDLE;
/**/ //Serial.println("== load motor settings ==");
loadMotorSettings();
// Load encoder settings
/**/ //Serial.println("== load encoder settings ==");
loadEncoderSettings();
/**/ //Serial.println("== load mdl encoder settings ==");
encoderX.loadMdlEncoderId(_MDL_X1);
encoderY.loadMdlEncoderId(_MDL_Y);
encoderZ.loadMdlEncoderId(_MDL_Z);
/**/ //Serial.println("== load encoder pin numbers ==");
encoderX.loadPinNumbers(X_ENCDR_A, X_ENCDR_B, X_ENCDR_A_Q, X_ENCDR_B_Q);
encoderY.loadPinNumbers(Y_ENCDR_A, Y_ENCDR_B, Y_ENCDR_A_Q, Y_ENCDR_B_Q);
encoderZ.loadPinNumbers(Z_ENCDR_A, Z_ENCDR_B, Z_ENCDR_A_Q, Z_ENCDR_B_Q);
/**/ //Serial.println("== load encoder load settings 2 ==");
encoderX.loadSettings(motorConsEncoderType[0], motorConsEncoderScaling[0], motorConsEncoderInvert[0]);
encoderY.loadSettings(motorConsEncoderType[1], motorConsEncoderScaling[1], motorConsEncoderInvert[1]);
encoderZ.loadSettings(motorConsEncoderType[2], motorConsEncoderScaling[2], motorConsEncoderInvert[2]);
}
#if defined(FARMDUINO_EXP_V20)
void Movement::initTMC2130()
{
axisX.initTMC2130();
axisY.initTMC2130();
axisZ.initTMC2130();
}
void Movement::loadSettingsTMC2130()
{
/**/
int motorCurrentX;
int stallSensitivityX;
int microStepsX;
int motorCurrentY;
int stallSensitivityY;
int microStepsY;
int motorCurrentZ;
int stallSensitivityZ;
int microStepsZ;
motorCurrentX = ParameterList::getInstance()->getValue(MOVEMENT_MOTOR_CURRENT_X);
stallSensitivityX = ParameterList::getInstance()->getValue(MOVEMENT_STALL_SENSITIVITY_X);
microStepsX = ParameterList::getInstance()->getValue(MOVEMENT_MICROSTEPS_X);
//axisX.loadSettingsTMC2130(motorCurrent, stallSensitivity, microSteps);
motorCurrentY = ParameterList::getInstance()->getValue(MOVEMENT_MOTOR_CURRENT_Y);
stallSensitivityY = ParameterList::getInstance()->getValue(MOVEMENT_STALL_SENSITIVITY_Y);
microStepsY = ParameterList::getInstance()->getValue(MOVEMENT_MICROSTEPS_Y);
//axisY.loadSettingsTMC2130(motorCurrent, stallSensitivity, microSteps);
motorCurrentZ = ParameterList::getInstance()->getValue(MOVEMENT_MOTOR_CURRENT_Z);
stallSensitivityZ = ParameterList::getInstance()->getValue(MOVEMENT_STALL_SENSITIVITY_Z);
microStepsX = ParameterList::getInstance()->getValue(MOVEMENT_MICROSTEPS_Z);
//axisZ.loadSettingsTMC2130(motorCurrent, stallSensitivity, microSteps);
motorCurrentX = 600;
stallSensitivityX = 0;
microStepsX = 0;
motorCurrentY = 600;
stallSensitivityY = 0;
microStepsY = 0;
motorCurrentZ = 600;
stallSensitivityZ = 0;
microStepsZ = 0;
TMC2130X->push();
TMC2130X->toff(3);
TMC2130X->tbl(1);
TMC2130X->hysteresis_start(4);
TMC2130X->hysteresis_end(-2);
TMC2130X->rms_current(motorCurrentX); // mA
TMC2130X->microsteps(microStepsX);
TMC2130X->diag1_stall(1);
TMC2130X->diag1_active_high(1);
TMC2130X->coolstep_min_speed(0xFFFFF); // 20bit max
TMC2130X->THIGH(0);
TMC2130X->semin(5);
TMC2130X->semax(2);
TMC2130X->sedn(0b01);
TMC2130X->sg_stall_value(stallSensitivityX);
TMC2130Y->push();
TMC2130Y->toff(3);
TMC2130Y->tbl(1);
TMC2130Y->hysteresis_start(4);
TMC2130Y->hysteresis_end(-2);
TMC2130Y->rms_current(motorCurrentY); // mA
TMC2130Y->microsteps(microStepsY);
TMC2130Y->diag1_stall(1);
TMC2130Y->diag1_active_high(1);
TMC2130Y->coolstep_min_speed(0xFFFFF); // 20bit max
TMC2130Y->THIGH(0);
TMC2130Y->semin(5);
TMC2130Y->semax(2);
TMC2130Y->sedn(0b01);
TMC2130Y->sg_stall_value(stallSensitivityY);
TMC2130Z->push();
TMC2130Z->toff(3);
TMC2130Z->tbl(1);
TMC2130Z->hysteresis_start(4);
TMC2130Z->hysteresis_end(-2);
TMC2130Z->rms_current(motorCurrentZ); // mA
TMC2130Z->microsteps(microStepsZ);
TMC2130Z->diag1_stall(1);
TMC2130Z->diag1_active_high(1);
TMC2130Z->coolstep_min_speed(0xFFFFF); // 20bit max
TMC2130Z->THIGH(0);
TMC2130Z->semin(5);
TMC2130Z->semax(2);
TMC2130Z->sedn(0b01);
TMC2130Z->sg_stall_value(stallSensitivityZ);
TMC2130E->push();
TMC2130E->toff(3);
TMC2130E->tbl(1);
TMC2130E->hysteresis_start(4);
TMC2130E->hysteresis_end(-2);
TMC2130E->rms_current(600); // mA
TMC2130E->microsteps(0);
TMC2130E->diag1_stall(1);
TMC2130E->diag1_active_high(1);
TMC2130E->coolstep_min_speed(0xFFFFF); // 20bit max
TMC2130E->THIGH(0);
TMC2130E->semin(5);
TMC2130E->semax(2);
TMC2130E->sedn(0b01);
TMC2130E->sg_stall_value(0);
}
#endif
void Movement::test()
{
axisX.enableMotor();
//axisY.test();
//axisX.enableMotor();
//axisX.setMotorStep();
//delayMicroseconds(10);
//axisX.setMotorStep();
//delayMicroseconds(10);
//digitalWrite(X_STEP_PIN, HIGH);
//delayMicroseconds(10);
//digitalWrite(X_STEP_PIN, LOW);
//delayMicroseconds(10);
//axisX.setMotorStepWriteTMC2130();
//axisX.test();
//Serial.print("R99");
//Serial.print(" mot x = ");
//Serial.print(axisX.currentPosition());
//Serial.print(" enc x = ");
//Serial.print(encoderX.currentPosition());
//Serial.print("\r\n");
//Serial.print("R99");
//Serial.print(" mot y = ");
//Serial.print(axisY.currentPosition());
//Serial.print(" enc y = ");
//Serial.print(encoderY.currentPosition());
//Serial.print("\r\n");
//Serial.print("R99");
//Serial.print(" mot z = ");
//Serial.print(axisZ.currentPosition());
//Serial.print(" enc z = ");
//Serial.print(encoderZ.currentPosition());
//Serial.print("\r\n");
// read changes in encoder
//encoderX.readEncoder();
//encoderY.readEncoder();
//encoderZ.readEncoder();
//reportPosition();
//bool test = axisX.endStopMin();
//Serial.print("R99");
//Serial.print(" test = ");
//Serial.print(test);
//Serial.print("\r\n");
}
void Movement::test2()
{
axisX.setMotorStep();
//CurrentState::getInstance()->printPosition();
//encoderX.test();
//encoderY.test();
//encoderZ.test();
}
/**
* xDest - destination X in steps
* yDest - destination Y in steps
* zDest - destination Z in steps
* maxStepsPerSecond - maximum number of steps per second
* maxAccelerationStepsPerSecond - maximum number of acceleration in steps per second
*/
int Movement::moveToCoords(double xDestScaled, double yDestScaled, double zDestScaled,
unsigned int xMaxSpd, unsigned int yMaxSpd, unsigned int zMaxSpd,
bool xHome, bool yHome, bool zHome)
{
/**/ //Serial.println("AAA");
/**/ //test();
long xDest = xDestScaled * stepsPerMm[0];
long yDest = yDestScaled * stepsPerMm[1];
long zDest = zDestScaled * stepsPerMm[2];
unsigned long currentMillis = 0;
unsigned long timeStart = millis();
serialMessageNr = 0;
serialMessageDelay = 0;
int incomingByte = 0;
int error = 0;
bool emergencyStop = false;
unsigned int commandSpeed[3];
// if a speed is given in the command, use that instead of the config speed
if (xMaxSpd > 0 && xMaxSpd < speedMax[0])
{
commandSpeed[0] = xMaxSpd;
}
else
{
commandSpeed[0] = speedMax[0];
}
if (yMaxSpd > 0 && yMaxSpd < speedMax[1])
{
commandSpeed[1] = yMaxSpd;
}
else
{
commandSpeed[1] = speedMax[1];
}
if (zMaxSpd > 0 && zMaxSpd < speedMax[2])
{
commandSpeed[2] = zMaxSpd;
}
else
{
commandSpeed[2] = speedMax[2];
}
axisX.setMaxSpeed(commandSpeed[0]);
axisY.setMaxSpeed(commandSpeed[1]);
axisZ.setMaxSpeed(commandSpeed[2]);
// Load coordinates into axis class
long sourcePoint[3] = {0, 0, 0};
sourcePoint[0] = CurrentState::getInstance()->getX();
sourcePoint[1] = CurrentState::getInstance()->getY();
sourcePoint[2] = CurrentState::getInstance()->getZ();
long currentPoint[3] = {0, 0, 0};
currentPoint[0] = CurrentState::getInstance()->getX();
currentPoint[1] = CurrentState::getInstance()->getY();
currentPoint[2] = CurrentState::getInstance()->getZ();
long destinationPoint[3] = {0, 0, 0};
destinationPoint[0] = xDest;
destinationPoint[1] = yDest;
destinationPoint[2] = zDest;
motorConsMissedSteps[0] = 0;
motorConsMissedSteps[1] = 0;
motorConsMissedSteps[2] = 0;
motorConsMissedStepsPrev[0] = 0;
motorConsMissedStepsPrev[1] = 0;
motorConsMissedStepsPrev[2] = 0;
motorLastPosition[0] = currentPoint[0];
motorLastPosition[1] = currentPoint[1];
motorLastPosition[2] = currentPoint[2];
// Load coordinates into motor control
// Report back coordinates if target coordinates changed
if (axisX.loadCoordinates(currentPoint[0], destinationPoint[0], xHome))
{
Serial.print(COMM_REPORT_COORD_CHANGED_X);
Serial.print(" X");
Serial.print(axisX.destinationPosition() / stepsPerMm[0]);
CurrentState::getInstance()->printQAndNewLine();
}
if (axisY.loadCoordinates(currentPoint[1], destinationPoint[1], yHome))
{
Serial.print(COMM_REPORT_COORD_CHANGED_Y);
Serial.print(" Y");
Serial.print(axisY.destinationPosition() / stepsPerMm[1]);
CurrentState::getInstance()->printQAndNewLine();
}
if (axisZ.loadCoordinates(currentPoint[2], destinationPoint[2], zHome))
{
Serial.print(COMM_REPORT_COORD_CHANGED_Z);
Serial.print(" Z");
Serial.print(axisZ.destinationPosition() / stepsPerMm[2]);
CurrentState::getInstance()->printQAndNewLine();
}
// Prepare for movement
axisX.movementStarted = false;
axisY.movementStarted = false;
axisZ.movementStarted = false;
storeEndStops();
reportEndStops();
axisX.setDirectionAxis();
axisY.setDirectionAxis();
axisZ.setDirectionAxis();
// Enable motors
axisSubStep[0] = COMM_REPORT_MOVE_STATUS_START_MOTOR;
axisSubStep[1] = COMM_REPORT_MOVE_STATUS_START_MOTOR;
axisSubStep[2] = COMM_REPORT_MOVE_STATUS_START_MOTOR;
reportStatus(&axisX, axisSubStep[0]);
reportStatus(&axisY, axisSubStep[1]);
reportStatus(&axisZ, axisSubStep[2]);
enableMotors();
// Start movement
axisActive[0] = true;
axisActive[1] = true;
axisActive[2] = true;
if (xHome || yHome || zHome)
{
if (!xHome) { axisX.deactivateAxis(); }
if (!yHome) { axisY.deactivateAxis(); }
if (!zHome) { axisZ.deactivateAxis(); }
axisActive[0] = xHome;
axisActive[1] = yHome;
axisActive[2] = zHome;
}
axisX.checkMovement();
axisY.checkMovement();
axisZ.checkMovement();
axisX.setTicks();
axisY.setTicks();
axisZ.setTicks();
emergencyStop = CurrentState::getInstance()->isEmergencyStop();
unsigned long loopCounts = 0;
// Let the interrupt handle all the movements
while ((axisActive[0] || axisActive[1] || axisActive[2]) && !emergencyStop)
{
#if defined(FARMDUINO_V14)
checkEncoders();
#endif
/**/
if (loopCounts % 1000 == 0)
{
//Serial.print("R99");
//Serial.print(" missed step ");
//Serial.print(motorConsMissedSteps[1]);
//Serial.print(" axis pos ");
//Serial.print(axisY.currentPosition());
//Serial.print("\r\n");
//Serial.print("X - ");
//axisX.test();
//Serial.print("Y - ");
//axisY.test();
}
loopCounts++;
checkAxisSubStatus(&axisX, &axisSubStep[0]);
checkAxisSubStatus(&axisY, &axisSubStep[1]);
checkAxisSubStatus(&axisZ, &axisSubStep[2]);
axisX.checkTiming();
axisY.checkTiming();
axisZ.checkTiming();
if (axisX.isStepDone())
{
axisX.checkMovement();
//checkAxisVsEncoder(&axisX, &encoderX, &motorConsMissedSteps[0], &motorLastPosition[0], &motorConsEncoderLastPosition[0], &motorConsEncoderUseForPos[0], &motorConsMissedStepsDecay[0], &motorConsEncoderEnabled[0]);
axisX.resetStepDone();
}
if (axisY.isStepDone())
{
axisY.checkMovement();
//checkAxisVsEncoder(&axisY, &encoderY, &motorConsMissedSteps[1], &motorLastPosition[1], &motorConsEncoderLastPosition[1], &motorConsEncoderUseForPos[1], &motorConsMissedStepsDecay[1], &motorConsEncoderEnabled[1]);
axisY.resetStepDone();
}
if (axisZ.isStepDone())
{
axisZ.checkMovement();
//checkAxisVsEncoder(&axisZ, &encoderZ, &motorConsMissedSteps[2], &motorLastPosition[2], &motorConsEncoderLastPosition[2], &motorConsEncoderUseForPos[2], &motorConsMissedStepsDecay[2], &motorConsEncoderEnabled[2]);
axisZ.resetStepDone();
}
if (axisX.isAxisActive() && motorConsMissedSteps[0] > motorConsMissedStepsMax[0])
{
axisX.deactivateAxis();
serialBuffer += "R99";
serialBuffer += " deactivate motor X due to missed steps";
serialBuffer += "\r\n";
if (xHome)
{
encoderX.setPosition(0);
axisX.setCurrentPosition(0);
}
else
{
error = ERR_STALL_DETECTED;
}
}
if (axisY.isAxisActive() && motorConsMissedSteps[1] > motorConsMissedStepsMax[1])
{
axisY.deactivateAxis();
serialBuffer += "R99";
serialBuffer += " deactivate motor Y due to missed steps";
serialBuffer += "\r\n";
if (yHome)
{
encoderY.setPosition(0);
axisY.setCurrentPosition(0);
}
else
{
error = ERR_STALL_DETECTED;
}
}
if (axisZ.isAxisActive() && motorConsMissedSteps[2] > motorConsMissedStepsMax[2])
{
axisZ.deactivateAxis();
serialBuffer += "R99";
serialBuffer += " deactivate motor Z due to missed steps";
serialBuffer += "\r\n";
if (zHome)
{
encoderZ.setPosition(0);
axisZ.setCurrentPosition(0);
}
else
{
error = ERR_STALL_DETECTED;
}
}
if (axisX.endStopAxisReached(false))
{
axisX.setCurrentPosition(0);
encoderX.setPosition(0);
}
if (axisY.endStopAxisReached(false))
{
axisY.setCurrentPosition(0);
encoderY.setPosition(0);
}
if (axisZ.endStopAxisReached(false))
{
axisZ.setCurrentPosition(0);
encoderZ.setPosition(0);
}
axisActive[0] = axisX.isAxisActive();
axisActive[1] = axisY.isAxisActive();
axisActive[2] = axisZ.isAxisActive();
currentPoint[0] = axisX.currentPosition();
currentPoint[1] = axisY.currentPosition();
currentPoint[2] = axisZ.currentPosition();
CurrentState::getInstance()->setX(currentPoint[0]);
CurrentState::getInstance()->setY(currentPoint[1]);
CurrentState::getInstance()->setZ(currentPoint[2]);
storeEndStops();
// Check timeouts
if (axisActive[0] == true && ((millis() >= timeStart && millis() - timeStart > timeOut[0] * 1000) || (millis() < timeStart && millis() > timeOut[0] * 1000)))
{
serialBuffer += COMM_REPORT_TIMEOUT_X;
serialBuffer += "\r\n";
serialBuffer += "R99 timeout X axis\r\n";
error = ERR_TIMEOUT;
}
if (axisActive[1] == true && ((millis() >= timeStart && millis() - timeStart > timeOut[1] * 1000) || (millis() < timeStart && millis() > timeOut[1] * 1000)))
{
serialBuffer += COMM_REPORT_TIMEOUT_Y;
serialBuffer += "\r\n";
serialBuffer += "R99 timeout Y axis\r\n";
error = ERR_TIMEOUT;
}
if (axisActive[2] == true && ((millis() >= timeStart && millis() - timeStart > timeOut[2] * 1000) || (millis() < timeStart && millis() > timeOut[2] * 1000)))
{
serialBuffer += COMM_REPORT_TIMEOUT_Z;
serialBuffer += "\r\n";
serialBuffer += "R99 timeout Z axis\r\n";
error = ERR_TIMEOUT;
}
// Check if there is an emergency stop command
if (Serial.available() > 0)
{
incomingByte = Serial.read();
if (incomingByte == 69 || incomingByte == 101)
{
serialBuffer += "R99 emergency stop\r\n";
Serial.print(COMM_REPORT_EMERGENCY_STOP);
CurrentState::getInstance()->printQAndNewLine();
emergencyStop = true;
axisX.deactivateAxis();
axisY.deactivateAxis();
axisZ.deactivateAxis();
axisActive[0] = false;
axisActive[1] = false;
axisActive[2] = false;
error = ERR_EMERGENCY_STOP;
}
}
if (error != 0)
{
serialBuffer += "R99 error\r\n";
axisActive[0] = false;
axisActive[1] = false;
axisActive[2] = false;
}
// Send the serial buffer one character per cycle to keep motor timing more accuracte
serialBufferSendNext();
// Periodically send message still active
currentMillis++;
serialMessageDelay++;
if (serialMessageDelay > 300 && serialBuffer.length() == 0 && serialBufferSending == 0)
{
//Serial.print("Y-");
//axisY.test();/**/
serialMessageDelay = 0;
switch(serialMessageNr)
{
case 0:
serialBuffer += COMM_REPORT_CMD_BUSY;
serialBuffer += CurrentState::getInstance()->getQAndNewLine();
break;
case 1:
serialBuffer += CurrentState::getInstance()->getPosition();
serialBuffer += CurrentState::getInstance()->getQAndNewLine();
#if defined(FARMDUINO_V14)
getEncoderReport();
#endif
break;
case 2:
#if defined(FARMDUINO_EXP_V20)
serialBuffer += "R89";
serialBuffer += " X";
serialBuffer += axisX.getLoad();
serialBuffer += " Y";
serialBuffer += axisY.getLoad();
serialBuffer += " Z";
serialBuffer += axisZ.getLoad();
serialBuffer += CurrentState::getInstance()->getQAndNewLine();
#endif
break;
default:
break;
}
serialMessageNr++;
#if !defined(FARMDUINO_EXP_V20)
if (serialMessageNr > 1)
{
serialMessageNr = 0;
}
#endif
#if defined(FARMDUINO_EXP_V20)
if (serialMessageNr > 2)
{
serialMessageNr = 0;
}
#endif
serialBufferSending = 0;
if (debugMessages /*&& debugInterrupt*/)
{
Serial.print("R99");
Serial.print(" missed step ");
Serial.print(motorConsMissedSteps[1]);
Serial.print(" encoder pos ");
Serial.print(encoderY.currentPosition());
Serial.print(" axis pos ");
Serial.print(axisY.currentPosition());
Serial.print("\r\n");
}
}
}
serialBufferEmpty();
Serial.print("R99 stopped\r\n");
// Send feedback for homing
if (xHome && !error && !emergencyStop)
{
Serial.print(COMM_REPORT_HOMED_X);
CurrentState::getInstance()->printQAndNewLine();
}
if (yHome && !error && !emergencyStop)
{
Serial.print(COMM_REPORT_HOMED_Y);
CurrentState::getInstance()->printQAndNewLine();
}
if (zHome && !error && !emergencyStop)
{
Serial.print(COMM_REPORT_HOMED_Z);
CurrentState::getInstance()->printQAndNewLine();
}
// Stop motors
axisSubStep[0] = COMM_REPORT_MOVE_STATUS_STOP_MOTOR;
axisSubStep[1] = COMM_REPORT_MOVE_STATUS_STOP_MOTOR;
axisSubStep[2] = COMM_REPORT_MOVE_STATUS_STOP_MOTOR;
reportStatus(&axisX, axisSubStep[0]);
reportStatus(&axisY, axisSubStep[1]);
reportStatus(&axisZ, axisSubStep[2]);
disableMotors();
// Report end statuses
currentPoint[0] = axisX.currentPosition();
currentPoint[1] = axisY.currentPosition();
currentPoint[2] = axisZ.currentPosition();
CurrentState::getInstance()->setX(currentPoint[0]);
CurrentState::getInstance()->setY(currentPoint[1]);
CurrentState::getInstance()->setZ(currentPoint[2]);
storeEndStops();
reportEndStops();
reportPosition();
reportEncoders();
// Report axis idle
axisSubStep[0] = COMM_REPORT_MOVE_STATUS_IDLE;
axisSubStep[1] = COMM_REPORT_MOVE_STATUS_IDLE;
axisSubStep[2] = COMM_REPORT_MOVE_STATUS_IDLE;
reportStatus(&axisX, axisSubStep[0]);
reportStatus(&axisY, axisSubStep[1]);
reportStatus(&axisZ, axisSubStep[2]);
disableMotors();
if (emergencyStop)
{
CurrentState::getInstance()->setEmergencyStop();
error = ERR_EMERGENCY_STOP;
}
Serial.print("R99 error ");
Serial.print(error);
Serial.print("\r\n");
// Return error
CurrentState::getInstance()->setLastError(error);
return error;
}
void Movement::serialBufferEmpty()
{
while (serialBuffer.length() > 0)
{
serialBufferSendNext();
}
}
void Movement::serialBufferSendNext()
{
// Send the next char in the serialBuffer
if (serialBuffer.length() > 0)
{
if (serialBufferSending < serialBuffer.length())
{
//Serial.print("-");
switch (serialBuffer.charAt(serialBufferSending))
{
case 13:
Serial.print("\r\n");
break;
case 10:
break;
default:
Serial.print(serialBuffer.charAt(serialBufferSending));
break;
}
serialBufferSending++;
}
else
{
// Reset length of buffer when done
serialBuffer = "";
serialBufferSending = 0;
}
}
}
//
// Calibration
//
int Movement::calibrateAxis(int axis)
{
// Load motor and encoder settings
loadMotorSettings();
loadEncoderSettings();
//unsigned long timeStart = millis();
bool movementDone = false;
int paramValueInt = 0;
int stepsCount = 0;
int incomingByte = 0;
int error = 0;
bool invertEndStops = false;
int parEndInv;
int parNbrStp;
float *missedSteps;
int *missedStepsMax;
long *lastPosition;
float *encoderStepDecay;
bool *encoderEnabled;
int *axisStatus;
long *axisStepsPerMm;
// Prepare for movement
storeEndStops();
reportEndStops();
// Select the right axis
MovementAxis *calibAxis;
MovementEncoder *calibEncoder;
switch (axis)
{
case 0:
calibAxis = &axisX;
calibEncoder = &encoderX;
parEndInv = MOVEMENT_INVERT_ENDPOINTS_X;
parNbrStp = MOVEMENT_AXIS_NR_STEPS_X;
invertEndStops = endStInv[0];
missedSteps = &motorConsMissedSteps[0];
missedStepsMax = &motorConsMissedStepsMax[0];
lastPosition = &motorLastPosition[0];
encoderStepDecay = &motorConsMissedStepsDecay[0];
encoderEnabled = &motorConsEncoderEnabled[0];
axisStatus = &axisSubStep[0];
axisStepsPerMm = &stepsPerMm[0];
break;
case 1:
calibAxis = &axisY;
calibEncoder = &encoderY;
parEndInv = MOVEMENT_INVERT_ENDPOINTS_Y;
parNbrStp = MOVEMENT_AXIS_NR_STEPS_Y;
invertEndStops = endStInv[1];
missedSteps = &motorConsMissedSteps[1];
missedStepsMax = &motorConsMissedStepsMax[1];
lastPosition = &motorLastPosition[1];
encoderStepDecay = &motorConsMissedStepsDecay[1];
encoderEnabled = &motorConsEncoderEnabled[1];
axisStatus = &axisSubStep[1];
axisStepsPerMm = &stepsPerMm[1];
break;
case 2:
calibAxis = &axisZ;
calibEncoder = &encoderZ;
parEndInv = MOVEMENT_INVERT_ENDPOINTS_Z;
parNbrStp = MOVEMENT_AXIS_NR_STEPS_Z;
invertEndStops = endStInv[2];
missedSteps = &motorConsMissedSteps[2];
missedStepsMax = &motorConsMissedStepsMax[2];
lastPosition = &motorLastPosition[2];
encoderStepDecay = &motorConsMissedStepsDecay[2];
encoderEnabled = &motorConsEncoderEnabled[2];
axisStatus = &axisSubStep[2];
axisStepsPerMm = &stepsPerMm[2];
break;
default:
Serial.print("R99 Calibration error: invalid axis selected\r\n");
error = 1;
CurrentState::getInstance()->setLastError(error);
return error;
}
// Preliminary checks
if (calibAxis->endStopMin() || calibAxis->endStopMax())
{
Serial.print("R99 Calibration error: end stop active before start\r\n");
error = 1;
CurrentState::getInstance()->setLastError(error);
return error;
}
Serial.print("R99");
Serial.print(" axis ");
Serial.print(calibAxis->channelLabel);
Serial.print(" move to start for calibration");
Serial.print("\r\n");
*axisStatus = COMM_REPORT_MOVE_STATUS_START_MOTOR;
reportStatus(calibAxis, axisStatus[0]);
// Move towards home
calibAxis->enableMotor();
/**/
//calibAxis->setDirectionHome();
calibAxis->setDirectionAway();
calibAxis->setCurrentPosition(calibEncoder->currentPosition());
stepsCount = 0;
*missedSteps = 0;
movementDone = false;
motorConsMissedSteps[0] = 0;
motorConsMissedSteps[1] = 0;
motorConsMissedSteps[2] = 0;
*axisStatus = COMM_REPORT_MOVE_STATUS_CRAWLING;
reportStatus(calibAxis, axisStatus[0]);
reportCalib(calibAxis, COMM_REPORT_CALIBRATE_STATUS_TO_HOME);
while (!movementDone && error == 0)
{
#if defined(FARMDUINO_V14)
checkEncoders();
#endif
checkAxisVsEncoder(calibAxis, calibEncoder, &motorConsMissedSteps[axis], &motorLastPosition[axis], &motorConsEncoderLastPosition[axis], &motorConsEncoderUseForPos[axis], &motorConsMissedStepsDecay[axis], &motorConsEncoderEnabled[axis]);
// Check if there is an emergency stop command
if (Serial.available() > 0)
{
incomingByte = Serial.read();
if (incomingByte == 69 || incomingByte == 101)
{
Serial.print("R99 emergency stop\r\n");
movementDone = true;
CurrentState::getInstance()->setEmergencyStop();
Serial.print(COMM_REPORT_EMERGENCY_STOP);
CurrentState::getInstance()->printQAndNewLine();
error = 1;
}
}
// Move until any end stop is reached or the motor is skipping. That end should be the far end stop. First, ram the end at high speed.
/**/
//if (((!invertEndStops && !calibAxis->endStopMax()) || (invertEndStops && !calibAxis->endStopMin())) && !movementDone && (*missedSteps < *missedStepsMax))
//if ((!calibAxis->endStopMin() && !calibAxis->endStopMax()) && !movementDone && (*missedSteps < *missedStepsMax))
if ((!calibAxis->endStopMin() && !calibAxis->endStopMax()) && !movementDone && (*missedSteps < *missedStepsMax))
{
calibAxis->setStepAxis();
delayMicroseconds(100000 / speedHome[axis] / 2);
stepsCount++;
if (stepsCount % (speedHome[axis] * 3) == 0)
{
// Periodically send message still active
Serial.print(COMM_REPORT_CMD_BUSY);
CurrentState::getInstance()->printQAndNewLine();
}
if (debugMessages)
{
if (stepsCount % (speedHome[axis] / 6) == 0 /*|| *missedSteps > 3*/)
{
Serial.print("R99");
Serial.print(" step count ");
Serial.print(stepsCount);
Serial.print(" missed steps ");
Serial.print(*missedSteps);
Serial.print(" max steps ");
Serial.print(*missedStepsMax);
Serial.print(" cur pos mtr ");
Serial.print(calibAxis->currentPosition());
Serial.print(" cur pos enc ");
Serial.print(calibEncoder->currentPosition());
Serial.print("\r\n");
}
}
calibAxis->resetMotorStep();
delayMicroseconds(100000 / speedHome[axis] / 2);
}
else
{
movementDone = true;
Serial.print("R99 movement done\r\n");
// If end stop for home is active, set the position to zero
if (calibAxis->endStopMin())
{
invertEndStops = true;
}
}
}
reportCalib(calibAxis, COMM_REPORT_CALIBRATE_STATUS_TO_END);
Serial.print("R99");
Serial.print(" axis ");
Serial.print(calibAxis->channelLabel);
Serial.print(" at starting point");
Serial.print("\r\n");
// Report back the end stop setting
if (error == 0)
{
if (invertEndStops)
{
paramValueInt = 1;
}
else
{
paramValueInt = 0;
}
Serial.print("R23");
Serial.print(" ");
Serial.print("P");
Serial.print(parEndInv);
Serial.print(" ");
Serial.print("V");
Serial.print(paramValueInt);
//Serial.print("\r\n");
CurrentState::getInstance()->printQAndNewLine();
}
// Store the status of the system
storeEndStops();
reportEndStops();
// Move into the other direction now, and measure the number of steps
Serial.print("R99");
Serial.print(" axis ");
Serial.print(calibAxis->channelLabel);
Serial.print(" calibrating length");
Serial.print("\r\n");
stepsCount = 0;
movementDone = false;
*missedSteps = 0;
/**/
//calibAxis->setDirectionAway();
calibAxis->setDirectionHome();
calibAxis->setCurrentPosition(calibEncoder->currentPosition());
motorConsMissedSteps[0] = 0;
motorConsMissedSteps[1] = 0;
motorConsMissedSteps[2] = 0;
long encoderStartPoint = calibEncoder->currentPosition();
long encoderEndPoint = calibEncoder->currentPosition();
while (!movementDone && error == 0)
{
#if defined(FARMDUINO_V14)
checkEncoders();
#endif
checkAxisVsEncoder(calibAxis, calibEncoder, &motorConsMissedSteps[axis], &motorLastPosition[axis], &motorConsEncoderLastPosition[axis], &motorConsEncoderUseForPos[axis], &motorConsMissedStepsDecay[axis], &motorConsEncoderEnabled[axis]);
// Check if there is an emergency stop command
if (Serial.available() > 0)
{
incomingByte = Serial.read();
if (incomingByte == 69 || incomingByte == 101)
{
Serial.print("R99 emergency stop\r\n");
movementDone = true;
CurrentState::getInstance()->setEmergencyStop();
Serial.print(COMM_REPORT_EMERGENCY_STOP);
CurrentState::getInstance()->printQAndNewLine();
error = 1;
}
}
// Ignore the missed steps at startup time
if (stepsCount < 10)
{
*missedSteps = 0;
}
// Move until the end stop is at the home position by detecting the other end stop or missed steps are detected
/**/
//if ((!calibAxis->endStopMin() && !calibAxis->endStopMax()) && !movementDone && (*missedSteps < *missedStepsMax))
//if (((!invertEndStops && !calibAxis->endStopMax()) || (invertEndStops && !calibAxis->endStopMin())) && !movementDone && (*missedSteps < *missedStepsMax))
if (((!invertEndStops && !calibAxis->endStopMin()) || (invertEndStops && !calibAxis->endStopMax())) && !movementDone && (*missedSteps < *missedStepsMax))
{
calibAxis->setStepAxis();
stepsCount++;
//checkAxisVsEncoder(&axisX, &encoderX, &motorConsMissedSteps[0], &motorLastPosition[0], &motorConsMissedStepsDecay[0], &motorConsEncoderEnabled[0]);
delayMicroseconds(100000 / speedHome[axis] / 2);
if (stepsCount % (speedHome[axis] * 3) == 0)
{
// Periodically send message still active
Serial.print(COMM_REPORT_CMD_BUSY);
//Serial.print("\r\n");
CurrentState::getInstance()->printQAndNewLine();
Serial.print("R99");
Serial.print(" step count: ");
Serial.print(stepsCount);
Serial.print("\r\n");
}
calibAxis->resetMotorStep();
delayMicroseconds(100000 / speedHome[axis] / 2);
}
else
{
Serial.print("R99 movement done\r\n");
movementDone = true;
}
}
Serial.print("R99");
Serial.print(" axis ");
Serial.print(calibAxis->channelLabel);
Serial.print(" at end point");
Serial.print("\r\n");
encoderEndPoint = calibEncoder->currentPosition();
// if the encoder is enabled, use the encoder data instead of the step count
if (encoderEnabled)
{
stepsCount = abs(encoderEndPoint - encoderStartPoint);
}
// Report back the end stop setting
if (error == 0)
{
Serial.print("R23");
Serial.print(" ");
Serial.print("P");
Serial.print(parNbrStp);
Serial.print(" ");
Serial.print("V");
Serial.print((float)stepsCount);
CurrentState::getInstance()->printQAndNewLine();
}
*axisStatus = COMM_REPORT_MOVE_STATUS_STOP_MOTOR;
reportStatus(calibAxis, axisStatus[0]);
calibAxis->disableMotor();
storeEndStops();
reportEndStops();
switch (axis)
{
case 0:
CurrentState::getInstance()->setX(stepsCount);
break;
case 1:
CurrentState::getInstance()->setY(stepsCount);
break;
case 2:
CurrentState::getInstance()->setZ(stepsCount);
break;
}
reportPosition();
*axisStatus = COMM_REPORT_MOVE_STATUS_IDLE;
reportStatus(calibAxis, axisStatus[0]);
reportCalib(calibAxis, COMM_REPORT_CALIBRATE_STATUS_IDLE);
CurrentState::getInstance()->setLastError(error);
return error;
}
int debugPrintCount = 0;
// Check encoder to verify the motor is at the right position
void Movement::checkAxisVsEncoder(MovementAxis *axis, MovementEncoder *encoder, float *missedSteps, long *lastPosition, long *encoderLastPosition, int *encoderUseForPos, float *encoderStepDecay, bool *encoderEnabled)
{
#if !defined(FARMDUINO_EXP_V20)
if (*encoderEnabled)
{
bool stepMissed = false;
if (debugMessages)
{
//debugPrintCount++;
//if (debugPrintCount % 50 == 0)
{
Serial.print("R99");
Serial.print(" encoder pos ");
Serial.print(encoder->currentPosition());
Serial.print(" last enc ");
Serial.print(*encoderLastPosition);
Serial.print(" axis pos ");
Serial.print(axis->currentPosition());
Serial.print(" last pos ");
Serial.print(*lastPosition);
Serial.print(" move up ");
Serial.print(axis->movingUp());
Serial.print(" missed step cons ");
Serial.print(motorConsMissedSteps[0]);
Serial.print(" missed step ");
Serial.print(*missedSteps);
//Serial.print(" encoder X pos ");
//Serial.print(encoderX.currentPosition());
//Serial.print(" axis X pos ");
//Serial.print(axisX.currentPosition());
Serial.print(" decay ");
Serial.print(*encoderStepDecay);
Serial.print(" enabled ");
Serial.print(*encoderEnabled);
Serial.print("\r\n");
}
}
// Decrease amount of missed steps if there are no missed step
if (*missedSteps > 0)
{
(*missedSteps) -= (*encoderStepDecay);
}
// Check if the encoder goes in the wrong direction or nothing moved
if ((axis->movingUp() && *encoderLastPosition > encoder->currentPositionRaw()) ||
(!axis->movingUp() && *encoderLastPosition < encoder->currentPositionRaw()))
{
stepMissed = true;
}
if (stepMissed && *missedSteps < 32000)
{
(*missedSteps)++;
}
*encoderLastPosition = encoder->currentPositionRaw();
*lastPosition = axis->currentPosition();
//axis->resetStepDone();
if (*encoderUseForPos)
{
axis->setCurrentPosition(encoder->currentPosition());
}
}
#endif
#if defined(FARMDUINO_EXP_V20)
/**/
/*
Serial.print("R99");
Serial.print(" XXX ");
Serial.print(" cur pos ");
Serial.print(axis->currentPosition());
Serial.print(" last pos ");
Serial.print(*lastPosition);
*/
if (*encoderEnabled) {
if (axis->stallDetected()) {
// In case of stall detection, count this as a missed step
(*missedSteps)++;
axis->setCurrentPosition(*lastPosition);
}
else {
// Decrease amount of missed steps if there are no missed step
if (*missedSteps > 0)
{
(*missedSteps) -= (*encoderStepDecay);
}
*lastPosition = axis->currentPosition();
encoder->setPosition(axis->currentPosition());
}
}
//Serial.print(" new last pos ");
//Serial.print(*lastPosition);
//Serial.print(" en pos ");
//Serial.print(encoder->currentPosition());
//Serial.print("\r\n");
#endif
}
void Movement::loadMotorSettings()
{
// Load settings
homeIsUp[0] = ParameterList::getInstance()->getValue(MOVEMENT_HOME_UP_X);
homeIsUp[1] = ParameterList::getInstance()->getValue(MOVEMENT_HOME_UP_Y);
homeIsUp[2] = ParameterList::getInstance()->getValue(MOVEMENT_HOME_UP_Z);
speedMax[0] = ParameterList::getInstance()->getValue(MOVEMENT_MAX_SPD_X);
speedMax[1] = ParameterList::getInstance()->getValue(MOVEMENT_MAX_SPD_Y);
speedMax[2] = ParameterList::getInstance()->getValue(MOVEMENT_MAX_SPD_Z);
speedMin[0] = ParameterList::getInstance()->getValue(MOVEMENT_MIN_SPD_X);
speedMin[1] = ParameterList::getInstance()->getValue(MOVEMENT_MIN_SPD_Y);
speedMin[2] = ParameterList::getInstance()->getValue(MOVEMENT_MIN_SPD_Z);
speedHome[0] = ParameterList::getInstance()->getValue(MOVEMENT_HOME_SPEED_X);
speedHome[1] = ParameterList::getInstance()->getValue(MOVEMENT_HOME_SPEED_Y);
speedHome[2] = ParameterList::getInstance()->getValue(MOVEMENT_HOME_SPEED_Z);
stepsAcc[0] = ParameterList::getInstance()->getValue(MOVEMENT_STEPS_ACC_DEC_X);
stepsAcc[1] = ParameterList::getInstance()->getValue(MOVEMENT_STEPS_ACC_DEC_Y);
stepsAcc[2] = ParameterList::getInstance()->getValue(MOVEMENT_STEPS_ACC_DEC_Z);
motorInv[0] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_INVERT_MOTOR_X));
motorInv[1] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_INVERT_MOTOR_Y));
motorInv[2] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_INVERT_MOTOR_Z));
endStInv[0] = ParameterList::getInstance()->getValue(MOVEMENT_INVERT_ENDPOINTS_X);
endStInv[1] = ParameterList::getInstance()->getValue(MOVEMENT_INVERT_ENDPOINTS_Y);
endStInv[2] = ParameterList::getInstance()->getValue(MOVEMENT_INVERT_ENDPOINTS_Z);
endStInv2[0] = ParameterList::getInstance()->getValue(MOVEMENT_INVERT_2_ENDPOINTS_X);
endStInv2[1] = ParameterList::getInstance()->getValue(MOVEMENT_INVERT_2_ENDPOINTS_Y);
endStInv2[2] = ParameterList::getInstance()->getValue(MOVEMENT_INVERT_2_ENDPOINTS_Z);
endStEnbl[0] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_ENABLE_ENDPOINTS_X));
endStEnbl[1] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_ENABLE_ENDPOINTS_Y));
endStEnbl[2] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_ENABLE_ENDPOINTS_Z));
timeOut[0] = ParameterList::getInstance()->getValue(MOVEMENT_TIMEOUT_X);
timeOut[1] = ParameterList::getInstance()->getValue(MOVEMENT_TIMEOUT_Y);
timeOut[2] = ParameterList::getInstance()->getValue(MOVEMENT_TIMEOUT_Z);
motorKeepActive[0] = ParameterList::getInstance()->getValue(MOVEMENT_KEEP_ACTIVE_X);
motorKeepActive[1] = ParameterList::getInstance()->getValue(MOVEMENT_KEEP_ACTIVE_Y);
motorKeepActive[2] = ParameterList::getInstance()->getValue(MOVEMENT_KEEP_ACTIVE_Z);
motorMaxSize[0] = ParameterList::getInstance()->getValue(MOVEMENT_AXIS_NR_STEPS_X);
motorMaxSize[1] = ParameterList::getInstance()->getValue(MOVEMENT_AXIS_NR_STEPS_Y);
motorMaxSize[2] = ParameterList::getInstance()->getValue(MOVEMENT_AXIS_NR_STEPS_Z);
motor2Inv[0] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_SECONDARY_MOTOR_INVERT_X));
motor2Inv[1] = false;
motor2Inv[2] = false;
motor2Enbl[0] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_SECONDARY_MOTOR_X));
motor2Enbl[1] = false;
motor2Enbl[2] = false;
motorStopAtHome[0] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_STOP_AT_HOME_X));
motorStopAtHome[1] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_STOP_AT_HOME_Y));
motorStopAtHome[2] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_STOP_AT_HOME_Z));
motorStopAtMax[0] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_STOP_AT_MAX_X));
motorStopAtMax[1] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_STOP_AT_MAX_Y));
motorStopAtMax[2] = intToBool(ParameterList::getInstance()->getValue(MOVEMENT_STOP_AT_MAX_Z));
stepsPerMm[0] = ParameterList::getInstance()->getValue(MOVEMENT_STEP_PER_MM_X);
stepsPerMm[1] = ParameterList::getInstance()->getValue(MOVEMENT_STEP_PER_MM_Y);
stepsPerMm[2] = ParameterList::getInstance()->getValue(MOVEMENT_STEP_PER_MM_Z);
if (stepsPerMm[0] < 1)
{
stepsPerMm[0] = 1;
}
if (stepsPerMm[1] < 1)
{
stepsPerMm[1] = 1;
}
if (stepsPerMm[2] < 1)
{
stepsPerMm[2] = 1;
}
CurrentState::getInstance()->setStepsPerMm(stepsPerMm[0], stepsPerMm[1], stepsPerMm[2]);
axisX.loadMotorSettings(speedMax[0], speedMin[0], speedHome[0], stepsAcc[0], timeOut[0], homeIsUp[0], motorInv[0], endStInv[0], endStInv2[0], MOVEMENT_INTERRUPT_SPEED, motor2Enbl[0], motor2Inv[0], endStEnbl[0], motorStopAtHome[0], motorMaxSize[0], motorStopAtMax[0]);
axisY.loadMotorSettings(speedMax[1], speedMin[1], speedHome[1], stepsAcc[1], timeOut[1], homeIsUp[1], motorInv[1], endStInv[1], endStInv2[1], MOVEMENT_INTERRUPT_SPEED, motor2Enbl[1], motor2Inv[1], endStEnbl[1], motorStopAtHome[1], motorMaxSize[1], motorStopAtMax[1]);
axisZ.loadMotorSettings(speedMax[2], speedMin[2], speedHome[2], stepsAcc[2], timeOut[2], homeIsUp[2], motorInv[2], endStInv[2], endStInv2[2], MOVEMENT_INTERRUPT_SPEED, motor2Enbl[2], motor2Inv[2], endStEnbl[2], motorStopAtHome[2], motorMaxSize[2], motorStopAtMax[2]);
/**/
/*
#if defined(FARMDUINO_EXP_V20)
loadSettingsTMC2130();
#endif
*/
primeMotors();
}
bool Movement::intToBool(int value)
{
if (value == 1)
{
return true;
}
return false;
}
void Movement::loadEncoderSettings()
{
// Load encoder settings
motorConsMissedStepsMax[0] = ParameterList::getInstance()->getValue(ENCODER_MISSED_STEPS_MAX_X);
motorConsMissedStepsMax[1] = ParameterList::getInstance()->getValue(ENCODER_MISSED_STEPS_MAX_Y);
motorConsMissedStepsMax[2] = ParameterList::getInstance()->getValue(ENCODER_MISSED_STEPS_MAX_Z);
motorConsMissedStepsDecay[0] = ParameterList::getInstance()->getValue(ENCODER_MISSED_STEPS_DECAY_X);
motorConsMissedStepsDecay[1] = ParameterList::getInstance()->getValue(ENCODER_MISSED_STEPS_DECAY_Y);
motorConsMissedStepsDecay[2] = ParameterList::getInstance()->getValue(ENCODER_MISSED_STEPS_DECAY_Z);
motorConsMissedStepsDecay[0] = motorConsMissedStepsDecay[0] / 100;
motorConsMissedStepsDecay[1] = motorConsMissedStepsDecay[1] / 100;
motorConsMissedStepsDecay[2] = motorConsMissedStepsDecay[2] / 100;
motorConsMissedStepsDecay[0] = min(max(motorConsMissedStepsDecay[0], 0.01), 99);
motorConsMissedStepsDecay[1] = min(max(motorConsMissedStepsDecay[1], 0.01), 99);
motorConsMissedStepsDecay[2] = min(max(motorConsMissedStepsDecay[2], 0.01), 99);
motorConsEncoderType[0] = ParameterList::getInstance()->getValue(ENCODER_TYPE_X);
motorConsEncoderType[1] = ParameterList::getInstance()->getValue(ENCODER_TYPE_Y);
motorConsEncoderType[2] = ParameterList::getInstance()->getValue(ENCODER_TYPE_Z);
motorConsEncoderScaling[0] = ParameterList::getInstance()->getValue(ENCODER_SCALING_X);
motorConsEncoderScaling[1] = ParameterList::getInstance()->getValue(ENCODER_SCALING_Y);
motorConsEncoderScaling[2] = ParameterList::getInstance()->getValue(ENCODER_SCALING_Z);
motorConsEncoderUseForPos[0] = ParameterList::getInstance()->getValue(ENCODER_USE_FOR_POS_X);
motorConsEncoderUseForPos[1] = ParameterList::getInstance()->getValue(ENCODER_USE_FOR_POS_Y);
motorConsEncoderUseForPos[2] = ParameterList::getInstance()->getValue(ENCODER_USE_FOR_POS_Z);
motorConsEncoderInvert[0] = ParameterList::getInstance()->getValue(ENCODER_INVERT_X);
motorConsEncoderInvert[1] = ParameterList::getInstance()->getValue(ENCODER_INVERT_Y);
motorConsEncoderInvert[2] = ParameterList::getInstance()->getValue(ENCODER_INVERT_Z);
if (ParameterList::getInstance()->getValue(ENCODER_ENABLED_X) == 1)
{
motorConsEncoderEnabled[0] = true;
}
else
{
motorConsEncoderEnabled[0] = false;
}
if (ParameterList::getInstance()->getValue(ENCODER_ENABLED_Y) == 1)
{
motorConsEncoderEnabled[1] = true;
}
else
{
motorConsEncoderEnabled[1] = false;
}
if (ParameterList::getInstance()->getValue(ENCODER_ENABLED_Z) == 1)
{
motorConsEncoderEnabled[2] = true;
}
else
{
motorConsEncoderEnabled[2] = false;
}
}
unsigned long Movement::getMaxLength(unsigned long lengths[3])
{
unsigned long max = lengths[0];
for (int i = 1; i < 3; i++)
{
if (lengths[i] > max)
{
max = lengths[i];
}
}
return max;
}
void Movement::enableMotors()
{
motorMotorsEnabled = true;
axisX.enableMotor();
axisY.enableMotor();
axisZ.enableMotor();
delay(100);
}
void Movement::disableMotorsEmergency()
{
motorMotorsEnabled = false;
axisX.disableMotor();
axisY.disableMotor();
axisZ.disableMotor();
}
void Movement::disableMotors()
{
motorMotorsEnabled = false;
if (motorKeepActive[0] == 0) { axisX.disableMotor(); }
if (motorKeepActive[1] == 0) { axisY.disableMotor(); }
if (motorKeepActive[2] == 0) { axisZ.disableMotor(); }
delay(100);
}
void Movement::primeMotors()
{
if (motorKeepActive[0] == 1) { axisX.enableMotor(); } else { axisX.disableMotor(); }
if (motorKeepActive[1] == 1) { axisY.enableMotor(); } else { axisY.disableMotor(); }
if (motorKeepActive[2] == 1) { axisZ.enableMotor(); } else { axisZ.disableMotor(); }
}
bool Movement::motorsEnabled()
{
return motorMotorsEnabled;
}
bool Movement::endStopsReached()
{
if (axisX.endStopsReached() ||
axisY.endStopsReached() ||
axisZ.endStopsReached())
{
return true;
}
return false;
}
void Movement::storePosition()
{
#if !defined(FARMDUINO_EXP_V20)
if (motorConsEncoderEnabled[0])
{
CurrentState::getInstance()->setX(encoderX.currentPosition());
}
else
{
CurrentState::getInstance()->setX(axisX.currentPosition());
}
if (motorConsEncoderEnabled[1])
{
CurrentState::getInstance()->setY(encoderY.currentPosition());
}
else
{
CurrentState::getInstance()->setY(axisY.currentPosition());
}
if (motorConsEncoderEnabled[2])
{
CurrentState::getInstance()->setZ(encoderZ.currentPosition());
}
else
{
CurrentState::getInstance()->setZ(axisZ.currentPosition());
}
#endif
#if defined(FARMDUINO_EXP_V20)
CurrentState::getInstance()->setX(axisX.currentPosition());
CurrentState::getInstance()->setY(axisY.currentPosition());
CurrentState::getInstance()->setZ(axisZ.currentPosition());
#endif
}
void Movement::reportEndStops()
{
CurrentState::getInstance()->printEndStops();
}
void Movement::reportPosition()
{
CurrentState::getInstance()->printPosition();
}
void Movement::storeEndStops()
{
CurrentState::getInstance()->storeEndStops();
}
void Movement::setPositionX(long pos)
{
axisX.setCurrentPosition(pos);
encoderX.setPosition(pos);
}
void Movement::setPositionY(long pos)
{
axisY.setCurrentPosition(pos);
encoderY.setPosition(pos);
}
void Movement::setPositionZ(long pos)
{
axisZ.setCurrentPosition(pos);
encoderZ.setPosition(pos);
}
// Handle movement by checking each axis
void Movement::handleMovementInterrupt(void)
{
// No need to check the encoders for Farmduino 1.4
#if defined(RAMPS_V14) || defined(FARMDUINO_V10)
checkEncoders();
#endif
// handle motor timing
axisX.incrementTick();
axisY.incrementTick();
axisZ.incrementTick();
}
void Movement::checkEncoders()
{
// read encoder pins using the arduino IN registers instead of digital in
// because it used much fewer cpu cycles
// A=16/PH1 B=17/PH0 AQ=31/PC6 BQ=33/PC4
encoderX.checkEncoder(
ENC_X_A_PORT & ENC_X_A_BYTE,
ENC_X_B_PORT & ENC_X_B_BYTE,
ENC_X_A_Q_PORT & ENC_X_A_Q_BYTE,
ENC_X_B_Q_PORT & ENC_X_B_Q_BYTE);
// A=23/PA1 B=25/PA3 AQ=35/PC2 BQ=37/PC0
encoderY.checkEncoder(
ENC_Y_A_PORT & ENC_Y_A_BYTE,
ENC_Y_B_PORT & ENC_Y_B_BYTE,
ENC_Y_A_Q_PORT & ENC_Y_A_Q_BYTE,
ENC_Y_B_Q_PORT & ENC_Y_B_Q_BYTE);
// A=27/PA5 B=29/PA7 AQ=39/PG2 BQ=41/PG0
encoderZ.checkEncoder(
ENC_Z_A_PORT & ENC_Z_A_BYTE,
ENC_Z_B_PORT & ENC_Z_B_BYTE,
ENC_Z_A_Q_PORT & ENC_Z_A_Q_BYTE,
ENC_Z_B_Q_PORT & ENC_Z_B_Q_BYTE);
}