/* This file is part of Repetier-Firmware. Repetier-Firmware is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Repetier-Firmware is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Repetier-Firmware. If not, see . */ #include "Repetier.h" #if USE_ADVANCE ufast8_t Printer::maxExtruderSpeed; ///< Timer delay for end extruder speed volatile int Printer::extruderStepsNeeded; ///< This many extruder steps are still needed, <0 = reverse steps needed. //uint8_t Printer::extruderAccelerateDelay; ///< delay between 2 speec increases #endif uint8_t Printer::unitIsInches = 0; ///< 0 = Units are mm, 1 = units are inches. //Stepper Movement Variables float Printer::axisStepsPerMM[E_AXIS_ARRAY] = {XAXIS_STEPS_PER_MM, YAXIS_STEPS_PER_MM, ZAXIS_STEPS_PER_MM, 1}; ///< Number of steps per mm needed. float Printer::invAxisStepsPerMM[E_AXIS_ARRAY]; ///< Inverse of axisStepsPerMM for faster conversion float Printer::maxFeedrate[E_AXIS_ARRAY] = {MAX_FEEDRATE_X, MAX_FEEDRATE_Y, MAX_FEEDRATE_Z}; ///< Maximum allowed feedrate. float Printer::homingFeedrate[Z_AXIS_ARRAY] = {HOMING_FEEDRATE_X, HOMING_FEEDRATE_Y, HOMING_FEEDRATE_Z}; #if DUAL_X_RESOLUTION float Printer::axisX1StepsPerMM = XAXIS_STEPS_PER_MM; float Printer::axisX2StepsPerMM = X2AXIS_STEPS_PER_MM; #endif #if RAMP_ACCELERATION // float max_start_speed_units_per_second[E_AXIS_ARRAY] = MAX_START_SPEED_UNITS_PER_SECOND; ///< Speed we can use, without acceleration. float Printer::maxAccelerationMMPerSquareSecond[E_AXIS_ARRAY] = {MAX_ACCELERATION_UNITS_PER_SQ_SECOND_X, MAX_ACCELERATION_UNITS_PER_SQ_SECOND_Y, MAX_ACCELERATION_UNITS_PER_SQ_SECOND_Z}; ///< X, Y, Z and E max acceleration in mm/s^2 for printing moves or retracts float Printer::maxTravelAccelerationMMPerSquareSecond[E_AXIS_ARRAY] = {MAX_TRAVEL_ACCELERATION_UNITS_PER_SQ_SECOND_X, MAX_TRAVEL_ACCELERATION_UNITS_PER_SQ_SECOND_Y, MAX_TRAVEL_ACCELERATION_UNITS_PER_SQ_SECOND_Z}; ///< X, Y, Z max acceleration in mm/s^2 for travel moves /** Acceleration in steps/s^3 in printing mode.*/ unsigned long Printer::maxPrintAccelerationStepsPerSquareSecond[E_AXIS_ARRAY]; /** Acceleration in steps/s^2 in movement mode.*/ unsigned long Printer::maxTravelAccelerationStepsPerSquareSecond[E_AXIS_ARRAY]; // uint32_t Printer::maxInterval; #endif #if NONLINEAR_SYSTEM long Printer::currentNonlinearPositionSteps[E_TOWER_ARRAY]; uint8_t lastMoveID = 0; // Last move ID #endif #if DRIVE_SYSTEM != DELTA int32_t Printer::zCorrectionStepsIncluded = 0; #endif #if FEATURE_BABYSTEPPING int16_t Printer::zBabystepsMissing = 0; int16_t Printer::zBabysteps = 0; #endif uint8_t Printer::relativeCoordinateMode = false; ///< Determines absolute (false) or relative Coordinates (true). uint8_t Printer::relativeExtruderCoordinateMode = false; ///< Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode. long Printer::currentPositionSteps[E_AXIS_ARRAY]; float Printer::currentPosition[Z_AXIS_ARRAY]; float Printer::lastCmdPos[Z_AXIS_ARRAY]; long Printer::destinationSteps[E_AXIS_ARRAY]; float Printer::coordinateOffset[Z_AXIS_ARRAY] = {0, 0, 0}; uint8_t Printer::flag0 = 0; uint8_t Printer::flag1 = 0; uint8_t Printer::flag2 = 0; uint8_t Printer::flag3 = 0; uint8_t Printer::debugLevel = 6; ///< Bitfield defining debug output. 1 = echo, 2 = info, 4 = error, 8 = dry run., 16 = Only communication, 32 = No moves fast8_t Printer::stepsPerTimerCall = 1; uint16_t Printer::menuMode = 0; uint8_t Printer::mode = DEFAULT_PRINTER_MODE; uint8_t Printer::fanSpeed = 0; // Last fan speed set with M106/M107 float Printer::extrudeMultiplyError = 0; float Printer::extrusionFactor = 1.0; uint8_t Printer::interruptEvent = 0; int Printer::currentLayer = 0; int Printer::maxLayer = -1; // -1 = unknown char Printer::printName[21] = ""; // max. 20 chars + 0 float Printer::progress = 0; millis_t Printer::lastTempReport = 0; #if EEPROM_MODE != 0 float Printer::zBedOffset = HAL::eprGetFloat(EPR_Z_PROBE_Z_OFFSET); #else float Printer::zBedOffset = Z_PROBE_Z_OFFSET; #endif #if FEATURE_AUTOLEVEL float Printer::autolevelTransformation[9]; ///< Transformation matrix #endif uint32_t Printer::interval = 30000; ///< Last step duration in ticks. uint32_t Printer::timer; ///< used for acceleration/deceleration timing uint32_t Printer::stepNumber; ///< Step number in current move. #if USE_ADVANCE #if ENABLE_QUADRATIC_ADVANCE int32_t Printer::advanceExecuted; ///< Executed advance steps #endif int Printer::advanceStepsSet; #endif #if NONLINEAR_SYSTEM int32_t Printer::maxDeltaPositionSteps; floatLong Printer::deltaDiagonalStepsSquaredA; floatLong Printer::deltaDiagonalStepsSquaredB; floatLong Printer::deltaDiagonalStepsSquaredC; float Printer::deltaMaxRadiusSquared; float Printer::radius0; int32_t Printer::deltaFloorSafetyMarginSteps = 0; int32_t Printer::deltaAPosXSteps; int32_t Printer::deltaAPosYSteps; int32_t Printer::deltaBPosXSteps; int32_t Printer::deltaBPosYSteps; int32_t Printer::deltaCPosXSteps; int32_t Printer::deltaCPosYSteps; int32_t Printer::realDeltaPositionSteps[TOWER_ARRAY]; int16_t Printer::travelMovesPerSecond; int16_t Printer::printMovesPerSecond; #endif #if !NONLINEAR_SYSTEM || defined(FAST_COREXYZ) int32_t Printer::xMinStepsAdj, Printer::yMinStepsAdj, Printer::zMinStepsAdj; // adjusted to cover extruder/probe offsets int32_t Printer::xMaxStepsAdj, Printer::yMaxStepsAdj, Printer::zMaxStepsAdj; #endif #if FEATURE_Z_PROBE || MAX_HARDWARE_ENDSTOP_Z || NONLINEAR_SYSTEM int32_t Printer::stepsRemainingAtZHit; #endif #if DRIVE_SYSTEM == DELTA int32_t Printer::stepsRemainingAtXHit; int32_t Printer::stepsRemainingAtYHit; #endif #if SOFTWARE_LEVELING int32_t Printer::levelingP1[3]; int32_t Printer::levelingP2[3]; int32_t Printer::levelingP3[3]; #endif //float Printer::minimumSpeed; ///< lowest allowed speed to keep integration error small //float Printer::minimumZSpeed; int32_t Printer::xMaxSteps; ///< For software endstops, limit of move in positive direction. int32_t Printer::yMaxSteps; ///< For software endstops, limit of move in positive direction. int32_t Printer::zMaxSteps; ///< For software endstops, limit of move in positive direction. int32_t Printer::xMinSteps; ///< For software endstops, limit of move in negative direction. int32_t Printer::yMinSteps; ///< For software endstops, limit of move in negative direction. int32_t Printer::zMinSteps; ///< For software endstops, limit of move in negative direction. float Printer::xLength; float Printer::xMin; float Printer::yLength; float Printer::yMin; float Printer::zLength; float Printer::zMin; float Printer::feedrate; ///< Last requested feedrate. int Printer::feedrateMultiply; ///< Multiplier for feedrate in percent (factor 1 = 100) unsigned int Printer::extrudeMultiply; ///< Flow multiplier in percent (factor 1 = 100) float Printer::maxJerk; ///< Maximum allowed jerk in mm/s #if DRIVE_SYSTEM != DELTA float Printer::maxZJerk; ///< Maximum allowed jerk in z direction in mm/s #endif float Printer::offsetX; ///< X-offset for different extruder positions. float Printer::offsetY; ///< Y-offset for different extruder positions. float Printer::offsetZ; ///< Z-offset for different extruder positions. float Printer::offsetZ2 = 0; ///< Z-offset without rotation correction. speed_t Printer::vMaxReached; ///< Maximum reached speed uint32_t Printer::msecondsPrinting; ///< Milliseconds of printing time (means time with heated extruder) float Printer::filamentPrinted; ///< mm of filament printed since counting started #if ENABLE_BACKLASH_COMPENSATION float Printer::backlashX; float Printer::backlashY; float Printer::backlashZ; uint8_t Printer::backlashDir; #endif float Printer::memoryX = IGNORE_COORDINATE; float Printer::memoryY = IGNORE_COORDINATE; float Printer::memoryZ = IGNORE_COORDINATE; float Printer::memoryE = IGNORE_COORDINATE; float Printer::memoryF = -1; #if GANTRY && !defined(FAST_COREXYZ) int8_t Printer::motorX; int8_t Printer::motorYorZ; #endif #if FAN_THERMO_PIN > -1 float Printer::thermoMinTemp = FAN_THERMO_MIN_TEMP; float Printer::thermoMaxTemp = FAN_THERMO_MAX_TEMP; #endif #ifdef DEBUG_SEGMENT_LENGTH float Printer::maxRealSegmentLength = 0; #endif #ifdef DEBUG_REAL_JERK float Printer::maxRealJerk = 0; #endif #if MULTI_XENDSTOP_HOMING fast8_t Printer::multiXHomeFlags; // 1 = move X0, 2 = move X1 #endif #if MULTI_YENDSTOP_HOMING fast8_t Printer::multiYHomeFlags; // 1 = move Y0, 2 = move Y1 #endif #if MULTI_ZENDSTOP_HOMING fast8_t Printer::multiZHomeFlags; // 1 = move Z0, 2 = move Z1 #endif #ifdef DEBUG_PRINT int debugWaitLoop = 0; #endif #if LAZY_DUAL_X_AXIS bool Printer::sledParked = false; #endif fast8_t Printer::wizardStackPos; wizardVar Printer::wizardStack[WIZARD_STACK_SIZE]; #if defined(DRV_TMC2130) #if TMC2130_ON_X TMC2130Stepper* Printer::tmc_driver_x = NULL; #endif #if TMC2130_ON_Y TMC2130Stepper* Printer::tmc_driver_y = NULL; #endif #if TMC2130_ON_Z TMC2130Stepper* Printer::tmc_driver_z = NULL; #endif #if TMC2130_ON_EXT0 TMC2130Stepper* Printer::tmc_driver_e0 = NULL; #endif #if TMC2130_ON_EXT1 TMC2130Stepper* Printer::tmc_driver_e1 = NULL; #endif #if TMC2130_ON_EXT2 TMC2130Stepper* Printer::tmc_driver_e2 = NULL; #endif #endif #if !NONLINEAR_SYSTEM void Printer::constrainDestinationCoords() { if(isNoDestinationCheck() || isHoming()) return; #if min_software_endstop_x if (destinationSteps[X_AXIS] < xMinStepsAdj) destinationSteps[X_AXIS] = xMinStepsAdj; #endif #if min_software_endstop_y if (destinationSteps[Y_AXIS] < yMinStepsAdj) destinationSteps[Y_AXIS] = yMinStepsAdj; #endif #if min_software_endstop_z if (isAutolevelActive() == false && destinationSteps[Z_AXIS] < zMinStepsAdj && !isZProbingActive()) destinationSteps[Z_AXIS] = zMinStepsAdj; #endif #if max_software_endstop_x if (destinationSteps[X_AXIS] > xMaxStepsAdj) destinationSteps[X_AXIS] = xMaxStepsAdj; #endif #if max_software_endstop_y if (destinationSteps[Y_AXIS] > yMaxStepsAdj) destinationSteps[Y_AXIS] = yMaxStepsAdj; #endif #if max_software_endstop_z if (isAutolevelActive() == false && destinationSteps[Z_AXIS] > zMaxStepsAdj && !isZProbingActive()) destinationSteps[Z_AXIS] = zMaxStepsAdj; #endif EVENT_CONTRAIN_DESTINATION_COORDINATES } #endif void Printer::setDebugLevel(uint8_t newLevel) { if(newLevel != debugLevel) { debugLevel = newLevel; if(debugDryrun()) { // Disable all heaters in case they were on Extruder::disableAllHeater(); } } Com::printFLN(PSTR("DebugLevel:"), (int)newLevel); } void Printer::toggleEcho() { setDebugLevel(debugLevel ^ 1); } void Printer::toggleInfo() { setDebugLevel(debugLevel ^ 2); } void Printer::toggleErrors() { setDebugLevel(debugLevel ^ 4); } void Printer::toggleDryRun() { setDebugLevel(debugLevel ^ 8); } void Printer::toggleCommunication() { setDebugLevel(debugLevel ^ 16); } void Printer::toggleNoMoves() { setDebugLevel(debugLevel ^ 32); } void Printer::toggleEndStop() { setDebugLevel(debugLevel ^ 64); } bool Printer::isPositionAllowed(float x, float y, float z) { if(isNoDestinationCheck()) return true; bool allowed = true; #if DRIVE_SYSTEM == DELTA if(!isHoming()) { allowed = allowed && (z >= 0) && (z <= zLength + 0.05 + ENDSTOP_Z_BACK_ON_HOME); allowed = allowed && (x * x + y * y <= deltaMaxRadiusSquared); } #else // DRIVE_SYSTEM if(!isHoming()) { allowed = allowed && x >= xMin - 0.01; allowed = allowed && x <= xMin + xLength + 0.01; allowed = allowed && y >= yMin - 0.01; allowed = allowed && y <= yMin + yLength + 0.01; allowed = allowed && z >= zMin - 0.01; allowed = allowed && z <= zMin + zLength + ENDSTOP_Z_BACK_ON_HOME + 0.01; } #endif /*#if DUAL_X_AXIS // Prevent carriage hit by disallowing moves inside other parking direction. if(Extruder::current->id == 0) { if(x > xMin + xLength + 0.01) allowed = false; } else { if(x < xMin - 0.01) allowed = false; } #endif*/ if(!allowed) { Printer::updateCurrentPosition(true); Commands::printCurrentPosition(); } return allowed; } void Printer::setFanSpeedDirectly(uint8_t speed) { uint8_t trimmedSpeed = TRIM_FAN_PWM(speed); #if FAN_PIN > -1 && FEATURE_FAN_CONTROL if(pwm_pos[PWM_FAN1] == trimmedSpeed) return; #if FAN_KICKSTART_TIME if(fanKickstart == 0 && speed > pwm_pos[PWM_FAN1] && speed < 85) { if(pwm_pos[PWM_FAN1]) fanKickstart = FAN_KICKSTART_TIME / 100; else fanKickstart = FAN_KICKSTART_TIME / 25; } #endif pwm_pos[PWM_FAN1] = trimmedSpeed; #endif } void Printer::setFan2SpeedDirectly(uint8_t speed) { uint8_t trimmedSpeed = TRIM_FAN_PWM(speed); #if FAN2_PIN > -1 && FEATURE_FAN2_CONTROL if(pwm_pos[PWM_FAN2] == trimmedSpeed) return; #if FAN_KICKSTART_TIME if(fan2Kickstart == 0 && speed > pwm_pos[PWM_FAN2] && speed < 85) { if(pwm_pos[PWM_FAN2]) fan2Kickstart = FAN_KICKSTART_TIME / 100; else fan2Kickstart = FAN_KICKSTART_TIME / 25; } #endif pwm_pos[PWM_FAN2] = trimmedSpeed; #endif } bool Printer::updateDoorOpen() { #if defined(DOOR_PIN) && DOOR_PIN > -1 // && SUPPORT_LASER should always be respected bool isOpen = isDoorOpen(); uint8_t b = READ(DOOR_PIN) != DOOR_INVERTING; if(!b && isOpen) { UI_STATUS_F(Com::tSpace); } else if(b && !isOpen) { Com::printWarningFLN(Com::tDoorOpen); UI_STATUS_F(Com::tDoorOpen); } flag3 = (b ? flag3 | PRINTER_FLAG3_DOOR_OPEN : flag3 & ~PRINTER_FLAG3_DOOR_OPEN); return b; #else return 0; #endif } void Printer::reportPrinterMode() { Printer::setMenuMode(MENU_MODE_CNC + MENU_MODE_LASER + MENU_MODE_FDM, false); switch(Printer::mode) { case PRINTER_MODE_FFF: Printer::setMenuMode(MENU_MODE_FDM, true); Com::printFLN(Com::tPrinterModeFFF); break; case PRINTER_MODE_LASER: Printer::setMenuMode(MENU_MODE_LASER, true); Com::printFLN(Com::tPrinterModeLaser); break; case PRINTER_MODE_CNC: Printer::setMenuMode(MENU_MODE_CNC, true); Com::printFLN(Com::tPrinterModeCNC); break; } } void Printer::updateDerivedParameter() { #if NONLINEAR_SYSTEM travelMovesPerSecond = EEPROM::deltaSegmentsPerSecondMove(); printMovesPerSecond = EEPROM::deltaSegmentsPerSecondPrint(); if(travelMovesPerSecond < 15) travelMovesPerSecond = 15; // lower values make no sense and can cause serious problems if(printMovesPerSecond < 15) printMovesPerSecond = 15; #endif #if DRIVE_SYSTEM == DELTA axisStepsPerMM[X_AXIS] = axisStepsPerMM[Y_AXIS] = axisStepsPerMM[Z_AXIS]; maxAccelerationMMPerSquareSecond[X_AXIS] = maxAccelerationMMPerSquareSecond[Y_AXIS] = maxAccelerationMMPerSquareSecond[Z_AXIS]; homingFeedrate[X_AXIS] = homingFeedrate[Y_AXIS] = homingFeedrate[Z_AXIS]; maxFeedrate[X_AXIS] = maxFeedrate[Y_AXIS] = maxFeedrate[Z_AXIS]; maxTravelAccelerationMMPerSquareSecond[X_AXIS] = maxTravelAccelerationMMPerSquareSecond[Y_AXIS] = maxTravelAccelerationMMPerSquareSecond[Z_AXIS]; zMaxSteps = axisStepsPerMM[Z_AXIS] * (zLength); towerAMinSteps = axisStepsPerMM[A_TOWER] * xMin; towerBMinSteps = axisStepsPerMM[B_TOWER] * yMin; towerCMinSteps = axisStepsPerMM[C_TOWER] * zMin; //radius0 = EEPROM::deltaHorizontalRadius(); float radiusA = radius0 + EEPROM::deltaRadiusCorrectionA(); float radiusB = radius0 + EEPROM::deltaRadiusCorrectionB(); float radiusC = radius0 + EEPROM::deltaRadiusCorrectionC(); deltaAPosXSteps = floor(radiusA * cos(EEPROM::deltaAlphaA() * M_PI / 180.0f) * axisStepsPerMM[Z_AXIS] + 0.5f); deltaAPosYSteps = floor(radiusA * sin(EEPROM::deltaAlphaA() * M_PI / 180.0f) * axisStepsPerMM[Z_AXIS] + 0.5f); deltaBPosXSteps = floor(radiusB * cos(EEPROM::deltaAlphaB() * M_PI / 180.0f) * axisStepsPerMM[Z_AXIS] + 0.5f); deltaBPosYSteps = floor(radiusB * sin(EEPROM::deltaAlphaB() * M_PI / 180.0f) * axisStepsPerMM[Z_AXIS] + 0.5f); deltaCPosXSteps = floor(radiusC * cos(EEPROM::deltaAlphaC() * M_PI / 180.0f) * axisStepsPerMM[Z_AXIS] + 0.5f); deltaCPosYSteps = floor(radiusC * sin(EEPROM::deltaAlphaC() * M_PI / 180.0f) * axisStepsPerMM[Z_AXIS] + 0.5f); deltaDiagonalStepsSquaredA.l = static_cast((EEPROM::deltaDiagonalCorrectionA() + EEPROM::deltaDiagonalRodLength()) * axisStepsPerMM[Z_AXIS]); deltaDiagonalStepsSquaredB.l = static_cast((EEPROM::deltaDiagonalCorrectionB() + EEPROM::deltaDiagonalRodLength()) * axisStepsPerMM[Z_AXIS]); deltaDiagonalStepsSquaredC.l = static_cast((EEPROM::deltaDiagonalCorrectionC() + EEPROM::deltaDiagonalRodLength()) * axisStepsPerMM[Z_AXIS]); if(deltaDiagonalStepsSquaredA.l > 65534 || 2 * radius0 * axisStepsPerMM[Z_AXIS] > 65534) { setLargeMachine(true); #ifdef SUPPORT_64_BIT_MATH deltaDiagonalStepsSquaredA.L = RMath::sqr(static_cast(deltaDiagonalStepsSquaredA.l)); deltaDiagonalStepsSquaredB.L = RMath::sqr(static_cast(deltaDiagonalStepsSquaredB.l)); deltaDiagonalStepsSquaredC.L = RMath::sqr(static_cast(deltaDiagonalStepsSquaredC.l)); #else deltaDiagonalStepsSquaredA.f = RMath::sqr(static_cast(deltaDiagonalStepsSquaredA.l)); deltaDiagonalStepsSquaredB.f = RMath::sqr(static_cast(deltaDiagonalStepsSquaredB.l)); deltaDiagonalStepsSquaredC.f = RMath::sqr(static_cast(deltaDiagonalStepsSquaredC.l)); #endif } else { setLargeMachine(false); deltaDiagonalStepsSquaredA.l = RMath::sqr(deltaDiagonalStepsSquaredA.l); deltaDiagonalStepsSquaredB.l = RMath::sqr(deltaDiagonalStepsSquaredB.l); deltaDiagonalStepsSquaredC.l = RMath::sqr(deltaDiagonalStepsSquaredC.l); } deltaMaxRadiusSquared = RMath::sqr(EEPROM::deltaMaxRadius()); long cart[Z_AXIS_ARRAY], delta[TOWER_ARRAY]; cart[X_AXIS] = cart[Y_AXIS] = 0; cart[Z_AXIS] = zMaxSteps; transformCartesianStepsToDeltaSteps(cart, delta); maxDeltaPositionSteps = delta[0]; xMaxSteps = yMaxSteps = zMaxSteps; xMinSteps = yMinSteps = zMinSteps = 0; deltaFloorSafetyMarginSteps = DELTA_FLOOR_SAFETY_MARGIN_MM * axisStepsPerMM[Z_AXIS]; #elif DRIVE_SYSTEM == TUGA deltaDiagonalStepsSquared.l = uint32_t(EEPROM::deltaDiagonalRodLength() * axisStepsPerMM[X_AXIS]); if(deltaDiagonalStepsSquared.l > 65534) { setLargeMachine(true); deltaDiagonalStepsSquared.f = float(deltaDiagonalStepsSquared.l) * float(deltaDiagonalStepsSquared.l); } else deltaDiagonalStepsSquared.l = deltaDiagonalStepsSquared.l * deltaDiagonalStepsSquared.l; deltaBPosXSteps = static_cast(EEPROM::deltaDiagonalRodLength() * axisStepsPerMM[X_AXIS]); xMaxSteps = static_cast(axisStepsPerMM[X_AXIS] * (xMin + xLength)); yMaxSteps = static_cast(axisStepsPerMM[Y_AXIS] * yLength); zMaxSteps = static_cast(axisStepsPerMM[Z_AXIS] * (zMin + zLength)); xMinSteps = static_cast(axisStepsPerMM[X_AXIS] * xMin); yMinSteps = 0; zMinSteps = static_cast(axisStepsPerMM[Z_AXIS] * zMin); #else #if DUAL_X_RESOLUTION if(Extruder::current->id == 0) // adjust resolution based on active extruder axisStepsPerMM[X_AXIS] = axisX1StepsPerMM; else axisStepsPerMM[X_AXIS] = axisX2StepsPerMM; invAxisStepsPerMM[X_AXIS] = 1.0 / axisStepsPerMM[X_AXIS]; #endif xMaxStepsAdj = xMaxSteps = static_cast(axisStepsPerMM[X_AXIS] * (xMin + xLength)); yMaxStepsAdj = yMaxSteps = static_cast(axisStepsPerMM[Y_AXIS] * (yMin + yLength)); zMaxStepsAdj = zMaxSteps = static_cast(axisStepsPerMM[Z_AXIS] * (zMin + zLength)); xMinStepsAdj = xMinSteps = static_cast(axisStepsPerMM[X_AXIS] * xMin); yMinStepsAdj = yMinSteps = static_cast(axisStepsPerMM[Y_AXIS] * yMin); zMinStepsAdj = zMinSteps = static_cast(axisStepsPerMM[Z_AXIS] * zMin); for(fast8_t i = 0; i < NUM_EXTRUDER; i++) { Extruder &e = extruder[i]; xMaxStepsAdj = RMath::max(xMaxStepsAdj, xMaxSteps - e.xOffset); xMinStepsAdj = RMath::min(xMinStepsAdj, xMinSteps - e.xOffset); yMaxStepsAdj = RMath::max(yMaxStepsAdj, yMaxSteps - e.yOffset); yMinStepsAdj = RMath::min(yMinStepsAdj, yMinSteps - e.yOffset); zMaxStepsAdj = RMath::max(zMaxStepsAdj, zMaxSteps - e.zOffset); zMinStepsAdj = RMath::min(zMinStepsAdj, zMinSteps - e.zOffset); } #if FEATURE_Z_PROBE xMaxStepsAdj = RMath::max(xMaxStepsAdj, xMaxSteps - static_cast(EEPROM::zProbeXOffset() * axisStepsPerMM[X_AXIS])); xMinStepsAdj = RMath::min(xMinStepsAdj, xMinSteps - static_cast(EEPROM::zProbeXOffset() * axisStepsPerMM[X_AXIS])); yMaxStepsAdj = RMath::max(yMaxStepsAdj, yMaxSteps - static_cast(EEPROM::zProbeYOffset() * axisStepsPerMM[Y_AXIS])); yMinStepsAdj = RMath::min(yMinStepsAdj, yMinSteps - static_cast(EEPROM::zProbeYOffset() * axisStepsPerMM[Y_AXIS])); #endif // For which directions do we need backlash compensation #if ENABLE_BACKLASH_COMPENSATION backlashDir &= XYZ_DIRPOS; if(backlashX != 0) backlashDir |= 8; if(backlashY != 0) backlashDir |= 16; if(backlashZ != 0) backlashDir |= 32; #endif #endif for(uint8_t i = 0; i < E_AXIS_ARRAY; i++) { invAxisStepsPerMM[i] = 1.0f / axisStepsPerMM[i]; #ifdef RAMP_ACCELERATION /** Acceleration in steps/s^3 in printing mode.*/ maxPrintAccelerationStepsPerSquareSecond[i] = maxAccelerationMMPerSquareSecond[i] * axisStepsPerMM[i]; /** Acceleration in steps/s^2 in movement mode.*/ maxTravelAccelerationStepsPerSquareSecond[i] = maxTravelAccelerationMMPerSquareSecond[i] * axisStepsPerMM[i]; #endif } // For numeric stability we need to start accelerations at a minimum speed and hence ensure that the // jerk is at least 2 * minimum speed. // For xy moves the minimum speed is multiplied with 1.41 to enforce the condition also for diagonals since the // driving axis is the problematic speed. float accel = RMath::max(maxAccelerationMMPerSquareSecond[X_AXIS], maxTravelAccelerationMMPerSquareSecond[X_AXIS]); float minimumSpeed = 1.41 * accel * sqrt(2.0f / (axisStepsPerMM[X_AXIS] * accel)); accel = RMath::max(maxAccelerationMMPerSquareSecond[Y_AXIS], maxTravelAccelerationMMPerSquareSecond[Y_AXIS]); float minimumSpeed2 = 1.41 * accel * sqrt(2.0f / (axisStepsPerMM[Y_AXIS] * accel)); if(minimumSpeed2 > minimumSpeed) { minimumSpeed = minimumSpeed2; } if(maxJerk < 2 * minimumSpeed) {// Enforce minimum start speed if target is faster and jerk too low maxJerk = 2 * minimumSpeed; Com::printFLN(PSTR("XY jerk was too low, setting to "), maxJerk); } accel = RMath::max(maxAccelerationMMPerSquareSecond[Z_AXIS], maxTravelAccelerationMMPerSquareSecond[Z_AXIS]); #if DRIVE_SYSTEM != DELTA float minimumZSpeed = 0.5 * accel * sqrt(2.0f / (axisStepsPerMM[Z_AXIS] * accel)); if(maxZJerk < 2 * minimumZSpeed) { maxZJerk = 2 * minimumZSpeed; Com::printFLN(PSTR("Z jerk was too low, setting to "), maxZJerk); } #endif /* maxInterval = F_CPU / (minimumSpeed * axisStepsPerMM[X_AXIS]); uint32_t tmp = F_CPU / (minimumSpeed * axisStepsPerMM[Y_AXIS]); if(tmp < maxInterval) maxInterval = tmp; #if DRIVE_SYSTEM != DELTA tmp = F_CPU / (minimumZSpeed * axisStepsPerMM[Z_AXIS]); if(tmp < maxInterval) maxInterval = tmp; #endif */ //Com::printFLN(PSTR("Minimum Speed:"),minimumSpeed); //Com::printFLN(PSTR("Minimum Speed Z:"),minimumZSpeed); #if DISTORTION_CORRECTION distortion.updateDerived(); #endif // DISTORTION_CORRECTION Printer::updateAdvanceFlags(); EVENT_UPDATE_DERIVED; } #if AUTOMATIC_POWERUP void Printer::enablePowerIfNeeded() { if(Printer::isPowerOn()) return; SET_OUTPUT(PS_ON_PIN); //GND Printer::setPowerOn(true); WRITE(PS_ON_PIN, (POWER_INVERTING ? HIGH : LOW)); HAL::delayMilliseconds(500); // Just to ensure power is up and stable } #endif /** \brief Stop heater and stepper motors. Disable power,if possible. */ void Printer::kill(uint8_t onlySteppers) { EVENT_KILL(onlySteppers); if(areAllSteppersDisabled() && onlySteppers) return; if(Printer::isAllKilled()) return; #if defined(NUM_MOTOR_DRIVERS) && NUM_MOTOR_DRIVERS > 0 disableAllMotorDrivers(); #endif // defined disableXStepper(); disableYStepper(); #if !defined(PREVENT_Z_DISABLE_ON_STEPPER_TIMEOUT) disableZStepper(); #else if(!onlySteppers) disableZStepper(); #endif Extruder::disableAllExtruderMotors(); setAllSteppersDiabled(); unsetHomedAll(); if(!onlySteppers) { for(uint8_t i = 0; i < NUM_EXTRUDER; i++) Extruder::setTemperatureForExtruder(0, i); Extruder::setHeatedBedTemperature(0); UI_STATUS_UPD_F(Com::translatedF(UI_TEXT_STANDBY_ID)); #if defined(PS_ON_PIN) && PS_ON_PIN>-1 && !defined(NO_POWER_TIMEOUT) //pinMode(PS_ON_PIN,INPUT); SET_OUTPUT(PS_ON_PIN); //GND WRITE(PS_ON_PIN, (POWER_INVERTING ? LOW : HIGH)); Printer::setPowerOn(false); #endif Printer::setAllKilled(true); } else UI_STATUS_UPD_F(Com::translatedF(UI_TEXT_STEPPER_DISABLED_ID)); #if FAN_BOARD_PIN > -1 #if HAVE_HEATED_BED if(heatedBedController.targetTemperatureC < 15) // turn off FAN_BOARD only if bed heater is off #endif pwm_pos[PWM_BOARD_FAN] = BOARD_FAN_MIN_SPEED; #endif // FAN_BOARD_PIN Commands::printTemperatures(false); } void Printer::updateAdvanceFlags() { Printer::setAdvanceActivated(false); #if USE_ADVANCE for(uint8_t i = 0; i < NUM_EXTRUDER; i++) { if(extruder[i].advanceL != 0) { Printer::setAdvanceActivated(true); } #if ENABLE_QUADRATIC_ADVANCE if(extruder[i].advanceK != 0) Printer::setAdvanceActivated(true); #endif } #endif } void Printer::moveToParkPosition() { if(Printer::isHomedAll()) { // for safety move only when homed! moveToReal(EEPROM::parkX(),EEPROM::parkY(),IGNORE_COORDINATE,IGNORE_COORDINATE, Printer::maxFeedrate[X_AXIS], true); moveToReal(IGNORE_COORDINATE,IGNORE_COORDINATE,RMath::min(zMin + zLength, currentPosition[Z_AXIS] + EEPROM::parkZ()),IGNORE_COORDINATE, Printer::maxFeedrate[Z_AXIS], true); } } // This is for untransformed move to coordinates in printers absolute Cartesian space uint8_t Printer::moveTo(float x, float y, float z, float e, float f) { if(x != IGNORE_COORDINATE) destinationSteps[X_AXIS] = (x + Printer::offsetX) * axisStepsPerMM[X_AXIS]; if(y != IGNORE_COORDINATE) destinationSteps[Y_AXIS] = (y + Printer::offsetY) * axisStepsPerMM[Y_AXIS]; if(z != IGNORE_COORDINATE) destinationSteps[Z_AXIS] = (z + Printer::offsetZ) * axisStepsPerMM[Z_AXIS]; if(e != IGNORE_COORDINATE) destinationSteps[E_AXIS] = e * axisStepsPerMM[E_AXIS]; else destinationSteps[E_AXIS] = currentPositionSteps[E_AXIS]; if(f != IGNORE_COORDINATE) feedrate = f; #if NONLINEAR_SYSTEM // Disable software end stop or we get wrong distances when length < real length if (!PrintLine::queueNonlinearMove(ALWAYS_CHECK_ENDSTOPS, true, false)) { Com::printWarningFLN(PSTR("moveTo / queueDeltaMove returns error")); return 0; } #else PrintLine::queueCartesianMove(ALWAYS_CHECK_ENDSTOPS, true); #endif updateCurrentPosition(false); return 1; } uint8_t Printer::moveToReal(float x, float y, float z, float e, float f, bool pathOptimize) { if(x == IGNORE_COORDINATE) x = currentPosition[X_AXIS]; else currentPosition[X_AXIS] = x; if(y == IGNORE_COORDINATE) y = currentPosition[Y_AXIS]; else currentPosition[Y_AXIS] = y; if(z == IGNORE_COORDINATE) z = currentPosition[Z_AXIS]; else currentPosition[Z_AXIS] = z; transformToPrinter(x + Printer::offsetX, y + Printer::offsetY, z + Printer::offsetZ, x, y, z); z += offsetZ2; // There was conflicting use of IGNOR_COORDINATE destinationSteps[X_AXIS] = static_cast(floor(x * axisStepsPerMM[X_AXIS] + 0.5f)); destinationSteps[Y_AXIS] = static_cast(floor(y * axisStepsPerMM[Y_AXIS] + 0.5f)); destinationSteps[Z_AXIS] = static_cast(floor(z * axisStepsPerMM[Z_AXIS] + 0.5f)); if(e != IGNORE_COORDINATE && !Printer::debugDryrun() #if MIN_EXTRUDER_TEMP > 30 && (Extruder::current->tempControl.currentTemperatureC > MIN_EXTRUDER_TEMP || Printer::isColdExtrusionAllowed() || Extruder::current->tempControl.sensorType == 0) #endif ) { destinationSteps[E_AXIS] = e * axisStepsPerMM[E_AXIS]; } else { destinationSteps[E_AXIS] = currentPositionSteps[E_AXIS]; } if(f != IGNORE_COORDINATE) feedrate = f; #if NONLINEAR_SYSTEM if (!PrintLine::queueNonlinearMove(ALWAYS_CHECK_ENDSTOPS, pathOptimize, true)) { Com::printWarningFLN(PSTR("moveToReal / queueDeltaMove returns error")); SHOWM(x); SHOWM(y); SHOWM(z); return 0; } #else PrintLine::queueCartesianMove(ALWAYS_CHECK_ENDSTOPS, pathOptimize); #endif return 1; } void Printer::setOrigin(float xOff, float yOff, float zOff) { coordinateOffset[X_AXIS] = xOff;// offset from G92 coordinateOffset[Y_AXIS] = yOff; coordinateOffset[Z_AXIS] = zOff; } /** Computes currentPosition from currentPositionSteps including correction for offset. */ void Printer::updateCurrentPosition(bool copyLastCmd) { #if DUAL_X_AXIS && LAZY_DUAL_X_AXIS if(!sledParked) currentPosition[X_AXIS] = static_cast(currentPositionSteps[X_AXIS]) * invAxisStepsPerMM[X_AXIS]; #else currentPosition[X_AXIS] = static_cast(currentPositionSteps[X_AXIS]) * invAxisStepsPerMM[X_AXIS]; #endif currentPosition[Y_AXIS] = static_cast(currentPositionSteps[Y_AXIS]) * invAxisStepsPerMM[Y_AXIS]; #if NONLINEAR_SYSTEM currentPosition[Z_AXIS] = static_cast(currentPositionSteps[Z_AXIS]) * invAxisStepsPerMM[Z_AXIS] - offsetZ2; #else currentPosition[Z_AXIS] = static_cast(currentPositionSteps[Z_AXIS] - zCorrectionStepsIncluded) * invAxisStepsPerMM[Z_AXIS] - offsetZ2; #endif transformFromPrinter(currentPosition[X_AXIS], currentPosition[Y_AXIS], currentPosition[Z_AXIS], currentPosition[X_AXIS], currentPosition[Y_AXIS], currentPosition[Z_AXIS]); currentPosition[X_AXIS] -= Printer::offsetX; // Offset from active extruder or z probe currentPosition[Y_AXIS] -= Printer::offsetY; currentPosition[Z_AXIS] -= Printer::offsetZ; if(copyLastCmd) { lastCmdPos[X_AXIS] = currentPosition[X_AXIS]; lastCmdPos[Y_AXIS] = currentPosition[Y_AXIS]; lastCmdPos[Z_AXIS] = currentPosition[Z_AXIS]; } } void Printer::updateCurrentPositionSteps() { float x_rotc, y_rotc, z_rotc; transformToPrinter(currentPosition[X_AXIS] + Printer::offsetX, currentPosition[Y_AXIS] + Printer::offsetY, currentPosition[Z_AXIS] + Printer::offsetZ, x_rotc, y_rotc, z_rotc); z_rotc += offsetZ2; currentPositionSteps[X_AXIS] = static_cast(floor(x_rotc * axisStepsPerMM[X_AXIS] + 0.5f)); currentPositionSteps[Y_AXIS] = static_cast(floor(y_rotc * axisStepsPerMM[Y_AXIS] + 0.5f)); currentPositionSteps[Z_AXIS] = static_cast(floor(z_rotc * axisStepsPerMM[Z_AXIS] + 0.5f)); #if NONLINEAR_SYSTEM transformCartesianStepsToDeltaSteps(Printer::currentPositionSteps, Printer::currentNonlinearPositionSteps); #endif #if DRIVE_SYSTEM != DELTA zCorrectionStepsIncluded = 0; #endif } /** \brief Sets the destination coordinates to values stored in com. Extracts x,y,z,e,f from g-code considering active units. Converted result is stored in currentPosition and lastCmdPos. Converts position to destinationSteps including rotation and offsets, excluding distortion correction (which gets added on move queuing). \param com g-code with new destination position. \return true if it is a move, false if no move results from coordinates. */ uint8_t Printer::setDestinationStepsFromGCode(GCode *com) { register int32_t p; float x, y, z; bool posAllowed = true; #if FEATURE_RETRACTION if(com->hasNoXYZ() && com->hasE() && isAutoretract()) { // convert into auto retract if(relativeCoordinateMode || relativeExtruderCoordinateMode) { Extruder::current->retract(com->E < 0, false); } else { p = convertToMM(com->E * axisStepsPerMM[E_AXIS]); // target position Extruder::current->retract(p < currentPositionSteps[E_AXIS], false); } return 0; // Fake no move so nothing gets added } #endif #if MOVE_X_WHEN_HOMED == 1 || MOVE_Y_WHEN_HOMED == 1 || MOVE_Z_WHEN_HOMED == 1 if(!isNoDestinationCheck()) { #if MOVE_X_WHEN_HOMED if(!isXHomed()) com->unsetX(); #endif #if MOVE_Y_WHEN_HOMED if(!isYHomed()) com->unsetY(); #endif #if MOVE_Z_WHEN_HOMED if(!isZHomed()) com->unsetZ(); #endif } #endif #if DISTORTION_CORRECTION == 0 if(!com->hasNoXYZ()) { #endif if(!relativeCoordinateMode) { if(com->hasX()) lastCmdPos[X_AXIS] = currentPosition[X_AXIS] = convertToMM(com->X) - coordinateOffset[X_AXIS]; if(com->hasY()) lastCmdPos[Y_AXIS] = currentPosition[Y_AXIS] = convertToMM(com->Y) - coordinateOffset[Y_AXIS]; if(com->hasZ()) lastCmdPos[Z_AXIS] = currentPosition[Z_AXIS] = convertToMM(com->Z) - coordinateOffset[Z_AXIS]; } else { if(com->hasX()) currentPosition[X_AXIS] = (lastCmdPos[X_AXIS] += convertToMM(com->X)); if(com->hasY()) currentPosition[Y_AXIS] = (lastCmdPos[Y_AXIS] += convertToMM(com->Y)); if(com->hasZ()) currentPosition[Z_AXIS] = (lastCmdPos[Z_AXIS] += convertToMM(com->Z)); } transformToPrinter(lastCmdPos[X_AXIS] + Printer::offsetX, lastCmdPos[Y_AXIS] + Printer::offsetY, lastCmdPos[Z_AXIS] + Printer::offsetZ, x, y, z); z += offsetZ2; destinationSteps[X_AXIS] = static_cast(floor(x * axisStepsPerMM[X_AXIS] + 0.5f)); destinationSteps[Y_AXIS] = static_cast(floor(y * axisStepsPerMM[Y_AXIS] + 0.5f)); destinationSteps[Z_AXIS] = static_cast(floor(z * axisStepsPerMM[Z_AXIS] + 0.5f)); #if LAZY_DUAL_X_AXIS sledParked = false; #endif posAllowed = com->hasNoXYZ() || Printer::isPositionAllowed(lastCmdPos[X_AXIS], lastCmdPos[Y_AXIS], lastCmdPos[Z_AXIS]); #if DISTORTION_CORRECTION == 0 } #endif #if DUAL_X_AXIS && LAZY_DUAL_X_AXIS if(sledParked) { destinationSteps[X_AXIS] = currentPositionSteps[X_AXIS]; destinationSteps[Y_AXIS] = currentPositionSteps[Y_AXIS]; destinationSteps[Z_AXIS] = currentPositionSteps[Z_AXIS]; } #endif if(com->hasE() && !Printer::debugDryrun()) { p = convertToMM(com->E * axisStepsPerMM[E_AXIS]); if(relativeCoordinateMode || relativeExtruderCoordinateMode) { if( #if MIN_EXTRUDER_TEMP > 20 (Extruder::current->tempControl.currentTemperatureC < MIN_EXTRUDER_TEMP && !Printer::isColdExtrusionAllowed() && Extruder::current->tempControl.sensorType != 0) || #endif fabs(com->E) * extrusionFactor > EXTRUDE_MAXLENGTH) p = 0; destinationSteps[E_AXIS] = currentPositionSteps[E_AXIS] + p; } else { if( #if MIN_EXTRUDER_TEMP > 20 (Extruder::current->tempControl.currentTemperatureC < MIN_EXTRUDER_TEMP && !Printer::isColdExtrusionAllowed() && Extruder::current->tempControl.sensorType != 0) || #endif fabs(p - currentPositionSteps[E_AXIS]) * extrusionFactor > EXTRUDE_MAXLENGTH * axisStepsPerMM[E_AXIS]) currentPositionSteps[E_AXIS] = p; destinationSteps[E_AXIS] = p; } } else Printer::destinationSteps[E_AXIS] = Printer::currentPositionSteps[E_AXIS]; if(com->hasF() && com->F > 0.1) { if(unitIsInches) feedrate = com->F * 0.0042333f * (float)feedrateMultiply; // Factor is 25.5/60/100 else feedrate = com->F * (float)feedrateMultiply * 0.00016666666f; } if(!posAllowed) { currentPositionSteps[E_AXIS] = destinationSteps[E_AXIS]; return false; // ignore move } return !com->hasNoXYZ() || (com->hasE() && destinationSteps[E_AXIS] != currentPositionSteps[E_AXIS]); // ignore unproductive moves } void Printer::setup() { HAL::stopWatchdog(); for(uint8_t i = 0; i < NUM_PWM; i++) pwm_pos[i] = 0; #if FEATURE_CONTROLLER == CONTROLLER_VIKI HAL::delayMilliseconds(100); #endif // FEATURE_CONTROLLER #if defined(MB_SETUP) MB_SETUP; #endif #if UI_DISPLAY_TYPE != NO_DISPLAY Com::selectLanguage(0); // just make sure we have a language in case someone uses it early #endif //HAL::delayMilliseconds(500); // add a delay at startup to give hardware time for initalization #if defined(EEPROM_AVAILABLE) && defined(EEPROM_SPI_ALLIGATOR) && EEPROM_AVAILABLE == EEPROM_SPI_ALLIGATOR HAL::spiBegin(); #endif HAL::hwSetup(); EVENT_INITIALIZE_EARLY #ifdef ANALYZER // Channel->pin assignments #if ANALYZER_CH0>=0 SET_OUTPUT(ANALYZER_CH0); #endif #if ANALYZER_CH1>=0 SET_OUTPUT(ANALYZER_CH1); #endif #if ANALYZER_CH2>=0 SET_OUTPUT(ANALYZER_CH2); #endif #if ANALYZER_CH3>=0 SET_OUTPUT(ANALYZER_CH3); #endif #if ANALYZER_CH4>=0 SET_OUTPUT(ANALYZER_CH4); #endif #if ANALYZER_CH5>=0 SET_OUTPUT(ANALYZER_CH5); #endif #if ANALYZER_CH6>=0 SET_OUTPUT(ANALYZER_CH6); #endif #if ANALYZER_CH7>=0 SET_OUTPUT(ANALYZER_CH7); #endif #endif #if defined(ENABLE_POWER_ON_STARTUP) && ENABLE_POWER_ON_STARTUP && (PS_ON_PIN>-1) SET_OUTPUT(PS_ON_PIN); //GND WRITE(PS_ON_PIN, (POWER_INVERTING ? HIGH : LOW)); Printer::setPowerOn(true); #else #if PS_ON_PIN > -1 SET_OUTPUT(PS_ON_PIN); //GND WRITE(PS_ON_PIN, (POWER_INVERTING ? LOW : HIGH)); Printer::setPowerOn(false); #else Printer::setPowerOn(true); #endif #endif #if SDSUPPORT //power to SD reader #if SDPOWER > -1 SET_OUTPUT(SDPOWER); WRITE(SDPOWER, HIGH); #endif #if defined(SDCARDDETECT) && SDCARDDETECT > -1 SET_INPUT(SDCARDDETECT); PULLUP(SDCARDDETECT, HIGH); #endif #endif //Initialize Step Pins SET_OUTPUT(X_STEP_PIN); SET_OUTPUT(Y_STEP_PIN); SET_OUTPUT(Z_STEP_PIN); endXYZSteps(); //Initialize Dir Pins #if X_DIR_PIN > -1 SET_OUTPUT(X_DIR_PIN); #endif #if Y_DIR_PIN > -1 SET_OUTPUT(Y_DIR_PIN); #endif #if Z_DIR_PIN > -1 SET_OUTPUT(Z_DIR_PIN); #endif //Steppers default to disabled. #if X_ENABLE_PIN > -1 SET_OUTPUT(X_ENABLE_PIN); WRITE(X_ENABLE_PIN, !X_ENABLE_ON); #endif #if Y_ENABLE_PIN > -1 SET_OUTPUT(Y_ENABLE_PIN); WRITE(Y_ENABLE_PIN, !Y_ENABLE_ON); #endif #if Z_ENABLE_PIN > -1 SET_OUTPUT(Z_ENABLE_PIN); WRITE(Z_ENABLE_PIN, !Z_ENABLE_ON); #endif #if FEATURE_TWO_XSTEPPER || DUAL_X_AXIS SET_OUTPUT(X2_STEP_PIN); SET_OUTPUT(X2_DIR_PIN); #if X2_ENABLE_PIN > -1 SET_OUTPUT(X2_ENABLE_PIN); WRITE(X2_ENABLE_PIN, !X_ENABLE_ON); #endif #endif #if FEATURE_TWO_YSTEPPER SET_OUTPUT(Y2_STEP_PIN); SET_OUTPUT(Y2_DIR_PIN); #if Y2_ENABLE_PIN > -1 SET_OUTPUT(Y2_ENABLE_PIN); WRITE(Y2_ENABLE_PIN, !Y_ENABLE_ON); #endif #endif #if FEATURE_TWO_ZSTEPPER SET_OUTPUT(Z2_STEP_PIN); SET_OUTPUT(Z2_DIR_PIN); #if Z2_ENABLE_PIN > -1 SET_OUTPUT(Z2_ENABLE_PIN); WRITE(Z2_ENABLE_PIN, !Z_ENABLE_ON); #endif #endif #if FEATURE_THREE_ZSTEPPER SET_OUTPUT(Z3_STEP_PIN); SET_OUTPUT(Z3_DIR_PIN); #if Z3_ENABLE_PIN > -1 SET_OUTPUT(Z3_ENABLE_PIN); WRITE(Z3_ENABLE_PIN, !Z_ENABLE_ON); #endif #endif #if FEATURE_FOUR_ZSTEPPER SET_OUTPUT(Z4_STEP_PIN); SET_OUTPUT(Z4_DIR_PIN); #if Z4_ENABLE_PIN > -1 SET_OUTPUT(Z4_ENABLE_PIN); WRITE(Z4_ENABLE_PIN, !Z_ENABLE_ON); #endif #endif #if defined(DOOR_PIN) && DOOR_PIN > -1 SET_INPUT(DOOR_PIN); #if defined(DOOR_PULLUP) && DOOR_PULLUP PULLUP(DOOR_PIN, HIGH); #endif #endif Endstops::setup(); #if FEATURE_Z_PROBE && Z_PROBE_PIN>-1 SET_INPUT(Z_PROBE_PIN); #if Z_PROBE_PULLUP PULLUP(Z_PROBE_PIN, HIGH); #endif #endif // FEATURE_FEATURE_Z_PROBE #if FAN_PIN > -1 && FEATURE_FAN_CONTROL SET_OUTPUT(FAN_PIN); WRITE(FAN_PIN, LOW); #endif #if FAN2_PIN > -1 && FEATURE_FAN2_CONTROL SET_OUTPUT(FAN2_PIN); WRITE(FAN2_PIN, LOW); #endif #if FAN_THERMO_PIN > -1 SET_OUTPUT(FAN_THERMO_PIN); WRITE(FAN_THERMO_PIN, LOW); #endif #if FAN_BOARD_PIN>-1 SET_OUTPUT(FAN_BOARD_PIN); WRITE(FAN_BOARD_PIN, LOW); pwm_pos[PWM_BOARD_FAN] = BOARD_FAN_MIN_SPEED; #endif #if defined(EXT0_HEATER_PIN) && EXT0_HEATER_PIN>-1 SET_OUTPUT(EXT0_HEATER_PIN); WRITE(EXT0_HEATER_PIN, HEATER_PINS_INVERTED); #endif #if defined(EXT1_HEATER_PIN) && EXT1_HEATER_PIN>-1 && NUM_EXTRUDER>1 SET_OUTPUT(EXT1_HEATER_PIN); WRITE(EXT1_HEATER_PIN, HEATER_PINS_INVERTED); #endif #if defined(EXT2_HEATER_PIN) && EXT2_HEATER_PIN>-1 && NUM_EXTRUDER>2 SET_OUTPUT(EXT2_HEATER_PIN); WRITE(EXT2_HEATER_PIN, HEATER_PINS_INVERTED); #endif #if defined(EXT3_HEATER_PIN) && EXT3_HEATER_PIN>-1 && NUM_EXTRUDER>3 SET_OUTPUT(EXT3_HEATER_PIN); WRITE(EXT3_HEATER_PIN, HEATER_PINS_INVERTED); #endif #if defined(EXT4_HEATER_PIN) && EXT4_HEATER_PIN>-1 && NUM_EXTRUDER>4 SET_OUTPUT(EXT4_HEATER_PIN); WRITE(EXT4_HEATER_PIN, HEATER_PINS_INVERTED); #endif #if defined(EXT5_HEATER_PIN) && EXT5_HEATER_PIN>-1 && NUM_EXTRUDER>5 SET_OUTPUT(EXT5_HEATER_PIN); WRITE(EXT5_HEATER_PIN, HEATER_PINS_INVERTED); #endif #if defined(EXT0_EXTRUDER_COOLER_PIN) && EXT0_EXTRUDER_COOLER_PIN>-1 SET_OUTPUT(EXT0_EXTRUDER_COOLER_PIN); WRITE(EXT0_EXTRUDER_COOLER_PIN, LOW); #endif #if defined(EXT1_EXTRUDER_COOLER_PIN) && EXT1_EXTRUDER_COOLER_PIN > -1 && NUM_EXTRUDER > 1 SET_OUTPUT(EXT1_EXTRUDER_COOLER_PIN); WRITE(EXT1_EXTRUDER_COOLER_PIN, LOW); #endif #if defined(EXT2_EXTRUDER_COOLER_PIN) && EXT2_EXTRUDER_COOLER_PIN > -1 && NUM_EXTRUDER > 2 SET_OUTPUT(EXT2_EXTRUDER_COOLER_PIN); WRITE(EXT2_EXTRUDER_COOLER_PIN, LOW); #endif #if defined(EXT3_EXTRUDER_COOLER_PIN) && EXT3_EXTRUDER_COOLER_PIN > -1 && NUM_EXTRUDER > 3 SET_OUTPUT(EXT3_EXTRUDER_COOLER_PIN); WRITE(EXT3_EXTRUDER_COOLER_PIN, LOW); #endif #if defined(EXT4_EXTRUDER_COOLER_PIN) && EXT4_EXTRUDER_COOLER_PIN > -1 && NUM_EXTRUDER > 4 SET_OUTPUT(EXT4_EXTRUDER_COOLER_PIN); WRITE(EXT4_EXTRUDER_COOLER_PIN, LOW); #endif #if defined(EXT5_EXTRUDER_COOLER_PIN) && EXT5_EXTRUDER_COOLER_PIN > -1 && NUM_EXTRUDER > 5 SET_OUTPUT(EXT5_EXTRUDER_COOLER_PIN); WRITE(EXT5_EXTRUDER_COOLER_PIN, LOW); #endif // Initialize jam sensors #if defined(EXT0_JAM_PIN) && EXT0_JAM_PIN > -1 SET_INPUT(EXT0_JAM_PIN); PULLUP(EXT0_JAM_PIN, EXT0_JAM_PULLUP); #endif // defined #if defined(EXT1_JAM_PIN) && EXT1_JAM_PIN > -1 SET_INPUT(EXT1_JAM_PIN); PULLUP(EXT1_JAM_PIN, EXT1_JAM_PULLUP); #endif // defined #if defined(EXT2_JAM_PIN) && EXT2_JAM_PIN > -1 SET_INPUT(EXT2_JAM_PIN); PULLUP(EXT2_JAM_PIN, EXT2_JAM_PULLUP); #endif // defined #if defined(EXT3_JAM_PIN) && EXT3_JAM_PIN > -1 SET_INPUT(EXT3_JAM_PIN); PULLUP(EXT3_JAM_PIN, EXT3_JAM_PULLUP); #endif // defined #if defined(EXT4_JAM_PIN) && EXT4_JAM_PIN > -1 SET_INPUT(EXT4_JAM_PIN); PULLUP(EXT4_JAM_PIN, EXT4_JAM_PULLUP); #endif // defined #if defined(EXT5_JAM_PIN) && EXT5_JAM_PIN > -1 SET_INPUT(EXT5_JAM_PIN); PULLUP(EXT5_JAM_PIN, EXT5_JAM_PULLUP); #endif // defined HAL::delayMilliseconds(1); #if defined(EXT0_JAM_PIN) && EXT0_JAM_PIN > -1 extruder[0].jamLastSignal = READ(EXT0_JAM_PIN); #endif // defined #if defined(EXT1_JAM_PIN) && EXT1_JAM_PIN > -1 extruder[1].jamLastSignal = READ(EXT1_JAM_PIN); #endif // defined #if defined(EXT2_JAM_PIN) && EXT2_JAM_PIN > -1 extruder[2].jamLastSignal = READ(EXT2_JAM_PIN); #endif // defined #if defined(EXT3_JAM_PIN) && EXT3_JAM_PIN > -1 extruder[3].jamLastSignal = READ(EXT3_JAM_PIN); #endif // defined #if defined(EXT4_JAM_PIN) && EXT4_JAM_PIN > -1 extruder[4].jamLastSignal = READ(EXT4_JAM_PIN); #endif // defined #if defined(EXT5_JAM_PIN) && EXT5_JAM_PIN > -1 extruder[5].jamLastSignal = READ(EXT5_JAM_PIN); #endif // defined #if CASE_LIGHTS_PIN >= 0 SET_OUTPUT(CASE_LIGHTS_PIN); WRITE(CASE_LIGHTS_PIN, CASE_LIGHT_DEFAULT_ON); #endif // CASE_LIGHTS_PIN #if defined(UI_VOLTAGE_LEVEL) && defined(EXP_VOLTAGE_LEVEL_PIN) && EXP_VOLTAGE_LEVEL_PIN >-1 SET_OUTPUT(EXP_VOLTAGE_LEVEL_PIN); WRITE(EXP_VOLTAGE_LEVEL_PIN, UI_VOLTAGE_LEVEL); #endif // UI_VOLTAGE_LEVEL #if defined(SUPPORT_LASER) && SUPPORT_LASER LaserDriver::initialize(); #endif // defined #if defined(SUPPORT_CNC) && SUPPORT_CNC CNCDriver::initialize(); #endif // defined #if GANTRY && !defined(FAST_COREXYZ) Printer::motorX = 0; Printer::motorYorZ = 0; #endif #ifdef RED_BLUE_STATUS_LEDS SET_OUTPUT(RED_STATUS_LED); SET_OUTPUT(BLUE_STATUS_LED); WRITE(BLUE_STATUS_LED, HIGH); WRITE(RED_STATUS_LED, LOW); #endif // RED_BLUE_STATUS_LEDS #if defined(DRV_TMC2130) // TMC2130 motor drivers #if TMC2130_ON_X Printer::tmc_driver_x = new TMC2130Stepper(X_ENABLE_PIN, X_DIR_PIN, X_STEP_PIN, TMC2130_X_CS_PIN); configTMC2130(Printer::tmc_driver_x, TMC2130_STEALTHCHOP_X, TMC2130_STALLGUARD_X, TMC2130_PWM_AMPL_X, TMC2130_PWM_GRAD_X, TMC2130_PWM_AUTOSCALE_X, TMC2130_PWM_FREQ_X); #endif #if TMC2130_ON_Y > 0 Printer::tmc_driver_y = new TMC2130Stepper(Y_ENABLE_PIN, Y_DIR_PIN, Y_STEP_PIN, TMC2130_Y_CS_PIN); configTMC2130(Printer::tmc_driver_y, TMC2130_STEALTHCHOP_Y, TMC2130_STALLGUARD_Y, TMC2130_PWM_AMPL_Y, TMC2130_PWM_GRAD_Y, TMC2130_PWM_AUTOSCALE_Y, TMC2130_PWM_FREQ_Y); #endif #if TMC2130_ON_Z > 0 Printer::tmc_driver_z = new TMC2130Stepper(Z_ENABLE_PIN, Z_DIR_PIN, Z_STEP_PIN, TMC2130_Z_CS_PIN); configTMC2130(Printer::tmc_driver_z, TMC2130_STEALTHCHOP_Z, TMC2130_STALLGUARD_Z, TMC2130_PWM_AMPL_Z, TMC2130_PWM_GRAD_Z, TMC2130_PWM_AUTOSCALE_Z, TMC2130_PWM_FREQ_Z); #endif #if TMC2130_ON_EXT0 > 0 Printer::tmc_driver_e0 = new TMC2130Stepper(EXT0_ENABLE_PIN, EXT0_DIR_PIN, EXT0_STEP_PIN, TMC2130_EXT0_CS_PIN); configTMC2130(Printer::tmc_driver_e0, TMC2130_STEALTHCHOP_EXT0, TMC2130_STALLGUARD_EXT0, TMC2130_PWM_AMPL_EXT0, TMC2130_PWM_GRAD_EXT0, TMC2130_PWM_AUTOSCALE_EXT0, TMC2130_PWM_FREQ_EXT0); #endif #if TMC2130_ON_EXT1 > 0 Printer::tmc_driver_e1 = new TMC2130Stepper(EXT1_ENABLE_PIN, EXT1_DIR_PIN, EXT1_STEP_PIN, TMC2130_EXT1_CS_PIN); configTMC2130(Printer::tmc_driver_e1, TMC2130_STEALTHCHOP_EXT1, TMC2130_STALLGUARD_EXT1, TMC2130_PWM_AMPL_EXT1, TMC2130_PWM_GRAD_EXT1, TMC2130_PWM_AUTOSCALE_EXT1, TMC2130_PWM_FREQ_EXT1); #endif #if TMC2130_ON_EXT2 > 0 Printer::tmc_driver_e2 = new TMC2130Stepper(EXT2_ENABLE_PIN, EXT2_DIR_PIN, EXT2_STEP_PIN, TMC2130_EXT2_CS_PIN); configTMC2130(Printer::tmc_driver_e2, TMC2130_STEALTHCHOP_EXT2, TMC2130_STALLGUARD_EXT2, TMC2130_PWM_AMPL_EXT2, TMC2130_PWM_GRAD_EXT2, TMC2130_PWM_AUTOSCALE_EXT2, TMC2130_PWM_FREQ_EXT2); #endif #endif // DRV_TMC2130 #if STEPPER_CURRENT_CONTROL != CURRENT_CONTROL_MANUAL motorCurrentControlInit(); // Set current if it is firmware controlled #endif #if defined(NUM_MOTOR_DRIVERS) && NUM_MOTOR_DRIVERS > 0 initializeAllMotorDrivers(); #endif // defined microstepInit(); #if FEATURE_AUTOLEVEL resetTransformationMatrix(true); #endif // FEATURE_AUTOLEVEL feedrate = 50; ///< Current feedrate in mm/s. feedrateMultiply = 100; extrudeMultiply = 100; lastCmdPos[X_AXIS] = lastCmdPos[Y_AXIS] = lastCmdPos[Z_AXIS] = 0; #if USE_ADVANCE #if ENABLE_QUADRATIC_ADVANCE advanceExecuted = 0; #endif advanceStepsSet = 0; #endif maxJerk = MAX_JERK; #if DRIVE_SYSTEM != DELTA maxZJerk = MAX_ZJERK; #endif offsetX = offsetY = offsetZ = 0; interval = 5000; stepsPerTimerCall = 1; msecondsPrinting = 0; filamentPrinted = 0; flag0 = PRINTER_FLAG0_STEPPER_DISABLED; xLength = X_MAX_LENGTH; yLength = Y_MAX_LENGTH; zLength = Z_MAX_LENGTH; xMin = X_MIN_POS; yMin = Y_MIN_POS; zMin = Z_MIN_POS; #if DRIVE_SYSTEM == DELTA radius0 = ROD_RADIUS; #endif #if ENABLE_BACKLASH_COMPENSATION backlashX = X_BACKLASH; backlashY = Y_BACKLASH; backlashZ = Z_BACKLASH; backlashDir = 0; #endif #if USE_ADVANCE extruderStepsNeeded = 0; #endif #if (MOTHERBOARD == 502) SET_INPUT(FTDI_COM_RESET_PIN); SET_INPUT(ESP_WIFI_MODULE_COM); SET_INPUT(MOTOR_FAULT_PIN); SET_INPUT(MOTOR_FAULT_PIGGY_PIN); #endif //(MOTHERBOARD == 501) || (MOTHERBOARD == 502) EEPROM::initBaudrate(); HAL::serialSetBaudrate(baudrate); Com::printFLN(Com::tStart); HAL::showStartReason(); Extruder::initExtruder(); // sets auto leveling in eeprom init EEPROM::init(); // Read settings from eeprom if wanted UI_INITIALIZE; for(uint8_t i = 0; i < E_AXIS_ARRAY; i++) { currentPositionSteps[i] = 0; } currentPosition[X_AXIS] = currentPosition[Y_AXIS] = currentPosition[Z_AXIS] = 0.0; //Commands::printCurrentPosition(); #if DISTORTION_CORRECTION distortion.init(); #endif // DISTORTION_CORRECTION updateDerivedParameter(); Commands::checkFreeMemory(); Commands::writeLowestFreeRAM(); HAL::setupTimer(); #if FEATURE_WATCHDOG HAL::startWatchdog(); #endif // FEATURE_WATCHDOG #if SDSUPPORT sd.mount(); #endif #if NONLINEAR_SYSTEM transformCartesianStepsToDeltaSteps(Printer::currentPositionSteps, Printer::currentNonlinearPositionSteps); #if DELTA_HOME_ON_POWER homeAxis(true, true, true); #endif setAutoretract(EEPROM_BYTE(AUTORETRACT_ENABLED)); Commands::printCurrentPosition(); #endif // DRIVE_SYSTEM Extruder::selectExtruderById(0); #if FEATURE_SERVO // set servos to neutral positions at power_up #if defined(SERVO0_NEUTRAL_POS) && SERVO0_NEUTRAL_POS >= 500 HAL::servoMicroseconds(0, SERVO0_NEUTRAL_POS, 1000); #endif #if defined(SERVO1_NEUTRAL_POS) && SERVO1_NEUTRAL_POS >= 500 HAL::servoMicroseconds(1, SERVO1_NEUTRAL_POS, 1000); #endif #if defined(SERVO2_NEUTRAL_POS) && SERVO2_NEUTRAL_POS >= 500 HAL::servoMicroseconds(2, SERVO2_NEUTRAL_POS, 1000); #endif #if defined(SERVO3_NEUTRAL_POS) && SERVO3_NEUTRAL_POS >= 500 HAL::servoMicroseconds(3, SERVO3_NEUTRAL_POS, 1000); #endif #endif EVENT_INITIALIZE; #ifdef STARTUP_GCODE GCode::executeFString(Com::tStartupGCode); #endif #if EEPROM_MODE != 0 && UI_DISPLAY_TYPE != NO_DISPLAY if(EEPROM::getStoredLanguage() == 254) { Com::printFLN(PSTR("Needs language selection")); uid.showLanguageSelectionWizard(); } #endif // EEPROM_MODE } void Printer::defaultLoopActions() { Commands::checkForPeriodicalActions(true); //check heater every n milliseconds UI_MEDIUM; // do check encoder millis_t curtime = HAL::timeInMilliseconds(); if(PrintLine::hasLines() || isMenuMode(MENU_MODE_SD_PRINTING + MENU_MODE_PAUSED)) previousMillisCmd = curtime; else { curtime -= previousMillisCmd; if(maxInactiveTime != 0 && curtime > maxInactiveTime ) Printer::kill(false); else Printer::setAllKilled(false); // prevent repeated kills if(stepperInactiveTime != 0 && curtime > stepperInactiveTime ) Printer::kill(true); } #if SDCARDDETECT > -1 && SDSUPPORT sd.automount(); #endif #if defined(EEPROM_AVAILABLE) && EEPROM_AVAILABLE == EEPROM_SDCARD HAL::syncEEPROM(); #endif DEBUG_MEMORY; } void Printer::MemoryPosition() { Commands::waitUntilEndOfAllMoves(); updateCurrentPosition(false); realPosition(memoryX, memoryY, memoryZ); memoryE = currentPositionSteps[E_AXIS] * invAxisStepsPerMM[E_AXIS]; memoryF = feedrate; } void Printer::GoToMemoryPosition(bool x, bool y, bool z, bool e, float feed) { if(memoryF < 0) return; // Not stored before call, so we ignore it bool all = !(x || y || z); moveToReal((all || x ? (lastCmdPos[X_AXIS] = memoryX) : IGNORE_COORDINATE) , (all || y ? (lastCmdPos[Y_AXIS] = memoryY) : IGNORE_COORDINATE) , (all || z ? (lastCmdPos[Z_AXIS] = memoryZ) : IGNORE_COORDINATE) , (e ? memoryE : IGNORE_COORDINATE), feed); feedrate = memoryF; updateCurrentPosition(false); } #if DRIVE_SYSTEM == DELTA void Printer::deltaMoveToTopEndstops(float feedrate) { for (fast8_t i = 0; i < 3; i++) Printer::currentPositionSteps[i] = 0; Printer::stepsRemainingAtXHit = -1; Printer::stepsRemainingAtYHit = -1; Printer::stepsRemainingAtZHit = -1; setHoming(true); transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); PrintLine::moveRelativeDistanceInSteps(0, 0, (zMaxSteps + EEPROM::deltaDiagonalRodLength()*axisStepsPerMM[Z_AXIS]) * 1.5, 0, feedrate, true, true); offsetX = offsetY = offsetZ = offsetZ2 = 0; setHoming(false); } void Printer::homeXAxis() { destinationSteps[X_AXIS] = 0; if (!PrintLine::queueNonlinearMove(true, false, false)) { Com::printWarningFLN(PSTR("homeXAxis / queueDeltaMove returns error")); } } void Printer::homeYAxis() { Printer::destinationSteps[Y_AXIS] = 0; if (!PrintLine::queueNonlinearMove(true, false, false)) { Com::printWarningFLN(PSTR("homeYAxis / queueDeltaMove returns error")); } } void Printer::homeZAxis() { // Delta z homing bool homingSuccess = false; Endstops::resetAccumulator(); deltaMoveToTopEndstops(Printer::homingFeedrate[Z_AXIS]); // New safe homing routine by Kyrre Aalerud // This method will safeguard against sticky endstops such as may be gotten cheaply from china. // This can lead to head crashes and even fire, thus a safer algorithm to ensure the endstops actually respond as expected. //Endstops::report(); // Check that all endstops (XYZ) were hit Endstops::fillFromAccumulator(); if (Endstops::xMax() && Endstops::yMax() && Endstops::zMax()) { // Back off for retest PrintLine::moveRelativeDistanceInSteps(0, 0, axisStepsPerMM[Z_AXIS] * -ENDSTOP_Z_BACK_MOVE, 0, Printer::homingFeedrate[Z_AXIS] / ENDSTOP_X_RETEST_REDUCTION_FACTOR, true, true); //Endstops::report(); // Check for proper release of all (XYZ) endstops if (!(Endstops::xMax() || Endstops::yMax() || Endstops::zMax())) { // Rehome with reduced speed Endstops::resetAccumulator(); deltaMoveToTopEndstops(Printer::homingFeedrate[Z_AXIS] / ENDSTOP_Z_RETEST_REDUCTION_FACTOR); Endstops::fillFromAccumulator(); //Endstops::report(); // Check that all endstops (XYZ) were hit again if (Endstops::xMax() && Endstops::yMax() && Endstops::zMax()) { homingSuccess = true; // Assume success in case there is no back move #if defined(ENDSTOP_Z_BACK_ON_HOME) if(ENDSTOP_Z_BACK_ON_HOME > 0) { PrintLine::moveRelativeDistanceInSteps(0, 0, axisStepsPerMM[Z_AXIS] * -ENDSTOP_Z_BACK_ON_HOME, 0, homingFeedrate[Z_AXIS], true, true); //Endstops::report(); // Check for missing release of any (XYZ) endstop if (Endstops::xMax() || Endstops::yMax() || Endstops::zMax()) { homingSuccess = false; // Reset success flag } } #endif } } } // Check if homing failed. If so, request pause! if (!homingSuccess) { setXHomed(false); setYHomed(false); setZHomed(false); GCodeSource::printAllFLN(PSTR("RequestPause:Homing failed!")); } else { setXHomed(true); setYHomed(true); setZHomed(true); } // Correct different end stop heights // These can be adjusted by two methods. You can use offsets stored by determining the center // or you can use the xyzMinSteps from G100 calibration. Both have the same effect but only one // should be measured as both have the same effect. long dx = -xMinSteps - EEPROM::deltaTowerXOffsetSteps(); long dy = -yMinSteps - EEPROM::deltaTowerYOffsetSteps(); long dz = -zMinSteps - EEPROM::deltaTowerZOffsetSteps(); long dm = RMath::min(dx, dy, dz); //Com::printFLN(Com::tTower1,dx); //Com::printFLN(Com::tTower2,dy); //Com::printFLN(Com::tTower3,dz); dx -= dm; // now all dxyz are positive dy -= dm; dz -= dm; currentPositionSteps[X_AXIS] = 0; // here we should be currentPositionSteps[Y_AXIS] = 0; currentPositionSteps[Z_AXIS] = zMaxSteps; transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); currentNonlinearPositionSteps[A_TOWER] -= dx; currentNonlinearPositionSteps[B_TOWER] -= dy; currentNonlinearPositionSteps[C_TOWER] -= dz; PrintLine::moveRelativeDistanceInSteps(0, 0, dm, 0, homingFeedrate[Z_AXIS], true, false); currentPositionSteps[X_AXIS] = 0; // now we are really here currentPositionSteps[Y_AXIS] = 0; currentPositionSteps[Z_AXIS] = zMaxSteps - zBedOffset * axisStepsPerMM[Z_AXIS]; // Extruder is now exactly in the delta center coordinateOffset[X_AXIS] = 0; coordinateOffset[Y_AXIS] = 0; coordinateOffset[Z_AXIS] = 0; transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); realDeltaPositionSteps[A_TOWER] = currentNonlinearPositionSteps[A_TOWER]; realDeltaPositionSteps[B_TOWER] = currentNonlinearPositionSteps[B_TOWER]; realDeltaPositionSteps[C_TOWER] = currentNonlinearPositionSteps[C_TOWER]; //maxDeltaPositionSteps = currentDeltaPositionSteps[X_AXIS]; #if defined(ENDSTOP_Z_BACK_ON_HOME) if(ENDSTOP_Z_BACK_ON_HOME > 0) maxDeltaPositionSteps += axisStepsPerMM[Z_AXIS] * ENDSTOP_Z_BACK_ON_HOME; #endif Extruder::selectExtruderById(Extruder::current->id); #if FEATURE_BABYSTEPPING Printer::zBabysteps = 0; #endif } // This home axis is for delta void Printer::homeAxis(bool xaxis, bool yaxis, bool zaxis) { // Delta homing code bool nocheck = isNoDestinationCheck(); setNoDestinationCheck(true); #if defined(SUPPORT_LASER) && SUPPORT_LASER bool oldLaser = LaserDriver::laserOn; LaserDriver::laserOn = false; #endif bool autoLevel = isAutolevelActive(); setAutolevelActive(false); if (!(X_MAX_PIN > -1 && Y_MAX_PIN > -1 && Z_MAX_PIN > -1 && MAX_HARDWARE_ENDSTOP_X && MAX_HARDWARE_ENDSTOP_Y && MAX_HARDWARE_ENDSTOP_Z)) { Com::printErrorFLN(PSTR("Hardware setup inconsistent. Delta cannot home without max endstops.")); } // The delta has to have home capability to zero and set position, // so the redundant check is only an opportunity to // gratuitously fail due to incorrect settings. // The following movements would be meaningless unless it was zeroed for example. UI_STATUS_UPD_F(Com::translatedF(UI_TEXT_HOME_DELTA_ID)); // Homing Z axis means that you must home X and Y EVENT_BEFORE_Z_HOME; homeZAxis(); moveToReal(0, 0, Printer::zLength - zBedOffset, IGNORE_COORDINATE, homingFeedrate[Z_AXIS]); // Move to designed coordinates including translation updateCurrentPosition(true); updateHomedAll(); UI_CLEAR_STATUS Commands::printCurrentPosition(); setAutolevelActive(autoLevel); #if defined(SUPPORT_LASER) && SUPPORT_LASER LaserDriver::laserOn = oldLaser; #endif Printer::updateCurrentPosition(); setNoDestinationCheck(nocheck); } #else #if DRIVE_SYSTEM == TUGA // Tuga printer homing void Printer::homeXAxis() { long steps; if ((MIN_HARDWARE_ENDSTOP_X && X_MIN_PIN > -1 && X_HOME_DIR == -1 && MIN_HARDWARE_ENDSTOP_Y && Y_MIN_PIN > -1 && Y_HOME_DIR == -1) || (MAX_HARDWARE_ENDSTOP_X && X_MAX_PIN > -1 && X_HOME_DIR == 1 && MAX_HARDWARE_ENDSTOP_Y && Y_MAX_PIN > -1 && Y_HOME_DIR == 1)) { long offX = 0, offY = 0; #if NUM_EXTRUDER>1 for(uint8_t i = 0; i < NUM_EXTRUDER; i++) { #if X_HOME_DIR < 0 offX = RMath::max(offX, extruder[i].xOffset); offY = RMath::max(offY, extruder[i].yOffset); #else offX = RMath::min(offX, extruder[i].xOffset); offY = RMath::min(offY, extruder[i].yOffset); #endif } // Reposition extruder that way, that all extruders can be selected at home pos. #endif UI_STATUS_UPD(UI_TEXT_HOME_X); steps = (Printer::xMaxSteps - Printer::xMinSteps) * X_HOME_DIR; currentPositionSteps[X_AXIS] = -steps; currentPositionSteps[Y_AXIS] = 0; setHoming(true); transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); PrintLine::moveRelativeDistanceInSteps(2 * steps, 0, 0, 0, homingFeedrate[X_AXIS], true, true); currentPositionSteps[X_AXIS] = (X_HOME_DIR == -1) ? xMinSteps - offX : xMaxSteps + offX; currentPositionSteps[Y_AXIS] = 0; //(Y_HOME_DIR == -1) ? yMinSteps-offY : yMaxSteps+offY; //PrintLine::moveRelativeDistanceInSteps(axisStepsPerMM[X_AXIS]*-ENDSTOP_X_BACK_MOVE * X_HOME_DIR,axisStepsPerMM[Y_AXIS]*-ENDSTOP_X_BACK_MOVE * Y_HOME_DIR,0,0,homingFeedrate[X_AXIS]/ENDSTOP_X_RETEST_REDUCTION_FACTOR,true,false); // PrintLine::moveRelativeDistanceInSteps(axisStepsPerMM[X_AXIS]*2*ENDSTOP_X_BACK_MOVE * X_HOME_DIR,axisStepsPerMM[Y_AXIS]*2*ENDSTOP_X_BACK_MOVE * Y_HOME_DIR,0,0,homingFeedrate[X_AXIS]/ENDSTOP_X_RETEST_REDUCTION_FACTOR,true,true); PrintLine::moveRelativeDistanceInSteps(axisStepsPerMM[X_AXIS] * -ENDSTOP_X_BACK_MOVE * X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS] / ENDSTOP_X_RETEST_REDUCTION_FACTOR, true, false); PrintLine::moveRelativeDistanceInSteps(axisStepsPerMM[X_AXIS] * 2 * ENDSTOP_X_BACK_MOVE * X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS] / ENDSTOP_X_RETEST_REDUCTION_FACTOR, true, true); setHoming(false); #if defined(ENDSTOP_X_BACK_ON_HOME) if(ENDSTOP_X_BACK_ON_HOME > 0) PrintLine::moveRelativeDistanceInSteps(axisStepsPerMM[X_AXIS] * -ENDSTOP_X_BACK_ON_HOME * X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS], true, false); // PrintLine::moveRelativeDistanceInSteps(axisStepsPerMM[X_AXIS]*-ENDSTOP_X_BACK_ON_HOME * X_HOME_DIR,axisStepsPerMM[Y_AXIS]*-ENDSTOP_Y_BACK_ON_HOME * Y_HOME_DIR,0,0,homingFeedrate[X_AXIS],true,false); #endif currentPositionSteps[X_AXIS] = (X_HOME_DIR == -1) ? xMinSteps - offX : xMaxSteps + offX; currentPositionSteps[Y_AXIS] = 0; //(Y_HOME_DIR == -1) ? yMinSteps-offY : yMaxSteps+offY; coordinateOffset[X_AXIS] = 0; coordinateOffset[Y_AXIS] = 0; transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); #if NUM_EXTRUDER>1 PrintLine::moveRelativeDistanceInSteps((Extruder::current->xOffset - offX) * X_HOME_DIR, (Extruder::current->yOffset - offY) * Y_HOME_DIR, 0, 0, homingFeedrate[X_AXIS], true, false); #endif setXHomed(true); setYHomed(true); } } void Printer::homeYAxis() { // Dummy function x and y homing must occur together } #else // Cartesian printer void Printer::homeXAxis() { #if defined(SENSORLESS_HOMING) && TMC2130_ON_X while(!Printer::tmc_driver_x->stst()); // Wait for motor stand-still uint32_t coolstep_speed = Printer::tmc_driver_x->coolstep_min_speed(); uint32_t stealth_max_sp = Printer::tmc_driver_x->stealth_max_speed(); bool stealth_state = Printer::tmc_driver_x->stealthChop(); Printer::tmcPrepareHoming(Printer::tmc_driver_x, TMC2130_TCOOLTHRS_X); #endif bool nocheck = isNoDestinationCheck(); setNoDestinationCheck(true); long steps; UI_STATUS_UPD_F(Com::translatedF(UI_TEXT_HOME_X_ID)); Commands::waitUntilEndOfAllMoves(); setHoming(true); #if DUAL_X_AXIS && NUM_EXTRUDER == 2 Extruder *curExtruder = Extruder::current; Extruder::current = &extruder[0]; steps = (Printer::xMaxSteps - Printer::xMinSteps); currentPositionSteps[X_AXIS] = steps; PrintLine::moveRelativeDistanceInSteps(-2 * steps * -X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS], true, true); // first contact PrintLine::moveRelativeDistanceInSteps(axisStepsPerMM[X_AXIS] * ENDSTOP_X_BACK_MOVE * -X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS], true, false); // back move PrintLine::moveRelativeDistanceInSteps(-axisStepsPerMM[X_AXIS] * 2 * ENDSTOP_X_BACK_MOVE * -X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS] / ENDSTOP_X_RETEST_REDUCTION_FACTOR, true, true); // final contact #if defined(ENDSTOP_X_BACK_ON_HOME) if(ENDSTOP_X_BACK_ON_HOME > 0) PrintLine::moveRelativeDistanceInSteps(axisStepsPerMM[X_AXIS] * ENDSTOP_X_BACK_ON_HOME * -X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS], true, false); #endif Extruder::current = &extruder[1]; currentPositionSteps[X_AXIS] = -steps; PrintLine::moveRelativeDistanceInSteps(2 * steps * -X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS], true, true); PrintLine::moveRelativeDistanceInSteps(-axisStepsPerMM[X_AXIS] * ENDSTOP_X_BACK_MOVE * -X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS], true, false); // back move PrintLine::moveRelativeDistanceInSteps(axisStepsPerMM[X_AXIS] * 2 * ENDSTOP_X_BACK_MOVE * -X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS] / ENDSTOP_X_RETEST_REDUCTION_FACTOR, true, true); #if defined(ENDSTOP_X_BACK_ON_HOME) if(ENDSTOP_X_BACK_ON_HOME > 0) PrintLine::moveRelativeDistanceInSteps(-axisStepsPerMM[X_AXIS] * ENDSTOP_X_BACK_ON_HOME * -X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS], true, false); #endif Extruder::current = curExtruder; #if LAZY_DUAL_X_AXIS currentPositionSteps[X_AXIS] = xMinSteps + Extruder::current->xOffset; sledParked = true; currentPosition[X_AXIS] = lastCmdPos[X_AXIS] = xMin; #else // Now position current extrude on x = 0 PrintLine::moveRelativeDistanceInSteps(-Extruder::current->xOffset, 0, 0, 0, homingFeedrate[X_AXIS], true, true); currentPositionSteps[X_AXIS] = xMinSteps; #endif // LAZY_DUAL_X_AXIS updateCurrentPosition(false); offsetX = 0; setXHomed(true); #else // DUAL_AXIS if ((MIN_HARDWARE_ENDSTOP_X && X_MIN_PIN > -1 && X_HOME_DIR == -1) || (MAX_HARDWARE_ENDSTOP_X && X_MAX_PIN > -1 && X_HOME_DIR == 1)) { coordinateOffset[X_AXIS] = 0; long offX = 0; #if NUM_EXTRUDER > 1 for(uint8_t i = 0; i < NUM_EXTRUDER; i++) #if X_HOME_DIR < 0 offX = RMath::max(offX, extruder[i].xOffset); #else offX = RMath::min(offX, extruder[i].xOffset); #endif // Reposition extruder that way, that all extruders can be selected at home position. #endif // NUM_EXTRUDER > 1 steps = (Printer::xMaxSteps - Printer::xMinSteps) * X_HOME_DIR; currentPositionSteps[X_AXIS] = -steps; #if NONLINEAR_SYSTEM transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); #endif PrintLine::moveRelativeDistanceInSteps(2 * steps, 0, 0, 0, homingFeedrate[X_AXIS], true, true); currentPositionSteps[X_AXIS] = (X_HOME_DIR == -1) ? xMinSteps - offX : xMaxSteps + offX; #if NONLINEAR_SYSTEM transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); #endif PrintLine::moveRelativeDistanceInSteps(axisStepsPerMM[X_AXIS] * -ENDSTOP_X_BACK_MOVE * X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS] / ENDSTOP_X_RETEST_REDUCTION_FACTOR, true, false); PrintLine::moveRelativeDistanceInSteps(axisStepsPerMM[X_AXIS] * 2 * ENDSTOP_X_BACK_MOVE * X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS] / ENDSTOP_X_RETEST_REDUCTION_FACTOR, true, true); #if defined(ENDSTOP_X_BACK_ON_HOME) if(ENDSTOP_X_BACK_ON_HOME > 0) PrintLine::moveRelativeDistanceInSteps(axisStepsPerMM[X_AXIS] * -ENDSTOP_X_BACK_ON_HOME * X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS], true, true); #endif currentPositionSteps[X_AXIS] = (X_HOME_DIR == -1) ? xMinSteps - offX : xMaxSteps + offX; #if NONLINEAR_SYSTEM transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); #endif #if NUM_EXTRUDER > 1 #if X_HOME_DIR < 0 PrintLine::moveRelativeDistanceInSteps((Extruder::current->xOffset - offX) * X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS], true, true); #else PrintLine::moveRelativeDistanceInSteps(-(Extruder::current->xOffset - offX) * X_HOME_DIR, 0, 0, 0, homingFeedrate[X_AXIS], true, true); #endif #endif setXHomed(true); } #endif // ELSE dual x axis setNoDestinationCheck(nocheck); setHoming(false); #if defined(SENSORLESS_HOMING) && TMC2130_ON_X while(!Printer::tmc_driver_x->stst()); // Wait for motor stand-still Printer::tmc_driver_x->coolstep_min_speed(coolstep_speed); Printer::tmc_driver_x->stealth_max_speed(stealth_max_sp); Printer::tmc_driver_x->stealthChop(stealth_state); #endif } void Printer::homeYAxis() { #if defined(SENSORLESS_HOMING) && TMC2130_ON_Y while(!Printer::tmc_driver_y->stst()); // Wait for motor stand-still uint32_t coolstep_speed = Printer::tmc_driver_y->coolstep_min_speed(); uint32_t stealth_max_sp = Printer::tmc_driver_y->stealth_max_speed(); bool stealth_state = Printer::tmc_driver_y->stealthChop(); Printer::tmcPrepareHoming(Printer::tmc_driver_y, TMC2130_TCOOLTHRS_Y); #endif long steps; if ((MIN_HARDWARE_ENDSTOP_Y && Y_MIN_PIN > -1 && Y_HOME_DIR == -1) || (MAX_HARDWARE_ENDSTOP_Y && Y_MAX_PIN > -1 && Y_HOME_DIR == 1)) { coordinateOffset[Y_AXIS] = 0; long offY = 0; #if NUM_EXTRUDER > 1 for(uint8_t i = 0; i < NUM_EXTRUDER; i++) #if Y_HOME_DIR < 0 offY = RMath::max(offY, extruder[i].yOffset); #else offY = RMath::min(offY, extruder[i].yOffset); #endif // Reposition extruder that way, that all extruders can be selected at home pos. #endif UI_STATUS_UPD_F(Com::translatedF(UI_TEXT_HOME_Y_ID)); steps = (yMaxSteps - Printer::yMinSteps) * Y_HOME_DIR; currentPositionSteps[Y_AXIS] = -steps; setHoming(true); #if NONLINEAR_SYSTEM transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); #endif PrintLine::moveRelativeDistanceInSteps(0, 2 * steps, 0, 0, homingFeedrate[Y_AXIS], true, true); currentPositionSteps[Y_AXIS] = (Y_HOME_DIR == -1) ? yMinSteps - offY : yMaxSteps + offY; #if NONLINEAR_SYSTEM transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); #endif PrintLine::moveRelativeDistanceInSteps(0, axisStepsPerMM[Y_AXIS] * -ENDSTOP_Y_BACK_MOVE * Y_HOME_DIR, 0, 0, homingFeedrate[Y_AXIS] / ENDSTOP_X_RETEST_REDUCTION_FACTOR, true, false); PrintLine::moveRelativeDistanceInSteps(0, axisStepsPerMM[Y_AXIS] * 2 * ENDSTOP_Y_BACK_MOVE * Y_HOME_DIR, 0, 0, homingFeedrate[Y_AXIS] / ENDSTOP_X_RETEST_REDUCTION_FACTOR, true, true); setHoming(false); #if defined(ENDSTOP_Y_BACK_ON_HOME) if(ENDSTOP_Y_BACK_ON_HOME > 0) PrintLine::moveRelativeDistanceInSteps(0, axisStepsPerMM[Y_AXIS] * -ENDSTOP_Y_BACK_ON_HOME * Y_HOME_DIR, 0, 0, homingFeedrate[Y_AXIS], true, false); #endif currentPositionSteps[Y_AXIS] = (Y_HOME_DIR == -1) ? yMinSteps - offY : yMaxSteps + offY; #if NONLINEAR_SYSTEM transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); #endif #if NUM_EXTRUDER > 1 #if Y_HOME_DIR < 0 PrintLine::moveRelativeDistanceInSteps(0, (Extruder::current->yOffset - offY) * Y_HOME_DIR, 0, 0, homingFeedrate[Y_AXIS], true, false); #else PrintLine::moveRelativeDistanceInSteps(0, -(Extruder::current->yOffset - offY) * Y_HOME_DIR, 0, 0, homingFeedrate[Y_AXIS], true, false); #endif #endif setYHomed(true); } #if defined(SENSORLESS_HOMING) && TMC2130_ON_Y while(!Printer::tmc_driver_y->stst()); // Wait for motor stand-still Printer::tmc_driver_y->coolstep_min_speed(coolstep_speed); Printer::tmc_driver_y->stealth_max_speed(stealth_max_sp); Printer::tmc_driver_y->stealthChop(stealth_state); #endif } #endif /** \brief homes z axis. Homing z axis is the most complicated homing part as it needs to correct for several parameters depending on rotation correction, distortion correction, position, homing direction, sensor type and bed coating. Because we get lots of support questions from "wrong" behavior due to misunderstandings of all these dependencies, I will try to describe the function as detailed as possible. ## Step 1: Test if homing is possible at all Test if homing in Z_HOME_DIR has a matching hardware endstop. If not, no z homing is possible at all. ## Step 2: Activate z-probe if required If homing to z min using a z-probe, activate the probe. Requires a position where this is possible, since probe offset could prevent the move. Hence in this case x and y must be homed first and a z homing position given and reached before calling this function. ## Step 3: Fast homing to sensor A move of 2 * z_length is send to printer. The move will stop when the endstop triggers. ## Step 4: Untrigger sensor Move in opposite direction ENDSTOP_Z_BACK_MOVE mm to disable the endstop signal safely. ## Step 5: Retest endstop slowly For best precision we rerun step 3 with 1/ENDSTOP_Z_RETEST_REDUCTION_FACTOR factor for speed. This should give a very accurate trigge rposition. ## Step 6: Deactivate z-probe if it was activated in step 2 ## Step 7: Correct Z position zCorrection sums up several influences: - -axisStepsPerMM[Z_AXIS] * EEPROM::zProbeHeight() to compensate for z-prove trigger offset if probe was used. - -axisStepsPerMM[Z_AXIS] * ENDSTOP_Z_BACK_ON_HOME * Z_HOME_DIR to add wanted extra distance ENDSTOP_Z_BACK_ON_HOME. - axisStepsPerMM[Z_AXIS] * zBedOffset to correct for bed coating if correction mode Z_PROBE_Z_OFFSET_MODE == 0 and z min homing. and moves the z axis up that distance. ## Step 8: Set position in CMC For z min homing set currentPositionSteps[Z_AXIS] to zMinSteps. For z max homing set it to zMaxSteps - bed coating. Set z offset according to selected tool z offset, if extruder is not sensor. If distortion correction is enabled, set zCorrectionStepsIncluded and add value to currentPositionSteps. #step 9: Compute RWC and correct rotation influence Compute real position from position in steps. If rotation is on we did measure with a z-probe, this result is wrong and we need to correct by the z change between origin and current position. currentPositionSteps[Z_AXIS] -= (axisStepsPerMM[Z_AXIS] * currentPosition[Z_AXIS] - zMinSteps); currentPosition[Z_AXIS] = zMin; ## Step 10: Update NMC for nonlinear systems ## Step 11: Set babysteps to 0 */ void Printer::homeZAxis() { // Cartesian homing #if defined(SENSORLESS_HOMING) && TMC2130_ON_Z while(!Printer::tmc_driver_z->stst()); // Wait for motor stand-still uint32_t coolstep_speed = Printer::tmc_driver_z->coolstep_min_speed(); uint32_t stealth_max_sp = Printer::tmc_driver_z->stealth_max_speed(); bool stealth_state = Printer::tmc_driver_z->stealthChop(); tmcPrepareHoming(Printer::tmc_driver_z, TMC2130_TCOOLTHRS_Z); #endif long steps; if ((MIN_HARDWARE_ENDSTOP_Z && Z_MIN_PIN > -1 && Z_HOME_DIR == -1) || (MAX_HARDWARE_ENDSTOP_Z && Z_MAX_PIN > -1 && Z_HOME_DIR == 1)) { offsetZ2 = 0; #if Z_HOME_DIR < 0 && Z_PROBE_PIN == Z_MIN_PIN && FEATURE_Z_PROBE Printer::startProbing(true); #endif coordinateOffset[Z_AXIS] = 0; // G92 Z offset UI_STATUS_UPD_F(Com::translatedF(UI_TEXT_HOME_Z_ID)); steps = (zMaxSteps - zMinSteps) * Z_HOME_DIR; currentPositionSteps[Z_AXIS] = -steps; setHoming(true); #if defined(Z_PROBE_DELAY) && Z_PROBE_DELAY > 0 && Z_MIN_PIN == Z_PROBE_PIN && Z_HOME_DIR == -1 HAL::delayMilliseconds(Z_PROBE_DELAY); #endif #if NONLINEAR_SYSTEM transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); #endif PrintLine::moveRelativeDistanceInSteps(0, 0, 2 * steps, 0, homingFeedrate[Z_AXIS], true, true); currentPositionSteps[Z_AXIS] = (Z_HOME_DIR == -1) ? zMinSteps : zMaxSteps; #if NONLINEAR_SYSTEM transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); #endif PrintLine::moveRelativeDistanceInSteps(0, 0, axisStepsPerMM[Z_AXIS] * -ENDSTOP_Z_BACK_MOVE * Z_HOME_DIR, 0, homingFeedrate[Z_AXIS] / ENDSTOP_Z_RETEST_REDUCTION_FACTOR, true, false); #if defined(ZHOME_WAIT_UNSWING) && ZHOME_WAIT_UNSWING > 0 HAL::delayMilliseconds(ZHOME_WAIT_UNSWING); #endif #if defined(Z_PROBE_DELAY) && Z_PROBE_DELAY > 0 && Z_MIN_PIN == Z_PROBE_PIN && Z_HOME_DIR == -1 HAL::delayMilliseconds(Z_PROBE_DELAY); #endif #if Z_HOME_DIR < 0 && Z_PROBE_PIN == Z_MIN_PIN && FEATURE_Z_PROBE #ifdef Z_PROBE_RUN_AFTER_EVERY_PROBE GCode::executeFString(PSTR(Z_PROBE_RUN_AFTER_EVERY_PROBE)); #endif #endif PrintLine::moveRelativeDistanceInSteps(0, 0, axisStepsPerMM[Z_AXIS] * 2 * ENDSTOP_Z_BACK_MOVE * Z_HOME_DIR, 0, homingFeedrate[Z_AXIS] / ENDSTOP_Z_RETEST_REDUCTION_FACTOR, true, true); #if Z_HOME_DIR < 0 && Z_PROBE_PIN == Z_MIN_PIN && FEATURE_Z_PROBE Printer::finishProbing(); #endif setHoming(false); int32_t zCorrection = 0; #if Z_HOME_DIR < 0 && MIN_HARDWARE_ENDSTOP_Z && FEATURE_Z_PROBE && Z_PROBE_PIN == Z_MIN_PIN // Fix error from z probe testing zCorrection -= axisStepsPerMM[Z_AXIS] * EEPROM::zProbeHeight(); // Correct from bed rotation //updateCurrentPosition(true); //float xt,yt,zt; //transformToPrinter(currentPosition[X_AXIS],currentPosition[Y_AXIS],0,xt,yt,zt); //zCorrection -= zt; #endif #if defined(ENDSTOP_Z_BACK_ON_HOME) // If we want to go up a bit more for some reason if(ENDSTOP_Z_BACK_ON_HOME > 0) zCorrection -= axisStepsPerMM[Z_AXIS] * ENDSTOP_Z_BACK_ON_HOME * Z_HOME_DIR; #endif #if Z_HOME_DIR < 0 // Fix bed coating #if Z_PROBE_Z_OFFSET_MODE == 0 // Only if measure through coating e.g. inductive zCorrection += axisStepsPerMM[Z_AXIS] * zBedOffset; #endif #endif //Com::printFLN(PSTR("Z-Correction-Steps:"),zCorrection); // TEST PrintLine::moveRelativeDistanceInSteps(0, 0, zCorrection, 0, homingFeedrate[Z_AXIS], true, false); currentPositionSteps[Z_AXIS] = ((Z_HOME_DIR == -1) ? zMinSteps : zMaxSteps - zBedOffset * axisStepsPerMM[Z_AXIS]); #if NUM_EXTRUDER > 0 #if (EXTRUDER_IS_Z_PROBE == 0 || Z_HOME_DIR > 0) // currentPositionSteps[Z_AXIS] -= Extruder::current->zOffset; Printer::offsetZ = -Extruder::current->zOffset * Printer::invAxisStepsPerMM[Z_AXIS]; #endif #endif #if DISTORTION_CORRECTION && Z_HOME_DIR < 0 && Z_PROBE_PIN == Z_MIN_PIN && FEATURE_Z_PROBE // Special case where z probe is z min end stop and distortion correction is enabled if(Printer::distortion.isEnabled()) { Printer::zCorrectionStepsIncluded = Printer::distortion.correct(Printer::currentPositionSteps[X_AXIS], currentPositionSteps[Y_AXIS], currentPositionSteps[Z_AXIS]); currentPositionSteps[Z_AXIS] += Printer::zCorrectionStepsIncluded; } #endif updateCurrentPosition(true); #if Z_HOME_DIR < 0 && Z_PROBE_PIN == Z_MIN_PIN && FEATURE_Z_PROBE // If we have software leveling enabled and are not at 0,0 z position is not zero, but we measured // for z = 0, so we need to correct for rotation. currentPositionSteps[Z_AXIS] -= (axisStepsPerMM[Z_AXIS] * currentPosition[Z_AXIS] - zMinSteps); currentPosition[Z_AXIS] = zMin; #endif #if NONLINEAR_SYSTEM transformCartesianStepsToDeltaSteps(currentPositionSteps, currentNonlinearPositionSteps); #endif setZHomed(true); #if FEATURE_BABYSTEPPING Printer::zBabysteps = 0; #endif } #if defined(SENSORLESS_HOMING) && TMC2130_ON_Z while(!Printer::tmc_driver_z->stst()); // Wait for motor stand-still Printer::tmc_driver_z->coolstep_min_speed(coolstep_speed); Printer::tmc_driver_z->stealth_max_speed(stealth_max_sp); Printer::tmc_driver_z->stealthChop(stealth_state); #endif } /** \brief Main function for all homing operations. For homing operations only this function should be used. It calls Printer::homeXAxis, Printer::homeYAxis and Printer::homeZAxis after doing some initialization work. The order of operation and some extra functions are controlled by HOMING_ORDER. \param xaxis True if homing of x axis is wanted. \param yaxis True if homing of y axis is wanted. \param zaxis True if homing of z axis is wanted. */ void Printer::homeAxis(bool xaxis, bool yaxis, bool zaxis) { // home non-delta printer bool nocheck = isNoDestinationCheck(); setNoDestinationCheck(true); #if defined(SUPPORT_LASER) && SUPPORT_LASER bool oldLaser = LaserDriver::laserOn; LaserDriver::laserOn = false; #endif float startX, startY, startZ; realPosition(startX, startY, startZ); #if !defined(HOMING_ORDER) #define HOMING_ORDER HOME_ORDER_XYZ #endif #if Z_HOME_DIR < 0 #if ZHOME_PRE_RAISE == 1 if(zaxis && Endstops::zProbe()) PrintLine::moveRelativeDistanceInSteps(0, 0, ZHOME_PRE_RAISE_DISTANCE * axisStepsPerMM[Z_AXIS], 0, homingFeedrate[Z_AXIS], true, true); #elif ZHOME_PRE_RAISE == 2 if(zaxis) PrintLine::moveRelativeDistanceInSteps(0, 0, ZHOME_PRE_RAISE_DISTANCE * axisStepsPerMM[Z_AXIS], 0, homingFeedrate[Z_AXIS], true, true); #endif #endif #if Z_HOME_DIR < 0 && Z_PROBE_PIN == Z_MIN_PIN && FEATURE_Z_PROBE #if HOMING_ORDER != HOME_ORDER_XYZ && HOMING_ORDER != HOME_ORDER_YXZ && HOMING_ORDER != HOME_ORDER_ZXYTZ && HOMING_ORDER != HOME_ORDER_XYTZ #error Illegal homing order for z probe based homing! #endif if(zaxis) { // we need to know xy position for z probe to work properly if(!xaxis && !isXHomed()) xaxis = true; if(!yaxis && !isYHomed()) yaxis = true; } #endif if(zaxis) { EVENT_BEFORE_Z_HOME; } #if HOMING_ORDER == HOME_ORDER_XYZ if(xaxis) homeXAxis(); if(yaxis) homeYAxis(); if(zaxis) homeZAxis(); #elif HOMING_ORDER == HOME_ORDER_XZY if(xaxis) homeXAxis(); if(zaxis) homeZAxis(); if(yaxis) homeYAxis(); #elif HOMING_ORDER == HOME_ORDER_YXZ if(yaxis) homeYAxis(); if(xaxis) homeXAxis(); if(zaxis) homeZAxis(); #elif HOMING_ORDER == HOME_ORDER_YZX if(yaxis) homeYAxis(); if(zaxis) homeZAxis(); if(xaxis) homeXAxis(); #elif HOMING_ORDER == HOME_ORDER_ZXY if(zaxis) homeZAxis(); if(xaxis) homeXAxis(); if(yaxis) homeYAxis(); #elif HOMING_ORDER == HOME_ORDER_ZYX if(zaxis) homeZAxis(); if(yaxis) homeYAxis(); if(xaxis) homeXAxis(); #elif HOMING_ORDER == HOME_ORDER_ZXYTZ || HOMING_ORDER == HOME_ORDER_XYTZ { #if ZHOME_MIN_TEMPERATURE > 20 float actTemp[NUM_EXTRUDER]; for(int i = 0; i < NUM_EXTRUDER; i++) actTemp[i] = extruder[i].tempControl.targetTemperatureC; #endif if(zaxis) { #if HOMING_ORDER == HOME_ORDER_ZXYTZ homeZAxis(); Printer::moveToReal(IGNORE_COORDINATE, IGNORE_COORDINATE, ZHOME_HEAT_HEIGHT, IGNORE_COORDINATE, homingFeedrate[Z_AXIS]); #endif Commands::waitUntilEndOfAllMoves(); #if ZHOME_MIN_TEMPERATURE > 20 #if ZHOME_HEAT_ALL for(int i = 0; i < NUM_EXTRUDER; i++) { Extruder::setTemperatureForExtruder(RMath::max(actTemp[i], static_cast(ZHOME_MIN_TEMPERATURE)), i, false, false); } for(int i = 0; i < NUM_EXTRUDER; i++) { if(extruder[i].tempControl.currentTemperatureC < ZHOME_MIN_TEMPERATURE) Extruder::setTemperatureForExtruder(RMath::max(actTemp[i], static_cast(ZHOME_MIN_TEMPERATURE)), i, false, true); } #else if(extruder[Extruder::current->id].tempControl.currentTemperatureC < ZHOME_MIN_TEMPERATURE) Extruder::setTemperatureForExtruder(RMath::max(actTemp[Extruder::current->id], static_cast(ZHOME_MIN_TEMPERATURE)), Extruder::current->id, false, true); #endif #endif } #if ZHOME_X_POS == IGNORE_COORDINATE if(xaxis) #else if(xaxis || zaxis) #endif { homeXAxis(); //#if ZHOME_X_POS == IGNORE_COORDINATE if(X_HOME_DIR < 0) startX = Printer::xMin; else startX = Printer::xMin + Printer::xLength; //#else // startX = ZHOME_X_POS; //#endif } #if ZHOME_Y_POS == IGNORE_COORDINATE if(yaxis) #else if(yaxis || zaxis) #endif { homeYAxis(); //#if ZHOME_Y_POS == IGNORE_COORDINATE if(Y_HOME_DIR < 0) startY = Printer::yMin; else startY = Printer::yMin + Printer::yLength; //#else // startY = ZHOME_Y_POS; //#endif } if(zaxis) { #if ZHOME_X_POS != IGNORE_COORDINATE || ZHOME_Y_POS != IGNORE_COORDINATE moveToReal(ZHOME_X_POS, ZHOME_Y_POS, IGNORE_COORDINATE, IGNORE_COORDINATE, homingFeedrate[X_AXIS]); // correct rotation! Commands::waitUntilEndOfAllMoves(); #endif homeZAxis(); // real z distance at that point to zero if(Z_HOME_DIR < 0) startZ = Printer::zMin; else startZ = Printer::zMin + Printer::zLength - zBedOffset; moveToReal(IGNORE_COORDINATE, IGNORE_COORDINATE, ZHOME_HEAT_HEIGHT, IGNORE_COORDINATE, homingFeedrate[Z_AXIS]); // correct rotation! Commands::waitUntilEndOfAllMoves(); #if ZHOME_MIN_TEMPERATURE > 20 #if ZHOME_HEAT_ALL for(int i = 0; i < NUM_EXTRUDER; i++) Extruder::setTemperatureForExtruder(actTemp[i], i, false, false); for(int i = 0; i < NUM_EXTRUDER; i++) Extruder::setTemperatureForExtruder(actTemp[i], i, false, actTemp[i] > MAX_ROOM_TEMPERATURE); #else Extruder::setTemperatureForExtruder(actTemp[Extruder::current->id], Extruder::current->id, false, actTemp[Extruder::current->id] > MAX_ROOM_TEMPERATURE); #endif #endif } } #endif // elif HOMING_ORDER == HOME_ORDER_ZXYTZ || HOMING_ORDER == HOME_ORDER_XYTZ #if HOMING_ORDER != HOME_ORDER_ZXYTZ && HOMING_ORDER != HOME_ORDER_XYTZ if(xaxis) { #if DUAL_X_AXIS startX = currentPosition[X_AXIS]; #else if(X_HOME_DIR < 0) startX = Printer::xMin; else startX = Printer::xMin + Printer::xLength; #endif // else DUAL_X_AXIS } if(yaxis) { if(Y_HOME_DIR < 0) startY = Printer::yMin; else startY = Printer::yMin + Printer::yLength; } if(zaxis) { if(Z_HOME_DIR < 0) startZ = Printer::zMin; else startZ = Printer::zMin + Printer::zLength - Printer::zBedOffset; } #endif // HOMING_ORDER != HOME_ORDER_ZXYTZ updateCurrentPosition(true); #if defined(Z_UP_AFTER_HOME) && Z_HOME_DIR < 0 #ifdef HOME_ZUP_FIRST PrintLine::moveRelativeDistanceInSteps(0, 0, axisStepsPerMM[Z_AXIS]*Z_UP_AFTER_HOME * Z_HOME_DIR, 0, homingFeedrate[Z_AXIS], true, false); #endif if(zaxis) startZ = Z_UP_AFTER_HOME; #endif moveToReal(startX, startY, startZ, IGNORE_COORDINATE, homingFeedrate[X_AXIS]); #if (DUAL_X_AXIS && LAZY_DUAL_X_AXIS) moveToReal(startX, startY, startZ, IGNORE_COORDINATE, homingFeedrate[X_AXIS]); if(!sledParked && xaxis) { // park sled homeXAxis(); } #endif updateCurrentPosition(true); #if DUAL_X_AXIS && LAZY_DUAL_X_AXIS == 1 lastCmdPos[X_AXIS] = xMin; #endif updateHomedAll(); UI_CLEAR_STATUS Commands::printCurrentPosition(); #if defined(SUPPORT_LASER) && SUPPORT_LASER LaserDriver::laserOn = oldLaser; #endif setNoDestinationCheck(nocheck); Printer::updateCurrentPosition(); } #endif // Not delta printer /** \brief Execute a open baby step. If zBabystepsMissing is not 0 this will do a z step in the desired direction. The old movement directions get restored after execution. */ void Printer::zBabystep() { #if FEATURE_BABYSTEPPING bool dir = zBabystepsMissing > 0; if(dir) zBabystepsMissing--; else zBabystepsMissing++; #if DRIVE_SYSTEM == DELTA Printer::enableXStepper(); Printer::enableYStepper(); #endif Printer::enableZStepper(); Printer::unsetAllSteppersDisabled(); #if DRIVE_SYSTEM == DELTA bool xDir = Printer::getXDirection(); bool yDir = Printer::getYDirection(); #endif bool zDir = Printer::getZDirection(); #if DRIVE_SYSTEM == DELTA Printer::setXDirection(dir); Printer::setYDirection(dir); #endif Printer::setZDirection(dir); #if defined(DIRECTION_DELAY) && DIRECTION_DELAY > 0 HAL::delayMicroseconds(DIRECTION_DELAY); #else HAL::delayMicroseconds(10); #endif #if DRIVE_SYSTEM == DELTA startXStep(); startYStep(); #endif // Drive system 3 startZStep(); HAL::delayMicroseconds(STEPPER_HIGH_DELAY + 2); Printer::endXYZSteps(); HAL::delayMicroseconds(10); #if DRIVE_SYSTEM == 3 Printer::setXDirection(xDir); Printer::setYDirection(yDir); #endif Printer::setZDirection(zDir); #if defined(DIRECTION_DELAY) && DIRECTION_DELAY > 0 HAL::delayMicroseconds(DIRECTION_DELAY); #endif //HAL::delayMicroseconds(STEPPER_HIGH_DELAY + 1); #endif } void Printer::setCaseLight(bool on) { #if CASE_LIGHTS_PIN > -1 WRITE(CASE_LIGHTS_PIN, on); reportCaseLightStatus(); #endif } void Printer::reportCaseLightStatus() { #if CASE_LIGHTS_PIN > -1 if(READ(CASE_LIGHTS_PIN)) Com::printInfoFLN(PSTR("Case lights on")); else Com::printInfoFLN(PSTR("Case lights off")); #else Com::printInfoFLN(PSTR("No case lights")); #endif } void Printer::handleInterruptEvent() { if(interruptEvent == 0) return; int event = interruptEvent; interruptEvent = 0; switch(event) { #if EXTRUDER_JAM_CONTROL case PRINTER_INTERRUPT_EVENT_JAM_DETECTED: if(isJamcontrolDisabled()) break; EVENT_JAM_DETECTED; Com::printFLN(PSTR("important:Extruder jam detected")); UI_ERROR_P(Com::translatedF(UI_TEXT_EXTRUDER_JAM_ID)); #if JAM_ACTION == 1 // start dialog Printer::setUIErrorMessage(false); #if UI_DISPLAY_TYPE != NO_DISPLAY uid.executeAction(UI_ACTION_WIZARD_JAM_EOF, true); #endif #elif JAM_ACTION == 2 // pause host/print #if SDSUPPORT if(sd.sdmode == 2) { sd.pausePrint(true); break; } #endif // SDSUPPORT GCodeSource::printAllFLN(PSTR("RequestPause:Extruder Jam Detected!")); #endif // JAM_ACTION EVENT_JAM_DETECTED_END; break; case PRINTER_INTERRUPT_EVENT_JAM_SIGNAL0: case PRINTER_INTERRUPT_EVENT_JAM_SIGNAL1: case PRINTER_INTERRUPT_EVENT_JAM_SIGNAL2: case PRINTER_INTERRUPT_EVENT_JAM_SIGNAL3: case PRINTER_INTERRUPT_EVENT_JAM_SIGNAL4: case PRINTER_INTERRUPT_EVENT_JAM_SIGNAL5: { if(isJamcontrolDisabled()) break; fast8_t extruderIndex = event - PRINTER_INTERRUPT_EVENT_JAM_SIGNAL0; Extruder &ext = extruder[extruderIndex]; int32_t steps = abs(extruder[extruderIndex].jamStepsOnSignal); EVENT_JAM_SIGNAL_CHANGED(extruderIndex, steps); if(steps > ext.jamSlowdownSteps && !ext.tempControl.isSlowedDown()) { extruder[extruderIndex].tempControl.setSlowedDown(true); Commands::changeFeedrateMultiply(ext.jamSlowdownTo); //UI_ERROR_P(Com::tFilamentSlipping); UI_MESSAGE(4); } if(isDebugJam()) { Com::printF(PSTR("Jam signal steps:"), steps); int32_t percent = static_cast(steps) * 100 / JAM_STEPS; Com::printF(PSTR(" / "), percent); Com::printFLN(PSTR("% on "), (int)extruderIndex); } } break; #endif // EXTRUDER_JAM_CONTROL case PRINTER_INTERRUPT_EVENT_JAM_DETECTED: } } #define START_EXTRUDER_CONFIG(i) Com::printF(Com::tConfig);Com::printF(Com::tExtrDot,i+1);Com::print(':'); void Printer::showConfiguration() { Com::config(PSTR("Baudrate:"), baudrate); #ifndef EXTERNALSERIAL Com::config(PSTR("InputBuffer:"), SERIAL_BUFFER_SIZE - 1); #endif Com::config(PSTR("NumExtruder:"), NUM_EXTRUDER); Com::config(PSTR("MixingExtruder:"), MIXING_EXTRUDER); Com::config(PSTR("HeatedBed:"), HAVE_HEATED_BED); Com::config(PSTR("SDCard:"), SDSUPPORT); Com::config(PSTR("Fan:"), FAN_PIN > -1 && FEATURE_FAN_CONTROL); #if FEATURE_FAN2_CONTROL && defined(FAN2_PIN) && FAN2_PIN > -1 Com::config(PSTR("Fan2:1")); #else Com::config(PSTR("Fan2:0")); #endif Com::config(PSTR("LCD:"), FEATURE_CONTROLLER != NO_CONTROLLER); Com::config(PSTR("SoftwarePowerSwitch:"), PS_ON_PIN > -1); Com::config(PSTR("XHomeDir:"), X_HOME_DIR); Com::config(PSTR("YHomeDir:"), Y_HOME_DIR); Com::config(PSTR("ZHomeDir:"), Z_HOME_DIR); #if DRIVE_SYSTEM == DELTA Com::config(PSTR("XHomePos:"), 0, 2); Com::config(PSTR("YHomePos:"), 0, 2); Com::config(PSTR("ZHomePos:"), zMin + zLength, 3); #else Com::config(PSTR("XHomePos:"), xMin + (X_HOME_DIR > 0 ? xLength : 0), 2); Com::config(PSTR("YHomePos:"), yMin + (Y_HOME_DIR > 0 ? yLength : 0), 2); Com::config(PSTR("ZHomePos:"), zMin + (Z_HOME_DIR > 0 ? zLength : 0), 3); #endif Com::config(PSTR("SupportG10G11:"), FEATURE_RETRACTION); Com::config(PSTR("SupportLocalFilamentchange:"), FEATURE_RETRACTION); Com::config(PSTR("CaseLights:"), CASE_LIGHTS_PIN > -1); Com::config(PSTR("ZProbe:"), FEATURE_Z_PROBE); Com::config(PSTR("Autolevel:"), FEATURE_AUTOLEVEL); Com::config(PSTR("EEPROM:"), EEPROM_MODE != 0); Com::config(PSTR("PrintlineCache:"), PRINTLINE_CACHE_SIZE); Com::config(PSTR("JerkXY:"), maxJerk); Com::config(PSTR("KeepAliveInterval:"), KEEP_ALIVE_INTERVAL); #if DRIVE_SYSTEM != DELTA Com::config(PSTR("JerkZ:"), maxZJerk); #endif #if FEATURE_RETRACTION Com::config(PSTR("RetractionLength:"), EEPROM_FLOAT(RETRACTION_LENGTH)); Com::config(PSTR("RetractionLongLength:"), EEPROM_FLOAT(RETRACTION_LONG_LENGTH)); Com::config(PSTR("RetractionSpeed:"), EEPROM_FLOAT(RETRACTION_SPEED)); Com::config(PSTR("RetractionZLift:"), EEPROM_FLOAT(RETRACTION_Z_LIFT)); Com::config(PSTR("RetractionUndoExtraLength:"), EEPROM_FLOAT(RETRACTION_UNDO_EXTRA_LENGTH)); Com::config(PSTR("RetractionUndoExtraLongLength:"), EEPROM_FLOAT(RETRACTION_UNDO_EXTRA_LONG_LENGTH)); Com::config(PSTR("RetractionUndoSpeed:"), EEPROM_FLOAT(RETRACTION_UNDO_SPEED)); #endif // FEATURE_RETRACTION Com::config(PSTR("XMin:"), xMin); Com::config(PSTR("YMin:"), yMin); Com::config(PSTR("ZMin:"), zMin); Com::config(PSTR("XMax:"), xMin + xLength); Com::config(PSTR("YMax:"), yMin + yLength); Com::config(PSTR("ZMax:"), zMin + zLength); Com::config(PSTR("XSize:"), xLength); Com::config(PSTR("YSize:"), yLength); Com::config(PSTR("ZSize:"), zLength); Com::config(PSTR("XPrintAccel:"), maxAccelerationMMPerSquareSecond[X_AXIS]); Com::config(PSTR("YPrintAccel:"), maxAccelerationMMPerSquareSecond[Y_AXIS]); Com::config(PSTR("ZPrintAccel:"), maxAccelerationMMPerSquareSecond[Z_AXIS]); Com::config(PSTR("XTravelAccel:"), maxTravelAccelerationMMPerSquareSecond[X_AXIS]); Com::config(PSTR("YTravelAccel:"), maxTravelAccelerationMMPerSquareSecond[Y_AXIS]); Com::config(PSTR("ZTravelAccel:"), maxTravelAccelerationMMPerSquareSecond[Z_AXIS]); #if DRIVE_SYSTEM == DELTA Com::config(PSTR("PrinterType:Delta")); #else Com::config(PSTR("PrinterType:Cartesian")); #endif // DRIVE_SYSTEM Com::config(PSTR("MaxBedTemp:"), HEATED_BED_MAX_TEMP); for(fast8_t i = 0; i < NUM_EXTRUDER; i++) { START_EXTRUDER_CONFIG(i) Com::printFLN(PSTR("Jerk:"), extruder[i].maxStartFeedrate); START_EXTRUDER_CONFIG(i) Com::printFLN(PSTR("MaxSpeed:"), extruder[i].maxFeedrate); START_EXTRUDER_CONFIG(i) Com::printFLN(PSTR("Acceleration:"), extruder[i].maxAcceleration); START_EXTRUDER_CONFIG(i) Com::printFLN(PSTR("Diameter:"), extruder[i].diameter); START_EXTRUDER_CONFIG(i) Com::printFLN(PSTR("MaxTemp:"), MAXTEMP); } } #if JSON_OUTPUT void Printer::showJSONStatus(int type) { bool firstOccurrence; Com::printF(PSTR("{\"status\": \"")); if (PrintLine::linesCount == 0) { Com::print('I'); // IDLING #if SDSUPPORT } else if (sd.sdactive) { Com::print('P'); // SD PRINTING #endif } else { Com::print('B'); // SOMETHING ELSE, BUT SOMETHIG } // "heaters": [27.5, 30.3, 30.6], Com::printF(PSTR("\",\"heaters\":[")); #if HAVE_HEATED_BED Com::print(heatedBedController.currentTemperatureC); #else Com::print((int)0); #endif for (int i = 0; i < NUM_EXTRUDER; i++) { Com::print(','); Com::print(extruder[i].tempControl.currentTemperatureC); } // "active": [65.0, 195.0, 0.0], Com::printF(PSTR("],\"active\":[")); #if HAVE_HEATED_BED Com::print(heatedBedController.targetTemperatureC); #else Com::print((int)0); #endif for (int i = 0; i < NUM_EXTRUDER; i++) { Com::print(','); Com::print(extruder[i].tempControl.targetTemperatureC); } // "standby": [-273.1, 0.0, 150.0], Com::printF(PSTR("],\"standby\":[")); #if HAVE_HEATED_BED Com::print(heatedBedController.targetTemperatureC); #else Com::print((int)0); #endif for (int i = 0; i < NUM_EXTRUDER; i++) { Com::print(','); Com::print(extruder[i].tempControl.targetTemperatureC); } // "hstat": [0, 0, 0], // hstat is 0 for heater off, 1 for standby, 2 for active and 3 for fault. We have just added 4 for "being auto-tuned' Com::printF(PSTR("],\"hstat\":[")); #if HAVE_HEATED_BED if(heatedBedController.isSensorDefect() || heatedBedController.isSensorDecoupled()) Com::print((int)3); else Com::print((int)(heatedBedController.targetTemperatureC < 30 ? 0 : 2)); #else Com::print((int)0); #endif for (int i = 0; i < NUM_EXTRUDER; i++) { Com::print(','); if(extruder[i].tempControl.isSensorDefect() || extruder[i].tempControl.isSensorDecoupled()) Com::print((int)3); else Com::print((int)(extruder[i].tempControl.targetTemperatureC < 30 ? 0 : 2)); } // "pos": [1.00, 205.00, 6.48], Com::printF(PSTR("],\"pos\":[")); Com::print(currentPosition[X_AXIS]); // X Com::print(','); Com::print(currentPosition[Y_AXIS]); // Y Com::print(','); Com::print(currentPosition[Z_AXIS]); // Z // "extr": [0.0, 0.0], Com::printF(PSTR("],\"extr\":[")); for (int i = 0; i < NUM_EXTRUDER; i++) { if (i) Com::print(','); Com::printFloat(extruder[i].tempControl.currentTemperatureC,1); } // "sfactor": 100.00, Com::printF(PSTR("],\"sfactor\":"), Printer::feedrateMultiply); // "efactor": [100.00, 100.00], Com::printF(PSTR(",\"efactor\":[")); for (int i = 0; i < NUM_EXTRUDER; i++) { if (i) Com::print(','); Com::print((int)Printer::extrudeMultiply); } // "tool": 0, Com::printF(PSTR("],\"tool\":"), Extruder::current->id); //"probe": "4", Com::printF(PSTR(",\"probe\":")); if(Endstops::zProbe()) Com::print((int)0); else Com::print((int)1000); // "fanPercent": [0.00, 100.00], Com::printF(PSTR(",\"fanPercent\":[")); #if FEATURE_FAN_CONTROL Com::print(getFanSpeed() / 2.55f); #endif #if FEATURE_FAN2_CONTROL Com::printF(Com::tComma, getFan2Speed() / 2.55f); #endif Com::printF(PSTR("]")); // "fanRPM": 0, // "homed": [1, 1, 1], Com::printF(PSTR(",\"homed\":[")); Com::print((int)isXHomed()); Com::print(','); Com::print(isYHomed()); Com::print(','); Com::print(isZHomed()); Com::printF(PSTR("]")); if(type == 1) { // "geometry": "cartesian", #if DRIVE_SYSTEM == DELTA Com::printF(PSTR(",\"geometry\":\"Delta\"")); #else Com::printF(PSTR(",\"geometry\":\"Cartesian\"")); #endif // "myName": "Ormerod" Com::printF(PSTR(",\"myName\":\"" UI_PRINTER_NAME "\"")); Com::printF(PSTR(",\"firmwareName\":\"Repetier\"")); } Com::printF(PSTR(",\"coords\": {")); Com::printF(PSTR("\"axesHomed\":[")); Com::print((int)isXHomed()); Com::print(','); Com::print(isYHomed()); Com::print(','); Com::print(isZHomed()); Com::printF(PSTR("],\"extr\":[")); firstOccurrence = true; for (int i = 0; i < NUM_EXTRUDER; i++) { if (!firstOccurrence) Com::print(','); Com::print(extruder[i].extrudePosition / extruder[i].stepsPerMM); firstOccurrence = false; } Com::printF(PSTR("],\"xyz\":[")); Com::print(currentPosition[X_AXIS]); // X Com::print(','); Com::print(currentPosition[Y_AXIS]); // Y Com::print(','); Com::print(currentPosition[Z_AXIS]); // Z Com::printF(PSTR("]},\"currentTool\":")); Com::print(Extruder::current->id); Com::printF(PSTR(",\"params\": {\"atxPower\":")); Com::print(isPowerOn() ? '1' : '0'); Com::printF(PSTR(",\"fanPercent\":[")); #if FEATURE_FAN_CONTROL Com::print(getFanSpeed() / 2.55f); #endif #if FEATURE_FAN2_CONTROL Com::printF(Com::tComma, getFan2Speed() / 2.55f); #endif Com::printF(PSTR("],\"speedFactor\":")); Com::print(Printer::feedrateMultiply); Com::printF(PSTR(",\"extrFactors\":[")); firstOccurrence = true; for (int i = 0; i < NUM_EXTRUDER; i++) { if (!firstOccurrence) Com::print(','); Com::print((int)Printer::extrudeMultiply); // Really *100? 100 is normal firstOccurrence = false; } Com::printF(PSTR("]},")); // SEQ?? Com::printF(PSTR("\"temps\": {")); #if HAVE_HEATED_BED Com::printF(PSTR("\"bed\": {\"current\":")); Com::print(heatedBedController.currentTemperatureC); Com::printF(PSTR(",\"active\":")); Com::print(heatedBedController.targetTemperatureC); Com::printF(PSTR(",\"state\":")); Com::print(heatedBedController.targetTemperatureC > 0 ? '2' : '1'); Com::printF(PSTR("},")); #endif Com::printF(PSTR("\"heads\": {\"current\": [")); firstOccurrence = true; for (int i = 0; i < NUM_EXTRUDER; i++) { if (!firstOccurrence) Com::print(','); Com::print(extruder[i].tempControl.currentTemperatureC); firstOccurrence = false; } Com::printF(PSTR("],\"active\": [")); firstOccurrence = true; for (int i = 0; i < NUM_EXTRUDER; i++) { if (!firstOccurrence) Com::print(','); Com::print(extruder[i].tempControl.targetTemperatureC); firstOccurrence = false; } Com::printF(PSTR("],\"state\": [")); firstOccurrence = true; for (int i = 0; i < NUM_EXTRUDER; i++) { if (!firstOccurrence) Com::print(','); Com::print(extruder[i].tempControl.targetTemperatureC > EXTRUDER_FAN_COOL_TEMP ? '2' : '1'); firstOccurrence = false; } Com::printF(PSTR("]}},\"time\":")); Com::print(HAL::timeInMilliseconds()); switch (type) { default: case 0: case 1: break; case 2: // UNTIL PRINT ESTIMATE TIMES ARE IMPLEMENTED // NO DURATION INFO IS SUPPORTED Com::printF(PSTR(",\"coldExtrudeTemp\":0,\"coldRetractTemp\":0.0,\"geometry\":\"")); #if (DRIVE_SYSTEM == DELTA) Com::printF(PSTR("delta")); #elif (DRIVE_SYSTEM == CARTESIAN || DRIVE_SYSTEM == GANTRY_FAKE) Com::printF(PSTR("cartesian")); #elif ((DRIVE_SYSTEM == XY_GANTRY) || (DRIVE_SYSTEM == YX_GANTRY)) Com::printF(PSTR("coreXY")); #elif (DRIVE_SYSTEM == XZ_GANTRY) Com::printF(PSTR("coreXZ")); #endif Com::printF(PSTR("\",\"name\":\"")); Com::printF(PSTR(UI_PRINTER_NAME)); Com::printF(PSTR("\",\"tools\":[")); firstOccurrence = true; for (int i = 0; i < NUM_EXTRUDER; i++) { if (!firstOccurrence) Com::print(','); Com::printF(PSTR("{\"number\":")); Com::print(i); Com::printF(PSTR(",\"heaters\":[1],\"drives\":[1]")); Com::print('}'); firstOccurrence = false; } Com::printF(PSTR("]")); break; case 3: Com::printF(PSTR(",\"currentLayer\":")); #if SDSUPPORT if (sd.sdactive && sd.fileInfo.layerHeight > 0) { // ONLY CAN TELL WHEN SD IS PRINTING Com::print((int) (currentPosition[Z_AXIS] / sd.fileInfo.layerHeight)); } else Com::print('0'); #else Com::printF(PSTR("-1")); #endif Com::printF(PSTR(",\"extrRaw\":[")); firstOccurrence = true; for (int i = 0; i < NUM_EXTRUDER; i++) { if (!firstOccurrence) Com::print(','); Com::print(extruder[i].extrudePosition * Printer::extrudeMultiply); firstOccurrence = false; } Com::printF(PSTR("],")); #if SDSUPPORT if (sd.sdactive) { Com::printF(PSTR("\"fractionPrinted\":")); float fraction; if (sd.filesize < 2000000) fraction = sd.sdpos / sd.filesize; else fraction = (sd.sdpos >> 8) / (sd.filesize >> 8); Com::print((float) floor(fraction * 1000) / 1000); // ONE DECIMAL, COULD BE DONE BY SHIFTING, BUT MEH Com::print(','); } #endif Com::printF(PSTR("\"firstLayerHeight\":")); #if SDSUPPORT if (sd.sdactive) { Com::print(sd.fileInfo.layerHeight); } else Com::print('0'); #else Com::print('0'); #endif break; case 4: case 5: Com::printF(PSTR(",\"axisMins\":[")); Com::print((int) X_MIN_POS); Com::print(','); Com::print((int) Y_MIN_POS); Com::print(','); Com::print((int) Z_MIN_POS); Com::printF(PSTR("],\"axisMaxes\":[")); Com::print((int) X_MAX_LENGTH); Com::print(','); Com::print((int) Y_MAX_LENGTH); Com::print(','); Com::print((int) Z_MAX_LENGTH); Com::printF(PSTR("],\"accelerations\":[")); Com::print(maxAccelerationMMPerSquareSecond[X_AXIS]); Com::print(','); Com::print(maxAccelerationMMPerSquareSecond[Y_AXIS]); Com::print(','); Com::print(maxAccelerationMMPerSquareSecond[Z_AXIS]); for (int i = 0; i < NUM_EXTRUDER; i++) { Com::print(','); Com::print(extruder[i].maxAcceleration); } Com::printF(PSTR("],\"firmwareElectronics\":\"")); #ifdef RAMPS_V_1_3 Com::printF(PSTR("RAMPS")); #elif (CPU_ARCH == ARCH_ARM) Com::printF(PSTR("Arduino Due")); #else Com::printF(PSTR("AVR")); #endif Com::printF(PSTR("\",\"firmwareName\":\"Repetier\",\"firmwareVersion\":\"")); Com::printF(PSTR(REPETIER_VERSION)); Com::printF(PSTR("\",\"minFeedrates\":[0,0,0")); for (int i = 0; i < NUM_EXTRUDER; i++) { Com::printF(PSTR(",0")); } Com::printF(PSTR("],\"maxFeedrates\":[")); Com::print(maxFeedrate[X_AXIS]); Com::print(','); Com::print(maxFeedrate[Y_AXIS]); Com::print(','); Com::print(maxFeedrate[Z_AXIS]); for (int i = 0; i < NUM_EXTRUDER; i++) { Com::print(','); Com::print(extruder[i].maxFeedrate); } Com::printF(PSTR("]")); break; } Com::printFLN(PSTR("}")); } #endif // JSON_OUTPUT void Printer::pausePrint() { #if SDSUPPORT if(Printer::isMenuMode(MENU_MODE_SD_PRINTING)) { sd.pausePrint(true); } else #endif if(Printer::isMenuMode(MENU_MODE_PRINTING)) { GCodeSource::printAllFLN(PSTR("RequestPause:")); Printer::setMenuMode(MENU_MODE_PAUSED, true); #if !defined(DISABLE_PRINTMODE_ON_PAUSE) || DISABLE_PRINTMODE_ON_PAUSE==1 Printer::setPrinting(false); #endif } } void Printer::continuePrint() { #if SDSUPPORT if(Printer::isMenuMode(MENU_MODE_SD_PRINTING + MENU_MODE_PAUSED)) { sd.continuePrint(true); } else #endif if(Printer::isMenuMode(MENU_MODE_PAUSED)) { GCodeSource::printAllFLN(PSTR("RequestContinue:")); } setMenuMode(MENU_MODE_PAUSED, false); } void Printer::stopPrint() { flashSource.close(); // stop flash printing if busy #if SDSUPPORT if(Printer::isMenuMode(MENU_MODE_SD_PRINTING)) { sd.stopPrint(); } else #endif { GCodeSource::printAllFLN(PSTR("RequestStop:")); } if(!isUIErrorMessage()) { UI_RESET_MENU } } #if defined(DRV_TMC2130) void Printer::configTMC2130(TMC2130Stepper* tmc_driver, bool tmc_stealthchop, int8_t tmc_sgt, uint8_t tmc_pwm_ampl, uint8_t tmc_pwm_grad, bool tmc_pwm_autoscale, uint8_t tmc_pwm_freq) { while(!tmc_driver->stst()); // Wait for motor stand-still tmc_driver->begin(); // Initiate pins and registries // Using internal reference should be good enough and work on more drivers // tmc_driver->I_scale_analog(true); // Set current reference source tmc_driver->interpolate(true); // Set internal micro step interpolation tmc_driver->pwm_ampl(tmc_pwm_ampl); // Chopper PWM amplitude tmc_driver->pwm_grad(tmc_pwm_grad); // Velocity gradient for chopper PWM amplitude tmc_driver->pwm_autoscale(tmc_pwm_autoscale); // Chopper PWM autos scaling tmc_driver->pwm_freq(tmc_pwm_freq); // Chopper PWM frequency selection tmc_driver->stealthChop(tmc_stealthchop); // Enable extremely quiet stepping tmc_driver->sg_stall_value(tmc_sgt); // StallGuard sensitivity } #if defined(SENSORLESS_HOMING) void Printer::tmcPrepareHoming(TMC2130Stepper* tmc_driver, uint32_t coolstep_sp_min) { while(!tmc_driver->stst()); // Wait for motor stand-still tmc_driver->stealth_max_speed(0); // Upper speed limit for stealthChop tmc_driver->stealthChop(false); // Turn off stealthChop tmc_driver->coolstep_min_speed(coolstep_sp_min);// Minimum speed for StallGuard triggering tmc_driver->sg_filter(false); // Turn off StallGuard filtering tmc_driver->diag1_stall(true); // Signal StallGuard on DIAG1 pin #if MOTHERBOARD != 310 // Rambo Einsy has diag0 and diag1 bound together so this could cause a defect tmc_driver->diag1_active_high(true); // StallGuard pulses active high #endif } #endif #endif