diff --git a/Repetier/Commands.cpp b/Repetier/Commands.cpp index 68d67b765..330b1d5d9 100644 --- a/Repetier/Commands.cpp +++ b/Repetier/Commands.cpp @@ -18,7 +18,7 @@ #include "Repetier.h" -int Commands::lowestRAMValue = MAX_RAM; +int Commands::lowestRAMValue = MAX_RAM; int Commands::lowestRAMValueSend = MAX_RAM; void Commands::commandLoop() @@ -28,9 +28,9 @@ void Commands::commandLoop() GCode *code = GCode::peekCurrentCommand(); if (code) { #if SDSUPPORT - if(sd.savetosd) + if (sd.savetosd) { - if(!(code->hasM() && code->M == 29)) // still writing to file + if (!(code->hasM() && code->M == 29)) // still writing to file sd.writeCommand(code); else sd.finishWrite(); @@ -45,13 +45,14 @@ void Commands::commandLoop() } code->popCurrentCommand(); Commands::checkForPeriodicalActions(Processing); //check heater and other stuff every n milliseconds - } else { + } + else { enum FirmwareState state = NotBusy; - if( g_pauseMode ) + if (g_pauseMode) { state = Paused; } - + Commands::checkForPeriodicalActions(state); //check heater and other stuff every n milliseconds } } // commandLoop @@ -59,41 +60,41 @@ void Commands::commandLoop() void Commands::checkForPeriodicalActions(enum FirmwareState state) { - /* + /* * The execute variables are set by PWM-Timer. This timer ticks with about 3910 Hz and the ms clocks are made with software counter dividors. * Except this 16ms execute variable which is set by internal watchdog timer. */ if (state != NotBusy) { - GCode::keepAlive( state ); + GCode::keepAlive(state); } if (execute10msPeriodical) { - execute10msPeriodical = 0; - // Dieses freigabesignal sollte aus dem PWM-Timer kommen, denn dann ist klar, dass auch der noch läuft. - // Dann laufen für den Watchdogreset der Timer und checkForPeriodicalActions(). - HAL::tellWatchdogOk(); + execute10msPeriodical = 0; + // Dieses freigabesignal sollte aus dem PWM-Timer kommen, denn dann ist klar, dass auch der noch läuft. + // Dann laufen für den Watchdogreset der Timer und checkForPeriodicalActions(). + HAL::tellWatchdogOk(); } if (execute16msPeriodical) { - execute16msPeriodical = 0; - bool buttonSpeedBoost = (!execute100msPeriodical && HAL::timeInMilliseconds() - uid.lastButtonStart < 20000); - if(buttonSpeedBoost) UI_SLOW; - recalculateZCompensation(); + execute16msPeriodical = 0; + bool buttonSpeedBoost = (!execute100msPeriodical && HAL::timeInMilliseconds() - uid.lastButtonStart < 20000); + if (buttonSpeedBoost) UI_SLOW; + recalculateZCompensation(); } if (execute100msPeriodical) { - execute100msPeriodical = 0; - Extruder::manageTemperatures(); - if (state == WaitHeater) Commands::printTemperatures(); //selfcontrolling timediff + execute100msPeriodical = 0; + Extruder::manageTemperatures(); + if (state == WaitHeater) Commands::printTemperatures(); //selfcontrolling timediff #if defined(SDCARDDETECT) && SDCARDDETECT>-1 && defined(SDSUPPORT) && SDSUPPORT - sd.automount(); + sd.automount(); #endif // defined(SDCARDDETECT) && SDCARDDETECT>-1 && defined(SDSUPPORT) && SDSUPPORT - UI_SLOW; + UI_SLOW; } if (execute50msPeriodical) { - execute50msPeriodical = 0; - loopFeatures(); + execute50msPeriodical = 0; + loopFeatures(); } DEBUG_MEMORY; @@ -108,24 +109,24 @@ void Commands::waitUntilEndOfAllMoves() { bool bWait = false; - if( PrintLine::hasLines() ) bWait = true; + if (PrintLine::hasLines()) bWait = true; #if FEATURE_FIND_Z_ORIGIN - if( g_nFindZOriginStatus ) bWait = true; + if (g_nFindZOriginStatus) bWait = true; #endif // FEATURE_FIND_Z_ORIGIN #if FEATURE_HEAT_BED_Z_COMPENSATION bWait = (Printer::needsCMPwait() ? true : bWait); #endif // FEATURE_HEAT_BED_Z_COMPENSATION - while( bWait ) + while (bWait) { - Commands::checkForPeriodicalActions( Processing ); + Commands::checkForPeriodicalActions(Processing); bWait = false; - if( PrintLine::hasLines() ) bWait = true; + if (PrintLine::hasLines()) bWait = true; #if FEATURE_FIND_Z_ORIGIN - if( g_nFindZOriginStatus ) bWait = true; + if (g_nFindZOriginStatus) bWait = true; #endif // FEATURE_FIND_Z_ORIGIN #if FEATURE_HEAT_BED_Z_COMPENSATION @@ -137,21 +138,21 @@ void Commands::waitUntilEndOfAllMoves() void Commands::printCurrentPosition() { - // Wir zeigen dem Repetier-Host wo wir gerade stehen. - // Hier ist die reine GCode-Position interessant, sonst würde das Einrechnen des GCode-Origin auch keinen Sinn machen. - float x = Printer::currentSteps[X_AXIS] * Printer::axisMMPerSteps[X_AXIS]; - float y = Printer::currentSteps[Y_AXIS] * Printer::axisMMPerSteps[Y_AXIS]; - // Z bleibt ein Sonderfall. Normalerweise auch hier GCode-Position - float z = Printer::currentZPositionMM(); + // Wir zeigen dem Repetier-Host wo wir gerade stehen. + // Hier ist die reine GCode-Position interessant, sonst würde das Einrechnen des GCode-Origin auch keinen Sinn machen. + float x = Printer::currentSteps[X_AXIS] * Printer::axisMMPerSteps[X_AXIS]; + float y = Printer::currentSteps[Y_AXIS] * Printer::axisMMPerSteps[Y_AXIS]; + // Z bleibt ein Sonderfall. Normalerweise auch hier GCode-Position + float z = Printer::currentZPositionMM(); x += Printer::originOffsetMM[X_AXIS]; y += Printer::originOffsetMM[Y_AXIS]; z += Printer::originOffsetMM[Z_AXIS]; - Com::printF(Com::tXColon,x*(Printer::unitIsInches?0.03937:1),2); - Com::printF(Com::tSpaceYColon,y*(Printer::unitIsInches?0.03937:1),2); - Com::printF(Com::tSpaceZColon,z*(Printer::unitIsInches?0.03937:1),2); - Com::printFLN(Com::tSpaceEColon, Printer::destinationMM[E_AXIS] * (Printer::unitIsInches ? 0.03937 : 1),2); + Com::printF(Com::tXColon, x*(Printer::unitIsInches ? 0.03937 : 1), 2); + Com::printF(Com::tSpaceYColon, y*(Printer::unitIsInches ? 0.03937 : 1), 2); + Com::printF(Com::tSpaceZColon, z*(Printer::unitIsInches ? 0.03937 : 1), 2); + Com::printFLN(Com::tSpaceEColon, Printer::destinationMM[E_AXIS] * (Printer::unitIsInches ? 0.03937 : 1), 2); } // printCurrentPosition @@ -159,40 +160,40 @@ void Commands::printTemperatures(bool showRaw) { static millis_t lastTemperatureSignal = 0; millis_t now = HAL::timeInMilliseconds(); - if( (now - lastTemperatureSignal) > 1000 ){ + if ((now - lastTemperatureSignal) > 1000) { lastTemperatureSignal = now; - Com::printF(Com::tTColon,Extruder::current->tempControl.currentTemperatureC,1); - Com::printF(Com::tSpaceSlash,Extruder::current->tempControl.targetTemperatureC,0); + Com::printF(Com::tTColon, Extruder::current->tempControl.currentTemperatureC, 1); + Com::printF(Com::tSpaceSlash, Extruder::current->tempControl.targetTemperatureC, 0); // Show output of autotune when tuning! - Com::printF(Com::tSpaceAtColon,(pwm_pos[Extruder::current->id])); + Com::printF(Com::tSpaceAtColon, (pwm_pos[Extruder::current->id])); #if HAVE_HEATED_BED - Com::printF(Com::tSpaceBColon,Extruder::getHeatedBedTemperature(),1); - Com::printF(Com::tSpaceSlash,heatedBedController.targetTemperatureC,0); + Com::printF(Com::tSpaceBColon, Extruder::getHeatedBedTemperature(), 1); + Com::printF(Com::tSpaceSlash, heatedBedController.targetTemperatureC, 0); - if(showRaw) + if (showRaw) { - Com::printF(Com::tSpaceRaw,(int)NUM_EXTRUDER); - Com::printF(Com::tColon,(1023<<(2-ANALOG_REDUCE_BITS))-heatedBedController.currentTemperature); + Com::printF(Com::tSpaceRaw, (int)NUM_EXTRUDER); + Com::printF(Com::tColon, (1023 << (2 - ANALOG_REDUCE_BITS)) - heatedBedController.currentTemperature); } - Com::printF(Com::tSpaceBAtColon,(pwm_pos[heatedBedController.pwmIndex])); // Show output of autotune when tuning! + Com::printF(Com::tSpaceBAtColon, (pwm_pos[heatedBedController.pwmIndex])); // Show output of autotune when tuning! #endif // HAVE_HEATED_BED #if NUM_EXTRUDER>1 - for(uint8_t i=0; i 0) ); - Com::printFLN(Com::tFanspeed, (fanSpeed == 1) ? 2 : fanSpeed ); //bei 1 zeigt repetierserver / repetierhost 0% an, was nicht stimmt. Das ist etwas Pfusch, aber nun funktionierts. + Printer::setMenuMode(MENU_MODE_FAN_RUNNING, (fanSpeed > 0)); + Com::printFLN(Com::tFanspeed, (fanSpeed == 1) ? 2 : fanSpeed); //bei 1 zeigt repetierserver / repetierhost 0% an, was nicht stimmt. Das ist etwas Pfusch, aber nun funktionierts. //wenn speed > 0 und < 255, dann wird der wertebereich eingegrenzt, sonst === 0 oder full power - if( speed > 0 && speed < 255 ) + if (speed > 0 && speed < 255) { //scale the input speed value within MIN and MAX long temp = speed; temp *= (part_fan_pwm_max - part_fan_pwm_min); temp /= 255; temp += part_fan_pwm_min; - speed = constrain(temp,0,255); + speed = constrain(temp, 0, 255); /* from here "speed" is scaled to a set boundary. It will be the same scale like pwm_pos[NUM_EXTRUDER+2] has. Commanded (and user ui) speed is "fanSpeed", which stays unscaled. @@ -275,22 +276,22 @@ void Commands::setFanSpeed(uint8_t speed, bool recalc) //if specified calculate a kickstart time when the fan speed is commanded to rise //use fanSpeed (not "speed") to compare with PART_FAN_KICKSTART_THRESHOLD so we dont have to recalculate the threshold according min-max. - if (fanKickstart == 0 && speed > pwm_pos[NUM_EXTRUDER+2] && fanSpeed < PART_FAN_KICKSTART_THRESHOLD) { - if(speed) fanKickstart = PART_FAN_KICKSTART_TIME_BOOST / 10; + if (fanKickstart == 0 && speed > pwm_pos[NUM_EXTRUDER + 2] && fanSpeed < PART_FAN_KICKSTART_THRESHOLD) { + if (speed) fanKickstart = PART_FAN_KICKSTART_TIME_BOOST / 10; else fanKickstart = PART_FAN_KICKSTART_TIME_OFF_ON / 10; } - pwm_pos[NUM_EXTRUDER+2] = speed; + pwm_pos[NUM_EXTRUDER + 2] = speed; } // setFanSpeed #endif // FAN_PIN>-1 && FEATURE_FAN_CONTROL #if FAN_PIN>-1 && FEATURE_FAN_CONTROL -void Commands::adjustFanFrequency(uint8_t speed_divisor = PART_FAN_DEFAULT_PWM_SPEED_DIVISOR){ //1 = ~15.3hz, ~2=7.62hz, ... +void Commands::adjustFanFrequency(uint8_t speed_divisor = PART_FAN_DEFAULT_PWM_SPEED_DIVISOR) { //1 = ~15.3hz, ~2=7.62hz, ... InterruptProtectedBlock noInts; - if(!speed_divisor) speed_divisor = 1; + if (!speed_divisor) speed_divisor = 1; part_fan_pwm_speed = (speed_divisor <= PART_FAN_MODE_MAX ? speed_divisor : PART_FAN_DEFAULT_PWM_SPEED_DIVISOR); } -void Commands::adjustFanMode(uint8_t output_mode){ //0 = pwm, 1 = pdm +void Commands::adjustFanMode(uint8_t output_mode) { //0 = pwm, 1 = pdm part_fan_frequency_modulation = (output_mode ? PART_FAN_MODE_PDM : PART_FAN_MODE_PWM); Printer::setMenuMode(MENU_MODE_FAN_MODE_PDM, (bool)part_fan_frequency_modulation); } @@ -300,53 +301,53 @@ void Commands::reportPrinterUsage() { #if EEPROM_MODE!=0 #if FEATURE_MILLING_MODE - if( Printer::operatingMode == OPERATING_MODE_PRINT ) + if (Printer::operatingMode == OPERATING_MODE_PRINT) { #endif // FEATURE_MILLING_MODE - if( Printer::debugInfo() ) + if (Printer::debugInfo()) { - float dist = Printer::filamentPrinted*0.001+HAL::eprGetFloat(EPR_PRINTING_DISTANCE); - Com::printF(Com::tPrintedFilament,dist,2); + float dist = Printer::filamentPrinted*0.001 + HAL::eprGetFloat(EPR_PRINTING_DISTANCE); + Com::printF(Com::tPrintedFilament, dist, 2); Com::printF(Com::tSpacem); } bool alloff = true; - for(uint8_t i=0; itargetTemperatureC > 0) alloff = false; + for (uint8_t i = 0; i < NUM_EXTRUDER; i++) + if (tempController[i]->targetTemperatureC > 0) alloff = false; - if( Printer::debugInfo() ) + if (Printer::debugInfo()) { - int32_t seconds = (alloff ? 0 : (HAL::timeInMilliseconds()-Printer::msecondsPrinting)/1000)+HAL::eprGetInt32(EPR_PRINTING_TIME); - int32_t tmp = seconds/86400; - seconds -= tmp*86400; + int32_t seconds = (alloff ? 0 : (HAL::timeInMilliseconds() - Printer::msecondsPrinting) / 1000) + HAL::eprGetInt32(EPR_PRINTING_TIME); + int32_t tmp = seconds / 86400; + seconds -= tmp * 86400; - Com::printF(Com::tPrintingTime,tmp); - tmp = seconds/3600; - Com::printF(Com::tSpaceDaysSpace,tmp); - seconds -= tmp*3600; - tmp = seconds/60; + Com::printF(Com::tPrintingTime, tmp); + tmp = seconds / 3600; + Com::printF(Com::tSpaceDaysSpace, tmp); + seconds -= tmp * 3600; + tmp = seconds / 60; - Com::printF(Com::tSpaceHoursSpace,tmp); + Com::printF(Com::tSpaceHoursSpace, tmp); Com::printFLN(Com::tSpaceMin); } #if FEATURE_SERVICE_INTERVAL - if( Printer::debugInfo() ) + if (Printer::debugInfo()) { - float dist_service = Printer::filamentPrinted*0.001+HAL::eprGetFloat(EPR_PRINTING_DISTANCE_SERVICE); - Com::printF(Com::tPrintedFilamentService,dist_service,2); + float dist_service = Printer::filamentPrinted*0.001 + HAL::eprGetFloat(EPR_PRINTING_DISTANCE_SERVICE); + Com::printF(Com::tPrintedFilamentService, dist_service, 2); Com::printF(Com::tSpacem); - int32_t uSecondsServicePrint = (alloff ? 0 : (HAL::timeInMilliseconds()-Printer::msecondsPrinting)/1000)+HAL::eprGetInt32(EPR_PRINTING_TIME_SERVICE); - int32_t tmp_service = uSecondsServicePrint/86400; - uSecondsServicePrint -= tmp_service*86400; + int32_t uSecondsServicePrint = (alloff ? 0 : (HAL::timeInMilliseconds() - Printer::msecondsPrinting) / 1000) + HAL::eprGetInt32(EPR_PRINTING_TIME_SERVICE); + int32_t tmp_service = uSecondsServicePrint / 86400; + uSecondsServicePrint -= tmp_service * 86400; - Com::printF(Com::tPrintingTimeService,tmp_service); - tmp_service = uSecondsServicePrint/3600; - Com::printF(Com::tSpaceDaysSpace,tmp_service); - uSecondsServicePrint -= tmp_service*3600; - tmp_service = uSecondsServicePrint/60; + Com::printF(Com::tPrintingTimeService, tmp_service); + tmp_service = uSecondsServicePrint / 3600; + Com::printF(Com::tSpaceDaysSpace, tmp_service); + uSecondsServicePrint -= tmp_service * 3600; + tmp_service = uSecondsServicePrint / 60; - Com::printF(Com::tSpaceHoursSpace,tmp_service); + Com::printF(Com::tSpaceHoursSpace, tmp_service); Com::printFLN(Com::tSpaceMin); } #endif // FEATURE_SERVICE_INTERVAL @@ -354,35 +355,35 @@ void Commands::reportPrinterUsage() } else { - if( Printer::debugInfo() ) + if (Printer::debugInfo()) { - int32_t seconds = (HAL::timeInMilliseconds()-Printer::msecondsMilling)/1000 + HAL::eprGetInt32(EPR_MILLING_TIME); - int32_t tmp = seconds/86400; - seconds -= tmp*86400; + int32_t seconds = (HAL::timeInMilliseconds() - Printer::msecondsMilling) / 1000 + HAL::eprGetInt32(EPR_MILLING_TIME); + int32_t tmp = seconds / 86400; + seconds -= tmp * 86400; - Com::printF(Com::tMillingTime,tmp); - tmp = seconds/3600; - Com::printF(Com::tSpaceDaysSpace,tmp); - seconds -= tmp*3600; - tmp = seconds/60; + Com::printF(Com::tMillingTime, tmp); + tmp = seconds / 3600; + Com::printF(Com::tSpaceDaysSpace, tmp); + seconds -= tmp * 3600; + tmp = seconds / 60; - Com::printF(Com::tSpaceHoursSpace,tmp); + Com::printF(Com::tSpaceHoursSpace, tmp); Com::printFLN(Com::tSpaceMin); } #if FEATURE_SERVICE_INTERVAL - if( Printer::debugInfo() ) + if (Printer::debugInfo()) { - int32_t uSecondsServicePrint = (HAL::timeInMilliseconds()-Printer::msecondsMilling)/1000 + HAL::eprGetInt32(EPR_MILLING_TIME_SERVICE); - int32_t tmp_service = uSecondsServicePrint/86400; - uSecondsServicePrint -= tmp_service*86400; + int32_t uSecondsServicePrint = (HAL::timeInMilliseconds() - Printer::msecondsMilling) / 1000 + HAL::eprGetInt32(EPR_MILLING_TIME_SERVICE); + int32_t tmp_service = uSecondsServicePrint / 86400; + uSecondsServicePrint -= tmp_service * 86400; - Com::printF(Com::tMillingTimeService,tmp_service); - tmp_service = uSecondsServicePrint/3600; - Com::printF(Com::tSpaceDaysSpace,tmp_service); - uSecondsServicePrint -= tmp_service*3600; - tmp_service = uSecondsServicePrint/60; + Com::printF(Com::tMillingTimeService, tmp_service); + tmp_service = uSecondsServicePrint / 3600; + Com::printF(Com::tSpaceDaysSpace, tmp_service); + uSecondsServicePrint -= tmp_service * 3600; + tmp_service = uSecondsServicePrint / 60; - Com::printF(Com::tSpaceHoursSpace,tmp_service); + Com::printF(Com::tSpaceHoursSpace, tmp_service); Com::printFLN(Com::tSpaceMin); } #endif // FEATURE_SERVICE_INTERVAL @@ -396,95 +397,95 @@ void Commands::reportPrinterUsage() */ #if FEATURE_ARC_SUPPORT void Commands::processArc(GCode *com) { - //TODO: Check if coordinates must be relative here. I guess so ... - - float position[4]; - position[X_AXIS] = Printer::destinationMM[X_AXIS]; - position[Y_AXIS] = Printer::destinationMM[Y_AXIS]; - position[Z_AXIS] = Printer::destinationMM[Z_AXIS]; - position[E_AXIS] = Printer::destinationMM[E_AXIS]; - - Printer::queueGCodeCoordinates(com, true); // For X Y Z E F - - // get start position for arc lines - float target[4]; - target[X_AXIS] = Printer::destinationMM[X_AXIS]; - target[Y_AXIS] = Printer::destinationMM[Y_AXIS]; - target[Z_AXIS] = Printer::destinationMM[Z_AXIS]; - target[E_AXIS] = Printer::destinationMM[E_AXIS]; - - float offset[2] = { - Printer::convertToMM(com->hasI()?com->I:0), - Printer::convertToMM(com->hasJ()?com->J:0) - }; - - float r; - if (com->hasR()) { - /* - We need to calculate the center of the circle that has the designated radius and passes - through both the current position and the target position. This method calculates the following - set of equations where [x,y] is the vector from current to target position, d == magnitude of - that vector, h == hypotenuse of the triangle formed by the radius of the circle, the distance to - the center of the travel vector. A vector perpendicular to the travel vector [-y,x] is scaled to the - length of h [-y/d*h, x/d*h] and added to the center of the travel vector [x/2,y/2] to form the new point - [i,j] at [x/2-y/d*h, y/2+x/d*h] which will be the center of our arc. - - d^2 == x^2 + y^2 - h^2 == r^2 - (d/2)^2 - i == x/2 - y/d*h - j == y/2 + x/d*h - - O <- [i,j] - - | - r - | - - | - - | h - - | - [0,0] -> C -----------------+--------------- T <- [x,y] - | <------ d/2 ---->| - - C - Current position - T - Target position - O - center of circle that pass through both C and T - d - distance from C to T - r - designated radius - h - distance from center of CT to O - - Expanding the equations: - - d -> sqrt(x^2 + y^2) - h -> sqrt(4 * r^2 - x^2 - y^2)/2 - i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 - j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 - - Which can be written: - - i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 - j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 - - Which we for size and speed reasons optimize to: - - h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2) - i = (x - (y * h_x2_div_d))/2 - j = (y + (x * h_x2_div_d))/2 - - */ - r = Printer::convertToMM(com->R); - // Calculate the change in position along each selected axis - double x = target[X_AXIS] - position[X_AXIS]; - double y = target[Y_AXIS] - position[Y_AXIS]; - - double h_x2_div_d = -sqrt(4 * r * r - x * x - y * y) / hypot(x, y); // == -(h * 2 / d) - // If r is smaller than d, the arc is now traversing the complex plane beyond the reach of any - // real CNC, and thus - for practical reasons - we will terminate promptly: - if (isnan(h_x2_div_d)) { - Com::printErrorFLN(Com::tInvalidArc); - return; - } - // Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below) - if (com->G == 3) { - h_x2_div_d = -h_x2_div_d; - } + //TODO: Check if coordinates must be relative here. I guess so ... + + float position[4]; + position[X_AXIS] = Printer::destinationMM[X_AXIS]; + position[Y_AXIS] = Printer::destinationMM[Y_AXIS]; + position[Z_AXIS] = Printer::destinationMM[Z_AXIS]; + position[E_AXIS] = Printer::destinationMM[E_AXIS]; + + Printer::queueGCodeCoordinates(com, true); // For X Y Z E F + + // get start position for arc lines + float target[4]; + target[X_AXIS] = Printer::destinationMM[X_AXIS]; + target[Y_AXIS] = Printer::destinationMM[Y_AXIS]; + target[Z_AXIS] = Printer::destinationMM[Z_AXIS]; + target[E_AXIS] = Printer::destinationMM[E_AXIS]; + + float offset[2] = { + Printer::convertToMM(com->hasI() ? com->I : 0), + Printer::convertToMM(com->hasJ() ? com->J : 0) + }; + + float r; + if (com->hasR()) { + /* + We need to calculate the center of the circle that has the designated radius and passes + through both the current position and the target position. This method calculates the following + set of equations where [x,y] is the vector from current to target position, d == magnitude of + that vector, h == hypotenuse of the triangle formed by the radius of the circle, the distance to + the center of the travel vector. A vector perpendicular to the travel vector [-y,x] is scaled to the + length of h [-y/d*h, x/d*h] and added to the center of the travel vector [x/2,y/2] to form the new point + [i,j] at [x/2-y/d*h, y/2+x/d*h] which will be the center of our arc. + + d^2 == x^2 + y^2 + h^2 == r^2 - (d/2)^2 + i == x/2 - y/d*h + j == y/2 + x/d*h + + O <- [i,j] + - | + r - | + - | + - | h + - | + [0,0] -> C -----------------+--------------- T <- [x,y] + | <------ d/2 ---->| + + C - Current position + T - Target position + O - center of circle that pass through both C and T + d - distance from C to T + r - designated radius + h - distance from center of CT to O + + Expanding the equations: + + d -> sqrt(x^2 + y^2) + h -> sqrt(4 * r^2 - x^2 - y^2)/2 + i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 + j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 + + Which can be written: + + i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 + j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 + + Which we for size and speed reasons optimize to: + + h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2) + i = (x - (y * h_x2_div_d))/2 + j = (y + (x * h_x2_div_d))/2 + + */ + r = Printer::convertToMM(com->R); + // Calculate the change in position along each selected axis + double x = target[X_AXIS] - position[X_AXIS]; + double y = target[Y_AXIS] - position[Y_AXIS]; + + double h_x2_div_d = -sqrt(4 * r * r - x * x - y * y) / hypot(x, y); // == -(h * 2 / d) + // If r is smaller than d, the arc is now traversing the complex plane beyond the reach of any + // real CNC, and thus - for practical reasons - we will terminate promptly: + if (isnan(h_x2_div_d)) { + Com::printErrorFLN(Com::tInvalidArc); + return; + } + // Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below) + if (com->G == 3) { + h_x2_div_d = -h_x2_div_d; + } /* The counter clockwise circle lies to the left of the target direction. When offset is positive, the left hand circle will be generated - when it is negative the right hand circle is generated. @@ -503,1237 +504,1237 @@ void Commands::processArc(GCode *com) { C <-- Current position */ - // Negative R is g-code-alias for "I want a circle with more than 180 degrees of travel" (go figure!), - // even though it is advised against ever generating such circles in a single line of g-code. By - // inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of - // travel and thus we get the inadvisable long arcs as prescribed. - if (r < 0) { - h_x2_div_d = -h_x2_div_d; - r = -r; // Finished with r. Set to positive for mc_arc - } - // Complete the operation by calculating the actual center of the arc - offset[X_AXIS] = 0.5 * (x - (y * h_x2_div_d)); - offset[Y_AXIS] = 0.5 * (y + (x * h_x2_div_d)); - - } - else { // Offset mode specific computations - // here we have an offset for the center. A radius is being calculated. - - // this is a radius from start coordinates to the center of arc. - r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for arc - - // to reach the end coordinates we should have the same radius from center to end. - // Vector from start to end minus offset is the vector from offset to end: - double centerToEndX = target[X_AXIS] - position[X_AXIS] - offset[X_AXIS]; - double centerToEndY = target[Y_AXIS] - position[Y_AXIS] - offset[Y_AXIS]; - // distance from center of circle to endpoint - float r2 = hypot(centerToEndX, centerToEndY); // Compute arc radius for arc - - // What is a valid calculation error? - // For this check 0.01 circle perfectness is probably enough - // as this is only a validation for totally wrong generated gcodes. - // The last move is a move to the perfect end-point, but if the slicer/user calculated the center a bit wrong the actual drawn circle would not end at the endpoint. - if (fabs(r2 - r) > 0.01f) { - Com::printErrorFLN(Com::tInvalidArc); - return; - } - } - // Set clockwise/counter-clockwise sign for arc computations - uint8_t isclockwise = com->G == 2; - // Trace the arc - PrintLine::arc(position, target, offset, r, isclockwise); + // Negative R is g-code-alias for "I want a circle with more than 180 degrees of travel" (go figure!), + // even though it is advised against ever generating such circles in a single line of g-code. By + // inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of + // travel and thus we get the inadvisable long arcs as prescribed. + if (r < 0) { + h_x2_div_d = -h_x2_div_d; + r = -r; // Finished with r. Set to positive for mc_arc + } + // Complete the operation by calculating the actual center of the arc + offset[X_AXIS] = 0.5 * (x - (y * h_x2_div_d)); + offset[Y_AXIS] = 0.5 * (y + (x * h_x2_div_d)); + + } + else { // Offset mode specific computations + // here we have an offset for the center. A radius is being calculated. + + // this is a radius from start coordinates to the center of arc. + r = hypot(offset[X_AXIS], offset[Y_AXIS]); // Compute arc radius for arc + + // to reach the end coordinates we should have the same radius from center to end. + // Vector from start to end minus offset is the vector from offset to end: + double centerToEndX = target[X_AXIS] - position[X_AXIS] - offset[X_AXIS]; + double centerToEndY = target[Y_AXIS] - position[Y_AXIS] - offset[Y_AXIS]; + // distance from center of circle to endpoint + float r2 = hypot(centerToEndX, centerToEndY); // Compute arc radius for arc + + // What is a valid calculation error? + // For this check 0.01 circle perfectness is probably enough + // as this is only a validation for totally wrong generated gcodes. + // The last move is a move to the perfect end-point, but if the slicer/user calculated the center a bit wrong the actual drawn circle would not end at the endpoint. + if (fabs(r2 - r) > 0.01f) { + Com::printErrorFLN(Com::tInvalidArc); + return; + } + } + // Set clockwise/counter-clockwise sign for arc computations + uint8_t isclockwise = com->G == 2; + // Trace the arc + PrintLine::arc(position, target, offset, r, isclockwise); } #endif /** \brief Execute the command stored in com. */ void Commands::executeGCode(GCode *com) { - // Set return channel for private commands. By default all commands send to all receivers. - GCodeSource *actSource = GCodeSource::activeSource; - GCodeSource::activeSource = com->source; - Com::writeToAll = true; + // Set return channel for private commands. By default all commands send to all receivers. + GCodeSource *actSource = GCodeSource::activeSource; + GCodeSource::activeSource = com->source; + Com::writeToAll = true; if (com->hasG()) { - Commands::processGCode(com); + Commands::processGCode(com); } else if (com->hasM()) // Process M Code { - Commands::processMCode(com); - } - else if (com->hasT()) // Process T code - { - Commands::waitUntilEndOfAllMoves(); //Tn-Code (change Extruder) - Extruder::selectExtruderById(com->T); - } - else if (com->hasF()) // Process F code http://linuxcnc.org/docs/html/gcode/other-code.html#sec:set-feed-rate - { - Printer::setFeedrate(com->F); - } + Commands::processMCode(com); + } + else if (com->hasT()) // Process T code + { + Commands::waitUntilEndOfAllMoves(); //Tn-Code (change Extruder) + Extruder::selectExtruderById(com->T); + } + else if (com->hasF()) // Process F code http://linuxcnc.org/docs/html/gcode/other-code.html#sec:set-feed-rate + { + Printer::setFeedrate(com->F); + } else { - if(Printer::debugErrors()) + if (Printer::debugErrors()) { - Com::writeToAll = false; + Com::writeToAll = false; Com::printF(Com::tUnknownCommand); com->printCommand(); } } - GCodeSource::activeSource = actSource; + GCodeSource::activeSource = actSource; } // executeGCode /** \brief Execute the G command stored in com. */ void Commands::processGCode(GCode *com) { - switch (com->G) - { - case 0: // G0 -> G1 - case 1: // G1 - { - if (isMovingAllowed(PSTR("G0/1"))) - { - Printer::queueGCodeCoordinates(com); // For X Y Z E F - } - - break; - } + switch (com->G) + { + case 0: // G0 -> G1 + case 1: // G1 + { + if (isMovingAllowed(PSTR("G0/1"))) + { + Printer::queueGCodeCoordinates(com); // For X Y Z E F + } + + break; + } #if FEATURE_ARC_SUPPORT - case 2: // CW Arc - case 3: // CCW Arc MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC: - processArc(com); - break; + case 2: // CW Arc + case 3: // CCW Arc MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC: + processArc(com); + break; #endif - case 4: // G4 dwell - { - Commands::waitUntilEndOfAllMoves(); //G4 - uint32_t codenum = 0; - if (com->hasP()) codenum = com->P; // milliseconds to wait - if (com->hasS()) codenum = com->S * 1000; // seconds to wait - codenum += HAL::timeInMilliseconds(); // keep track of when we started waiting - - while ((uint32_t)(codenum - HAL::timeInMilliseconds()) < 2000000000) - { - Commands::checkForPeriodicalActions(Processing); - } - break; - } - case 20: // G20 - Units to inches - { - Printer::unitIsInches = 1; - break; - } - case 21: // G21 - Units to mm - { - Printer::unitIsInches = 0; - break; - } - case 28: // G28 - Home all axes one at a time - { - if (!isHomingAllowed(com)) - { - break; - } - uint8_t home_all_axis = (com->hasNoXYZ() && !com->hasE()); - if (com->hasE()) - { - Printer::setEAxisSteps(0); // Wie G92 E0 - } - if (home_all_axis || !com->hasNoXYZ()) - Printer::homeAxis(home_all_axis || com->hasX(), home_all_axis || com->hasY(), home_all_axis || com->hasZ()); - } - break; + case 4: // G4 dwell + { + Commands::waitUntilEndOfAllMoves(); //G4 + uint32_t codenum = 0; + if (com->hasP()) codenum = com->P; // milliseconds to wait + if (com->hasS()) codenum = com->S * 1000; // seconds to wait + codenum += HAL::timeInMilliseconds(); // keep track of when we started waiting + + while ((uint32_t)(codenum - HAL::timeInMilliseconds()) < 2000000000) + { + Commands::checkForPeriodicalActions(Processing); + } + break; + } + case 20: // G20 - Units to inches + { + Printer::unitIsInches = 1; + break; + } + case 21: // G21 - Units to mm + { + Printer::unitIsInches = 0; + break; + } + case 28: // G28 - Home all axes one at a time + { + if (!isHomingAllowed(com)) + { + break; + } + uint8_t home_all_axis = (com->hasNoXYZ() && !com->hasE()); + if (com->hasE()) + { + Printer::setEAxisSteps(0); // Wie G92 E0 + } + if (home_all_axis || !com->hasNoXYZ()) + Printer::homeAxis(home_all_axis || com->hasX(), home_all_axis || com->hasY(), home_all_axis || com->hasZ()); + } + break; #if FEATURE_MILLING_MODE - case 80: // G80 - { - if (isSupportedGCommand(com->G, OPERATING_MODE_MILL)) - { - // there is not a lot to do at the moment because drilling cycles are not supported - Printer::drillFeedrate = 0.0; - Printer::drillZDepth = 0.0; - } - break; - } - case 81: // G81 - { - if (isSupportedGCommand(com->G, OPERATING_MODE_MILL)) - { - char szTemp[40]; - float exitZ; - - - /* Com::printFLN( PSTR( "G81 detected" ) ); - if( com->hasX() ) Com::printFLN( PSTR( "X = " ), com->X ); - if( com->hasY() ) Com::printFLN( PSTR( "Y = " ), com->Y ); - if( com->hasZ() ) Com::printFLN( PSTR( "Z = " ), com->Z ); - if( com->hasR() ) Com::printFLN( PSTR( "R = " ), com->R ); - if( com->hasF() ) Com::printFLN( PSTR( "F = " ), com->F ); - */ - if (!isMovingAllowed(PSTR("G81"))) - { - break; - } - - // safety checks - if (!com->hasZ() && !Printer::drillZDepth) - { - if (Printer::debugErrors()) - { - Com::printFLN(PSTR("G81: aborted (the Z position is not defined)")); - } - break; - } - if (!com->hasF() && !Printer::drillFeedrate) - { - if (Printer::debugErrors()) - { - Com::printFLN(PSTR("G81: aborted (the drilling feedrate is not defined)")); - } - break; - } - - if (Printer::relativeCoordinateMode) - { - // move to the position of the (to be drilled) hole - strcpy(szTemp, "G1 X"); - addFloat(szTemp, com->hasX() ? com->X : 0, 3); - strcat(szTemp, " Y"); - addFloat(szTemp, com->hasY() ? com->Y : 0, 3); - strcat(szTemp, " Z"); - addFloat(szTemp, com->hasR() ? com->R : 0, 3); - strcat(szTemp, " F"); - addFloat(szTemp, Printer::maxFeedrate[X_AXIS], 3); - GCode::executeString(szTemp); - - // in order to leave the hole, we must travel the drilling path in reverse direction - exitZ = -(com->hasZ() ? com->Z : Printer::drillZDepth); - } - else - { - // move to the position of the (to be drilled) hole - strcpy(szTemp, "G1"); - if (com->hasX()) - { - strcat(szTemp, " X"); - addFloat(szTemp, com->X, 3); - } - if (com->hasY()) - { - strcat(szTemp, " Y"); - addFloat(szTemp, com->Y, 3); - } - if (com->hasR()) - { - strcat(szTemp, " Z"); - addFloat(szTemp, com->R, 3); - } - strcat(szTemp, " F"); - addFloat(szTemp, Printer::maxFeedrate[X_AXIS], 3); - GCode::executeString(szTemp); - - // in order to leave the hole, we must return to our start position - exitZ = Printer::destinationMM[Z_AXIS]; - } - - // drill the hole - strcpy(szTemp, "G1 Z"); - addFloat(szTemp, com->hasZ() ? com->Z : Printer::drillZDepth, 3); - strcat(szTemp, " F"); - addFloat(szTemp, com->hasF() ? com->F : Printer::drillFeedrate, 3); - - GCode::executeString(szTemp); - - // get out of the hole - strcpy(szTemp, "G1 Z"); - addFloat(szTemp, exitZ, 3); - strcat(szTemp, " F"); - addFloat(szTemp, Printer::maxFeedrate[Z_AXIS], 3); - - GCode::executeString(szTemp); - - if (com->hasZ()) Printer::drillZDepth = com->Z; - if (com->hasF()) Printer::drillFeedrate = com->F; - } - break; - } + case 80: // G80 + { + if (isSupportedGCommand(com->G, OPERATING_MODE_MILL)) + { + // there is not a lot to do at the moment because drilling cycles are not supported + Printer::drillFeedrate = 0.0; + Printer::drillZDepth = 0.0; + } + break; + } + case 81: // G81 + { + if (isSupportedGCommand(com->G, OPERATING_MODE_MILL)) + { + char szTemp[40]; + float exitZ; + + + /* Com::printFLN( PSTR( "G81 detected" ) ); + if( com->hasX() ) Com::printFLN( PSTR( "X = " ), com->X ); + if( com->hasY() ) Com::printFLN( PSTR( "Y = " ), com->Y ); + if( com->hasZ() ) Com::printFLN( PSTR( "Z = " ), com->Z ); + if( com->hasR() ) Com::printFLN( PSTR( "R = " ), com->R ); + if( com->hasF() ) Com::printFLN( PSTR( "F = " ), com->F ); + */ + if (!isMovingAllowed(PSTR("G81"))) + { + break; + } + + // safety checks + if (!com->hasZ() && !Printer::drillZDepth) + { + if (Printer::debugErrors()) + { + Com::printFLN(PSTR("G81: aborted (the Z position is not defined)")); + } + break; + } + if (!com->hasF() && !Printer::drillFeedrate) + { + if (Printer::debugErrors()) + { + Com::printFLN(PSTR("G81: aborted (the drilling feedrate is not defined)")); + } + break; + } + + if (Printer::relativeCoordinateMode) + { + // move to the position of the (to be drilled) hole + strcpy(szTemp, "G1 X"); + addFloat(szTemp, com->hasX() ? com->X : 0, 3); + strcat(szTemp, " Y"); + addFloat(szTemp, com->hasY() ? com->Y : 0, 3); + strcat(szTemp, " Z"); + addFloat(szTemp, com->hasR() ? com->R : 0, 3); + strcat(szTemp, " F"); + addFloat(szTemp, Printer::maxFeedrate[X_AXIS], 3); + GCode::executeString(szTemp); + + // in order to leave the hole, we must travel the drilling path in reverse direction + exitZ = -(com->hasZ() ? com->Z : Printer::drillZDepth); + } + else + { + // move to the position of the (to be drilled) hole + strcpy(szTemp, "G1"); + if (com->hasX()) + { + strcat(szTemp, " X"); + addFloat(szTemp, com->X, 3); + } + if (com->hasY()) + { + strcat(szTemp, " Y"); + addFloat(szTemp, com->Y, 3); + } + if (com->hasR()) + { + strcat(szTemp, " Z"); + addFloat(szTemp, com->R, 3); + } + strcat(szTemp, " F"); + addFloat(szTemp, Printer::maxFeedrate[X_AXIS], 3); + GCode::executeString(szTemp); + + // in order to leave the hole, we must return to our start position + exitZ = Printer::destinationMM[Z_AXIS]; + } + + // drill the hole + strcpy(szTemp, "G1 Z"); + addFloat(szTemp, com->hasZ() ? com->Z : Printer::drillZDepth, 3); + strcat(szTemp, " F"); + addFloat(szTemp, com->hasF() ? com->F : Printer::drillFeedrate, 3); + + GCode::executeString(szTemp); + + // get out of the hole + strcpy(szTemp, "G1 Z"); + addFloat(szTemp, exitZ, 3); + strcat(szTemp, " F"); + addFloat(szTemp, Printer::maxFeedrate[Z_AXIS], 3); + + GCode::executeString(szTemp); + + if (com->hasZ()) Printer::drillZDepth = com->Z; + if (com->hasF()) Printer::drillFeedrate = com->F; + } + break; + } #endif // FEATURE_MILLING_MODE - case 90: // G90 - { - Printer::relativeCoordinateMode = false; - if (com->internalCommand) - Com::printInfoFLN(PSTR("Absolute positioning")); - break; - } - case 91: // G91 - { - Printer::relativeCoordinateMode = true; - if (com->internalCommand) - Com::printInfoFLN(PSTR("Relative positioning")); - break; - } - case 92: // G92 - { - if (!com->hasNoXYZ()) - { - // set the origin only in case we got any x, y and/or z offset - float xOff = Printer::originOffsetMM[X_AXIS]; - float yOff = Printer::originOffsetMM[Y_AXIS]; - float zOff = Printer::originOffsetMM[Z_AXIS]; - - if (com->hasX()) xOff = Printer::convertToMM(com->X) - Printer::destinationMM[X_AXIS]; - if (com->hasY()) yOff = Printer::convertToMM(com->Y) - Printer::destinationMM[Y_AXIS]; - if (com->hasZ()) zOff = Printer::convertToMM(com->Z) - Printer::destinationMM[Z_AXIS]; - - Printer::setOrigin(xOff, yOff, zOff); - } - if (com->hasE()) - { - Printer::setEAxisSteps(Printer::convertToMM(com->E) * Printer::axisStepsPerMM[E_AXIS]); - } - break; - } - } - previousMillisCmd = HAL::timeInMilliseconds(); //prevent inactive shutdown of steppers/temps + case 90: // G90 + { + Printer::relativeCoordinateMode = false; + if (com->internalCommand) + Com::printInfoFLN(PSTR("Absolute positioning")); + break; + } + case 91: // G91 + { + Printer::relativeCoordinateMode = true; + if (com->internalCommand) + Com::printInfoFLN(PSTR("Relative positioning")); + break; + } + case 92: // G92 + { + if (!com->hasNoXYZ()) + { + // set the origin only in case we got any x, y and/or z offset + float xOff = Printer::originOffsetMM[X_AXIS]; + float yOff = Printer::originOffsetMM[Y_AXIS]; + float zOff = Printer::originOffsetMM[Z_AXIS]; + + if (com->hasX()) xOff = Printer::convertToMM(com->X) - Printer::destinationMM[X_AXIS]; + if (com->hasY()) yOff = Printer::convertToMM(com->Y) - Printer::destinationMM[Y_AXIS]; + if (com->hasZ()) zOff = Printer::convertToMM(com->Z) - Printer::destinationMM[Z_AXIS]; + + Printer::setOrigin(xOff, yOff, zOff); + } + if (com->hasE()) + { + Printer::setEAxisSteps(Printer::convertToMM(com->E) * Printer::axisStepsPerMM[E_AXIS]); + } + break; + } + } + previousMillisCmd = HAL::timeInMilliseconds(); //prevent inactive shutdown of steppers/temps } /** \brief Execute the M command stored in com. */ void Commands::processMCode(GCode *com) { - switch (com->M) - { + switch (com->M) + { #if SDSUPPORT - case 20: // M20 - list SD card - { - if(sd.sdactive) sd.ls(); - break; - } - case 21: // M21 - init SD card - { - sd.mount(/*not silent mount*/); - break; - } - case 22: // M22 - release SD card - { - sd.unmount(); - break; - } - case 23: // M23 - Select file - { - if (!sd.sdactive) break; - if (com->hasString()) - { - sd.fat.chdir(); - sd.selectFileByName(com->text); - } - break; - } - case 24: // M24 - Start SD print - { - if (g_pauseMode) - { - continuePrint(); - } - else - { - sd.startPrint(); - } - break; - } - case 25: // M25 - Pause (SD) print - { - queueTask(TASK_PAUSE_PRINT); - Commands::waitUntilEndOfAllMoves(); //M400 (normal gcode wait) - break; - } - case 26: // M26 - Set SD index - { - Com::printFLN(PSTR("M26: not supported")); - break; - } - case 27: // M27 - Get SD status - sd.printStatus(); - break; - case 28: // M28 - Start SD write - if (com->hasString()) - sd.startWrite(com->text); - break; - case 29: // M29 - Stop SD write - //processed in write to file routine above - //savetosd = false; - break; - case 30: // M30 - filename - Delete file - if (com->hasString()) - { - sd.fat.chdir(); - sd.deleteFile(com->text); - } - break; - case 32: // M32 - directoryname - if (com->hasString()) - { - sd.fat.chdir(); - sd.makeDirectory(com->text); - } - break; + case 20: // M20 - list SD card + { + if (sd.sdactive) sd.ls(); + break; + } + case 21: // M21 - init SD card + { + sd.mount(/*not silent mount*/); + break; + } + case 22: // M22 - release SD card + { + sd.unmount(); + break; + } + case 23: // M23 - Select file + { + if (!sd.sdactive) break; + if (com->hasString()) + { + sd.fat.chdir(); + sd.selectFileByName(com->text); + } + break; + } + case 24: // M24 - Start SD print + { + if (g_pauseMode) + { + continuePrint(); + } + else + { + sd.startPrint(); + } + break; + } + case 25: // M25 - Pause (SD) print + { + queueTask(TASK_PAUSE_PRINT); + Commands::waitUntilEndOfAllMoves(); //M400 (normal gcode wait) + break; + } + case 26: // M26 - Set SD index + { + Com::printFLN(PSTR("M26: not supported")); + break; + } + case 27: // M27 - Get SD status + sd.printStatus(); + break; + case 28: // M28 - Start SD write + if (com->hasString()) + sd.startWrite(com->text); + break; + case 29: // M29 - Stop SD write + //processed in write to file routine above + //savetosd = false; + break; + case 30: // M30 - filename - Delete file + if (com->hasString()) + { + sd.fat.chdir(); + sd.deleteFile(com->text); + } + break; + case 32: // M32 - directoryname + if (com->hasString()) + { + sd.fat.chdir(); + sd.makeDirectory(com->text); + } + break; #endif // SDSUPPORT - case 104: // M104 - set extruder temp - { - if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) - { + case 104: // M104 - set extruder temp + { + if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) + { #if NUM_EXTRUDER>0 - if (Printer::isAnyTempsensorDefect()) { - reportTempsensorAndHeaterErrors(); - break; - } - previousMillisCmd = HAL::timeInMilliseconds(); //prevent inactive shutdown of steppers/temps - if (Printer::debugDryrun()) break; - - //TODO man müsste das in den Movecache legen! - if (com->hasP() || (com->hasS() && com->S == 0)) - Commands::waitUntilEndOfAllMoves(); //M104 - - if (com->hasS()) - { - if (com->hasT()) - Extruder::setTemperatureForExtruder(com->S, com->T, com->hasF() && com->F > 0); - else - Extruder::setTemperatureForExtruder(com->S, Extruder::current->id, com->hasF() && com->F > 0); - } + if (Printer::isAnyTempsensorDefect()) { + reportTempsensorAndHeaterErrors(); + break; + } + previousMillisCmd = HAL::timeInMilliseconds(); //prevent inactive shutdown of steppers/temps + if (Printer::debugDryrun()) break; + + //TODO man müsste das in den Movecache legen! + if (com->hasP() || (com->hasS() && com->S == 0)) + Commands::waitUntilEndOfAllMoves(); //M104 + + if (com->hasS()) + { + if (com->hasT()) + Extruder::setTemperatureForExtruder(com->S, com->T, com->hasF() && com->F > 0); + else + Extruder::setTemperatureForExtruder(com->S, Extruder::current->id, com->hasF() && com->F > 0); + } #endif // NUM_EXTRUDER>0 - } - break; - } - case 105: // M105 - get temperature. Always returns the current temperature, doesn't wait until move stopped - { - Com::writeToAll = false; - printTemperatures(com->hasX()); - break; - } - case 140: // M140 - set bed temp - { - if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) - { - if (Printer::isAnyTempsensorDefect()) { - reportTempsensorAndHeaterErrors(); - break; - } - previousMillisCmd = HAL::timeInMilliseconds(); //prevent inactive shutdown of steppers/temps - if (Printer::debugDryrun()) break; - if (com->hasS()) Extruder::setHeatedBedTemperature(com->S, com->hasF() && com->F > 0); - } - break; - } - case 109: // M109 - Wait for extruder heater to reach target. - { - if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) - { - previousMillisCmd = HAL::timeInMilliseconds(); //prevent inactive shutdown of steppers/temps + } + break; + } + case 105: // M105 - get temperature. Always returns the current temperature, doesn't wait until move stopped + { + Com::writeToAll = false; + printTemperatures(com->hasX()); + break; + } + case 140: // M140 - set bed temp + { + if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) + { + if (Printer::isAnyTempsensorDefect()) { + reportTempsensorAndHeaterErrors(); + break; + } + previousMillisCmd = HAL::timeInMilliseconds(); //prevent inactive shutdown of steppers/temps + if (Printer::debugDryrun()) break; + if (com->hasS()) Extruder::setHeatedBedTemperature(com->S, com->hasF() && com->F > 0); + } + break; + } + case 109: // M109 - Wait for extruder heater to reach target. + { + if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) + { + previousMillisCmd = HAL::timeInMilliseconds(); //prevent inactive shutdown of steppers/temps #if NUM_EXTRUDER>0 - if (Printer::isAnyTempsensorDefect()) { - reportTempsensorAndHeaterErrors(); - break; - } - if (Printer::debugDryrun()) { - break; - } - - g_uStartOfIdle = 0; //M109 - Commands::waitUntilEndOfAllMoves(); //M109 - - Extruder *actExtruder = Extruder::current; - if (com->hasT() && com->T < NUM_EXTRUDER) actExtruder = &extruder[com->T]; - if (com->hasS()) Extruder::setTemperatureForExtruder(com->S, actExtruder->id, com->hasF() && com->F > 0); - - if (fabs(actExtruder->tempControl.targetTemperatureC - actExtruder->tempControl.currentTemperatureC) < TEMP_TOLERANCE) - { - break; - } + if (Printer::isAnyTempsensorDefect()) { + reportTempsensorAndHeaterErrors(); + break; + } + if (Printer::debugDryrun()) { + break; + } + + g_uStartOfIdle = 0; //M109 + Commands::waitUntilEndOfAllMoves(); //M109 + + Extruder *actExtruder = Extruder::current; + if (com->hasT() && com->T < NUM_EXTRUDER) actExtruder = &extruder[com->T]; + if (com->hasS()) Extruder::setTemperatureForExtruder(com->S, actExtruder->id, com->hasF() && com->F > 0); + + if (fabs(actExtruder->tempControl.targetTemperatureC - actExtruder->tempControl.currentTemperatureC) < TEMP_TOLERANCE) + { + break; + } #if RETRACT_DURING_HEATUP - uint8_t retracted = 0; + uint8_t retracted = 0; #endif // RETRACT_DURING_HEATUP - millis_t currentTime = HAL::timeInMilliseconds(); - bool isTempReached; - bool longTempTime = false; // random init - bool dirRising = true; // random init - float settarget = -1; // random init in °C - - do { - Commands::checkForPeriodicalActions(WaitHeater); - - //Anpassung an die neue Situation falls der Bediener am Display-Menü des Druckers während Aufheizzeit was umstellt. - if (settarget != actExtruder->tempControl.targetTemperatureC) { - settarget = actExtruder->tempControl.targetTemperatureC; //in °C - dirRising = (actExtruder->tempControl.targetTemperatureC > actExtruder->tempControl.currentTemperatureC); - longTempTime = (fabs(actExtruder->tempControl.targetTemperatureC - actExtruder->tempControl.currentTemperatureC) > 40.0f ? true : false); - if (dirRising) { - UI_STATUS_UPD(UI_TEXT_HEATING_EXTRUDER); - } - else { - UI_STATUS_UPD(UI_TEXT_COOLING_DOWN); - } - } - - isTempReached = fabs(actExtruder->tempControl.targetTemperatureC - actExtruder->tempControl.currentTemperatureC) < TEMP_TOLERANCE; + millis_t currentTime = HAL::timeInMilliseconds(); + bool isTempReached; + bool longTempTime = false; // random init + bool dirRising = true; // random init + float settarget = -1; // random init in °C + + do { + Commands::checkForPeriodicalActions(WaitHeater); + + //Anpassung an die neue Situation falls der Bediener am Display-Menü des Druckers während Aufheizzeit was umstellt. + if (settarget != actExtruder->tempControl.targetTemperatureC) { + settarget = actExtruder->tempControl.targetTemperatureC; //in °C + dirRising = (actExtruder->tempControl.targetTemperatureC > actExtruder->tempControl.currentTemperatureC); + longTempTime = (fabs(actExtruder->tempControl.targetTemperatureC - actExtruder->tempControl.currentTemperatureC) > 40.0f ? true : false); + if (dirRising) { + UI_STATUS_UPD(UI_TEXT_HEATING_EXTRUDER); + } + else { + UI_STATUS_UPD(UI_TEXT_COOLING_DOWN); + } + } + + isTempReached = fabs(actExtruder->tempControl.targetTemperatureC - actExtruder->tempControl.currentTemperatureC) < TEMP_TOLERANCE; #if RETRACT_DURING_HEATUP - if (!retracted && dirRising) { - if (longTempTime - && actExtruder == Extruder::current - && actExtruder->waitRetractUnits > 0 - && actExtruder->tempControl.currentTemperatureC >= actExtruder->waitRetractTemperature) - { - Printer::queueRelativeMMCoordinates(0, 0, 0, -actExtruder->waitRetractUnits, actExtruder->maxFeedrate, false, false); - retracted = 1; - } - } + if (!retracted && dirRising) { + if (longTempTime + && actExtruder == Extruder::current + && actExtruder->waitRetractUnits > 0 + && actExtruder->tempControl.currentTemperatureC >= actExtruder->waitRetractTemperature) + { + Printer::queueRelativeMMCoordinates(0, 0, 0, -actExtruder->waitRetractUnits, actExtruder->maxFeedrate, false, false); + retracted = 1; + } + } #endif // RETRACT_DURING_HEATUP - if (!dirRising) { - if (actExtruder->tempControl.currentTemperatureC <= MAX_ROOM_TEMPERATURE) { - break; - //never wait longer than reaching lowest allowed temperature. - //This might still be a long-run-bug if you have heated chamber/hot summer and wrong settings in MAX_ROOM_TEMPERATURE! - } - } - if (abs(HAL::timeInMilliseconds() - currentTime) > 300000) { - /* Aufheizen dauert nie länger als 5 Minuten */ - break; - } - if (Printer::isAnyTempsensorDefect()) { - /* Temp sensor decoupled oder defekt? abort. */ - break; - } - } while (!isTempReached); + if (!dirRising) { + if (actExtruder->tempControl.currentTemperatureC <= MAX_ROOM_TEMPERATURE) { + break; + //never wait longer than reaching lowest allowed temperature. + //This might still be a long-run-bug if you have heated chamber/hot summer and wrong settings in MAX_ROOM_TEMPERATURE! + } + } + if (abs(HAL::timeInMilliseconds() - currentTime) > 300000) { + /* Aufheizen dauert nie länger als 5 Minuten */ + break; + } + if (Printer::isAnyTempsensorDefect()) { + /* Temp sensor decoupled oder defekt? abort. */ + break; + } + } while (!isTempReached); #if RETRACT_DURING_HEATUP - if (retracted && actExtruder == Extruder::current) - { - Printer::queueRelativeMMCoordinates(0, 0, 0, actExtruder->waitRetractUnits, actExtruder->maxFeedrate, false, false); - } + if (retracted && actExtruder == Extruder::current) + { + Printer::queueRelativeMMCoordinates(0, 0, 0, actExtruder->waitRetractUnits, actExtruder->maxFeedrate, false, false); + } #endif // RETRACT_DURING_HEATUP #endif // NUM_EXTRUDER>0 - g_uStartOfIdle = HAL::timeInMilliseconds(); //end of M109 - } - break; - } - case 190: // M190 - Wait bed for heater to reach target. - { - if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) - { + g_uStartOfIdle = HAL::timeInMilliseconds(); //end of M109 + } + break; + } + case 190: // M190 - Wait bed for heater to reach target. + { + if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) + { #if HAVE_HEATED_BED - previousMillisCmd = HAL::timeInMilliseconds(); //prevent inactive shutdown of steppers/temps - if (Printer::isAnyTempsensorDefect()) { - reportTempsensorAndHeaterErrors(); - break; - } - if (Printer::debugDryrun()) { - break; - } - g_uStartOfIdle = 0; //M190 - Commands::waitUntilEndOfAllMoves(); //M190 - if (com->hasS()) Extruder::setHeatedBedTemperature(com->S, com->hasF() && com->F > 0); - - bool dirRising = true; // random init - float settarget = -1; // random init in °C - - while (fabs(heatedBedController.currentTemperatureC - heatedBedController.targetTemperatureC) > TEMP_TOLERANCE) - { - //Init und Anpassung an die neue Situation falls der Bediener am Display-Menü des Druckers während Aufheizzeit was umstellt. - if (settarget != heatedBedController.targetTemperatureC) { - settarget = heatedBedController.targetTemperatureC; //in °C - dirRising = (heatedBedController.targetTemperatureC > heatedBedController.currentTemperatureC); - if (dirRising) { - UI_STATUS_UPD(UI_TEXT_HEATING_BED); - } - else { - UI_STATUS_UPD(UI_TEXT_COOLING_DOWN); - } - } - - Commands::checkForPeriodicalActions(WaitHeater); - if (!dirRising && heatedBedController.currentTemperatureC <= MAX_ROOM_TEMPERATURE) break; - if (Printer::isAnyTempsensorDefect()) break; - } - - g_uStartOfIdle = HAL::timeInMilliseconds() + 5000; //end of M190 + previousMillisCmd = HAL::timeInMilliseconds(); //prevent inactive shutdown of steppers/temps + if (Printer::isAnyTempsensorDefect()) { + reportTempsensorAndHeaterErrors(); + break; + } + if (Printer::debugDryrun()) { + break; + } + g_uStartOfIdle = 0; //M190 + Commands::waitUntilEndOfAllMoves(); //M190 + if (com->hasS()) Extruder::setHeatedBedTemperature(com->S, com->hasF() && com->F > 0); + + bool dirRising = true; // random init + float settarget = -1; // random init in °C + + while (fabs(heatedBedController.currentTemperatureC - heatedBedController.targetTemperatureC) > TEMP_TOLERANCE) + { + //Init und Anpassung an die neue Situation falls der Bediener am Display-Menü des Druckers während Aufheizzeit was umstellt. + if (settarget != heatedBedController.targetTemperatureC) { + settarget = heatedBedController.targetTemperatureC; //in °C + dirRising = (heatedBedController.targetTemperatureC > heatedBedController.currentTemperatureC); + if (dirRising) { + UI_STATUS_UPD(UI_TEXT_HEATING_BED); + } + else { + UI_STATUS_UPD(UI_TEXT_COOLING_DOWN); + } + } + + Commands::checkForPeriodicalActions(WaitHeater); + if (!dirRising && heatedBedController.currentTemperatureC <= MAX_ROOM_TEMPERATURE) break; + if (Printer::isAnyTempsensorDefect()) break; + } + + g_uStartOfIdle = HAL::timeInMilliseconds() + 5000; //end of M190 #endif // HAVE_HEATED_BED - } - break; - } - case 116: // M116 - Wait for temperatures to reach target temperature - { - if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) - { - if (Printer::debugDryrun()) break; - { - bool allReached = false; - while (!allReached) - { - allReached = true; - Commands::checkForPeriodicalActions(WaitHeater); - - for (uint8_t h = 0; h < NUM_TEMPERATURE_LOOPS; h++) - { - TemperatureController *act = tempController[h]; - if (act->targetTemperatureC > MAX_ROOM_TEMPERATURE && fabs(act->targetTemperatureC - act->currentTemperatureC) > TEMP_TOLERANCE) - { - allReached = false; - } - } - } - } - } - break; - } + } + break; + } + case 116: // M116 - Wait for temperatures to reach target temperature + { + if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) + { + if (Printer::debugDryrun()) break; + { + bool allReached = false; + while (!allReached) + { + allReached = true; + Commands::checkForPeriodicalActions(WaitHeater); + + for (uint8_t h = 0; h < NUM_TEMPERATURE_LOOPS; h++) + { + TemperatureController *act = tempController[h]; + if (act->targetTemperatureC > MAX_ROOM_TEMPERATURE && fabs(act->targetTemperatureC - act->currentTemperatureC) > TEMP_TOLERANCE) + { + allReached = false; + } + } + } + } + } + break; + } #if FEATURE_DITTO_PRINTING - case 280: // M280 - { - if (com->hasS()) // Set ditto mode S: 0 = off, 1 = on - { - Extruder::dittoMode = com->S; - } - break; - } + case 280: // M280 + { + if (com->hasS()) // Set ditto mode S: 0 = off, 1 = on + { + Extruder::dittoMode = com->S; + } + break; + } #endif // FEATURE_DITTO_PRINTING #if BEEPER_PIN >= 0 - case 300: // M300 - { - int beepS = 1; - int beepP = 1000; - if (com->hasS()) beepS = com->S; - if (com->hasP()) beepP = com->P; - HAL::tone(BEEPER_PIN, beepS); - HAL::delayMilliseconds(beepP); - HAL::noTone(BEEPER_PIN); - } - break; + case 300: // M300 + { + int beepS = 1; + int beepP = 1000; + if (com->hasS()) beepS = com->S; + if (com->hasP()) beepP = com->P; + HAL::tone(BEEPER_PIN, beepS); + HAL::delayMilliseconds(beepP); + HAL::noTone(BEEPER_PIN); + } + break; #endif // BEEPER_PIN >= 0 - case 303: // M303 - { - if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) - { + case 303: // M303 + { + if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) + { #if NUM_TEMPERATURE_LOOPS > 0 - int temp = 150; - int cont = 0; - int cycles = 10; - int method = 0; //0 = Classic PID - if (com->hasS()) temp = com->S; //Verwechsle ich immer, weil T wie Temperatur, aber T ist 0..255 - if (com->hasP()) cont = com->P; - if (com->hasR()) cycles = static_cast(com->R); - if (com->hasJ()) method = static_cast(com->J); //original Repetier used hasC, we dont have that in this version of repetier. - if (cont >= NUM_TEMPERATURE_LOOPS) cont = NUM_TEMPERATURE_LOOPS - 1; - if (cont < 0) cont = 0; - tempController[cont]->autotunePID(temp, cont, cycles, com->hasX(), method); + int temp = 150; + int cont = 0; + int cycles = 10; + int method = 0; //0 = Classic PID + if (com->hasS()) temp = com->S; //Verwechsle ich immer, weil T wie Temperatur, aber T ist 0..255 + if (com->hasP()) cont = com->P; + if (com->hasR()) cycles = static_cast(com->R); + if (com->hasJ()) method = static_cast(com->J); //original Repetier used hasC, we dont have that in this version of repetier. + if (cont >= NUM_TEMPERATURE_LOOPS) cont = NUM_TEMPERATURE_LOOPS - 1; + if (cont < 0) cont = 0; + tempController[cont]->autotunePID(temp, cont, cycles, com->hasX(), method); #endif // NUM_TEMPERATURE_LOOPS > 0 - } - break; - } + } + break; + } #if FAN_PIN>-1 && FEATURE_FAN_CONTROL - case 106: // M106 - Fan On - { - if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) - { - setFanSpeed(com->hasS() ? (uint8_t)constrain(com->S, 0, 255) : (uint8_t)255); - } - break; - } - case 107: // M107 - Fan Off - { - if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) - { - setFanSpeed(0); - } - break; - } + case 106: // M106 - Fan On + { + if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) + { + setFanSpeed(com->hasS() ? (uint8_t)constrain(com->S, 0, 255) : (uint8_t)255); + } + break; + } + case 107: // M107 - Fan Off + { + if (isSupportedMCommand(com->M, OPERATING_MODE_PRINT)) + { + setFanSpeed(0); + } + break; + } #endif // FAN_PIN>-1 && FEATURE_FAN_CONTROL - case 82: // M82 - { - Printer::relativeExtruderCoordinateMode = false; - break; - } - case 83: // M83 - { - Printer::relativeExtruderCoordinateMode = true; - break; - } - case 84: // M84 - { - if (com->hasS()) - { - stepperInactiveTime = com->S * 1000; - } - else - { - Commands::waitUntilEndOfAllMoves(); //M84 - Printer::disableAllSteppersNow(); - } - break; - } - case 85: // M85 - { - if (com->hasS()) - maxInactiveTime = (long)com->S * 1000; - else - maxInactiveTime = 0; - break; - } - case 99: // M99 S