2739 lines
104 KiB
C++
2739 lines
104 KiB
C++
|
/*
|
||
|
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 <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
This firmware is a nearly complete rewrite of the sprinter firmware
|
||
|
by kliment (https://github.com/kliment/Sprinter)
|
||
|
which based on Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware.
|
||
|
*/
|
||
|
|
||
|
#include "Repetier.h"
|
||
|
|
||
|
uint8_t mpu_threshold = 50;
|
||
|
//float probes[9];
|
||
|
|
||
|
#include <Wire.h>
|
||
|
|
||
|
#define ACCELEROMETER_I2C_ADDR 0x19
|
||
|
|
||
|
void accelerometer_send(uint8_t val)
|
||
|
{
|
||
|
#if FEATURE_Z_PROBE == 1
|
||
|
Wire.beginTransmission(ACCELEROMETER_I2C_ADDR);
|
||
|
Wire.write(val);
|
||
|
if(Wire.endTransmission(false))
|
||
|
//Myserial.println(F("send i2c error."));
|
||
|
Com::printFLN(PSTR("accelerometer send i2c failed."));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void accelerometer_write(uint8_t reg, uint8_t val)
|
||
|
{
|
||
|
#if FEATURE_Z_PROBE == 1
|
||
|
Wire.beginTransmission(ACCELEROMETER_I2C_ADDR);
|
||
|
Wire.write(reg);
|
||
|
Wire.write(val);
|
||
|
if(Wire.endTransmission())
|
||
|
//Myserial.println(F("write i2c error."));
|
||
|
Com::printFLN(PSTR("accelerometer write i2c failed."));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
bool accelerometer_recv(uint8_t reg)
|
||
|
{
|
||
|
#if FEATURE_Z_PROBE == 1
|
||
|
uint8_t receiveByte;
|
||
|
|
||
|
accelerometer_send(reg); //Send an 8bit register to be read
|
||
|
|
||
|
Wire.requestFrom(ACCELEROMETER_I2C_ADDR,1); //Request one 8bit response
|
||
|
|
||
|
if(Wire.available())
|
||
|
{
|
||
|
receiveByte = Wire.read();
|
||
|
|
||
|
// Com::printF(PSTR("read reg "),reg);
|
||
|
// Com::printFLN(PSTR(" value: "),receiveByte);
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Com::printFLN(PSTR("accelerometer i2c recv failed."));
|
||
|
return false;
|
||
|
//Serial.println(F("i2c recv error."));
|
||
|
}
|
||
|
#else
|
||
|
return false;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void accelerometer_init()
|
||
|
{
|
||
|
#if FEATURE_Z_PROBE == 1
|
||
|
Com::printFLN(PSTR("iis2dh accelerometer initializing..."));
|
||
|
Wire.begin(); // join i2c bus
|
||
|
|
||
|
accelerometer_recv(0x0F); //WHO AM I = 0x6A
|
||
|
|
||
|
accelerometer_recv(0x31); //INT1_SRC (31h)
|
||
|
|
||
|
//CTRL_REG1 (20h)
|
||
|
accelerometer_recv(0x20);
|
||
|
accelerometer_write(0x20,0b10011100); // ODR 5.376kHz in LPMode [7-4]. Low power enable [3]. Z enable [2].
|
||
|
accelerometer_recv(0x20);
|
||
|
|
||
|
|
||
|
//CTRL_REG3 (22h)
|
||
|
accelerometer_recv(0x22);
|
||
|
accelerometer_write(0x22,0b01000000); // CLICK interrupt on INT1 pin [7]. AOI (And Or Interrupt) on INT1 en [6]. AOI on INT2 en [5].
|
||
|
accelerometer_recv(0x22);
|
||
|
|
||
|
//CTRL_REG6 (25h)
|
||
|
accelerometer_recv(0x25);
|
||
|
accelerometer_write(0x25,0b000000); //Click interrupt on INT2 pin [7]. Interrupt 1 function enable on INT2 pin [6]. Interrupt 2 on INT2 pin enable [5]. 0=INT Active High [1].
|
||
|
accelerometer_recv(0x25);
|
||
|
|
||
|
//CTRL_REG4 (23h)
|
||
|
accelerometer_recv(0x23);
|
||
|
accelerometer_write(0x23,0b00110000); // Full-scale selection 16G [5-4]. High resolution mode [3].
|
||
|
accelerometer_recv(0x23);
|
||
|
|
||
|
|
||
|
//CTRL_REG5 (24h)
|
||
|
accelerometer_recv(0x24);
|
||
|
accelerometer_write(0x24,0b01001010); // FIFO enable [6]. Latch INT1 [3]. Latch INT2 until cleared by read [1].
|
||
|
accelerometer_recv(0x24);
|
||
|
|
||
|
|
||
|
//INT1_CFG (30h)
|
||
|
accelerometer_recv(0x30);
|
||
|
accelerometer_write(0x30,0b100000); // ZHI events enabled [5]. ZLO events enabled [4].
|
||
|
accelerometer_recv(0x30);
|
||
|
|
||
|
//INT1_SRC (31h)
|
||
|
accelerometer_recv(0x31);
|
||
|
|
||
|
//INT1_THS (32h) this is the i2c probe
|
||
|
accelerometer_recv(0x32);
|
||
|
accelerometer_write(0x32,Z_PROBE_SENSITIVITY); // 7bits
|
||
|
accelerometer_recv(0x32);
|
||
|
|
||
|
//INT1_DURATION (33h)
|
||
|
accelerometer_recv(0x33);
|
||
|
accelerometer_write(0x33,0);
|
||
|
accelerometer_recv(0x33);
|
||
|
|
||
|
//INT2_CFG (34h)
|
||
|
accelerometer_recv(0x34);
|
||
|
accelerometer_write(0x34,0b000000); // ZHI events not enabled on INT2 [5].
|
||
|
accelerometer_recv(0x34);
|
||
|
|
||
|
//INT2_SRC (35h)
|
||
|
|
||
|
//INT2_THS (36h)
|
||
|
accelerometer_recv(0x36);
|
||
|
accelerometer_write(0x36,50); // 7bits
|
||
|
accelerometer_recv(0x36);
|
||
|
|
||
|
//INT2_DURATION (37h)
|
||
|
accelerometer_recv(0x37);
|
||
|
accelerometer_write(0x37,0);
|
||
|
accelerometer_recv(0x37);
|
||
|
|
||
|
|
||
|
//CLICK_CFG (38h)
|
||
|
accelerometer_recv(0x38);
|
||
|
accelerometer_write(0x38,0b10000); //Single Click Z axis
|
||
|
accelerometer_recv(0x38);
|
||
|
|
||
|
//CLICK_SRC (39h)
|
||
|
accelerometer_recv(0x39);
|
||
|
|
||
|
//CLICK_THS (3Ah)
|
||
|
accelerometer_recv(0x3A);
|
||
|
accelerometer_write(0x3A,50);
|
||
|
accelerometer_recv(0x3A);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
bool accelerometer_status()
|
||
|
{
|
||
|
#if FEATURE_Z_PROBE == 1
|
||
|
bool retValue = true;
|
||
|
|
||
|
if(!accelerometer_recv(0x31)) { retValue = false; } //INT1_SRC (31h)
|
||
|
if(!accelerometer_recv(0x35)) { retValue = false; } //INT1_SRC (31h)
|
||
|
if(!accelerometer_recv(0x39)) { retValue = false; } //INT1_SRC (31h)
|
||
|
if(!accelerometer_recv(0x2D)) { retValue = false; } //INT1_SRC (31h)
|
||
|
|
||
|
return(retValue);
|
||
|
#else
|
||
|
return(false);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
const int sensitive_pins[] PROGMEM = SENSITIVE_PINS; // Sensitive pin list for M42
|
||
|
int Commands::lowestRAMValue = MAX_RAM;
|
||
|
int Commands::lowestRAMValueSend = MAX_RAM;
|
||
|
|
||
|
void Commands::commandLoop()
|
||
|
{
|
||
|
while(true)
|
||
|
{
|
||
|
#ifdef DEBUG_PRINT
|
||
|
debugWaitLoop = 1;
|
||
|
#endif
|
||
|
if(!Printer::isBlockingReceive())
|
||
|
{
|
||
|
GCode::readFromSerial();
|
||
|
GCode *code = GCode::peekCurrentCommand();
|
||
|
//UI_SLOW; // do longer timed user interface action
|
||
|
UI_MEDIUM; // do check encoder
|
||
|
if(code)
|
||
|
{
|
||
|
#if SDSUPPORT
|
||
|
if(sd.savetosd)
|
||
|
{
|
||
|
if(!(code->hasM() && code->M == 29)) // still writing to file
|
||
|
sd.writeCommand(code);
|
||
|
else
|
||
|
sd.finishWrite();
|
||
|
#if ECHO_ON_EXECUTE
|
||
|
code->echoCommand();
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
#endif
|
||
|
Commands::executeGCode(code);
|
||
|
code->popCurrentCommand();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UI_MEDIUM;
|
||
|
}
|
||
|
Printer::defaultLoopActions();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Commands::checkForPeriodicalActions(bool allowNewMoves)
|
||
|
{
|
||
|
if(!executePeriodical) return;
|
||
|
executePeriodical = 0;
|
||
|
Extruder::manageTemperatures();
|
||
|
if(--counter250ms == 0)
|
||
|
{
|
||
|
if(manageMonitor <= 1 + NUM_EXTRUDER)
|
||
|
writeMonitor();
|
||
|
counter250ms = 5;
|
||
|
}
|
||
|
// If called from queueDelta etc. it is an error to start a new move since it
|
||
|
// would invalidate old computation resulting in unpredicted behaviour.
|
||
|
// lcd controller can start new moves, so we disallow it if called from within
|
||
|
// a move command.
|
||
|
UI_SLOW(allowNewMoves);
|
||
|
}
|
||
|
|
||
|
/** \brief Waits until movement cache is empty.
|
||
|
|
||
|
Some commands expect no movement, before they can execute. This function
|
||
|
waits, until the steppers are stopped. In the meanwhile it buffers incoming
|
||
|
commands and manages temperatures.
|
||
|
*/
|
||
|
void Commands::waitUntilEndOfAllMoves()
|
||
|
{
|
||
|
#ifdef DEBUG_PRINT
|
||
|
debugWaitLoop = 8;
|
||
|
#endif
|
||
|
while(PrintLine::hasLines())
|
||
|
{
|
||
|
GCode::readFromSerial();
|
||
|
checkForPeriodicalActions(false);
|
||
|
UI_MEDIUM;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Commands::waitUntilEndOfAllBuffers()
|
||
|
{
|
||
|
GCode *code = NULL;
|
||
|
#ifdef DEBUG_PRINT
|
||
|
debugWaitLoop = 9;
|
||
|
#endif
|
||
|
while(PrintLine::hasLines() || (code != NULL))
|
||
|
{
|
||
|
GCode::readFromSerial();
|
||
|
code = GCode::peekCurrentCommand();
|
||
|
UI_MEDIUM; // do check encoder
|
||
|
if(code)
|
||
|
{
|
||
|
#if SDSUPPORT
|
||
|
if(sd.savetosd)
|
||
|
{
|
||
|
if(!(code->hasM() && code->M == 29)) // still writing to file
|
||
|
sd.writeCommand(code);
|
||
|
else
|
||
|
sd.finishWrite();
|
||
|
#if ECHO_ON_EXECUTE
|
||
|
code->echoCommand();
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
#endif
|
||
|
Commands::executeGCode(code);
|
||
|
code->popCurrentCommand();
|
||
|
}
|
||
|
Commands::checkForPeriodicalActions(false); // only called from memory
|
||
|
UI_MEDIUM;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Commands::printCurrentPosition(FSTRINGPARAM(s))
|
||
|
{
|
||
|
float x, y, z;
|
||
|
Printer::realPosition(x, y, z);
|
||
|
if (isnan(x) || isinf(x) || isnan(y) || isinf(y) || isnan(z) || isinf(z))
|
||
|
{
|
||
|
Com::printErrorFLN(s); // flag where the error condition came from
|
||
|
}
|
||
|
x += Printer::coordinateOffset[X_AXIS];
|
||
|
y += Printer::coordinateOffset[Y_AXIS];
|
||
|
z += Printer::coordinateOffset[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), 3);
|
||
|
Com::printFLN(Com::tSpaceEColon, Printer::currentPositionSteps[E_AXIS] * Printer::invAxisStepsPerMM[E_AXIS] * (Printer::unitIsInches ? 0.03937 : 1), 4);
|
||
|
//Com::printF(PSTR("OffX:"),Printer::offsetX); // to debug offset handling
|
||
|
//Com::printFLN(PSTR(" OffY:"),Printer::offsetY);
|
||
|
}
|
||
|
|
||
|
void Commands::printTemperatures(bool showRaw)
|
||
|
{
|
||
|
float temp = Extruder::current->tempControl.currentTemperatureC;
|
||
|
#if HEATED_BED_SENSOR_TYPE == 0
|
||
|
Com::printF(Com::tTColon,temp);
|
||
|
Com::printF(Com::tSpaceSlash,Extruder::current->tempControl.targetTemperatureC,0);
|
||
|
#else
|
||
|
Com::printF(Com::tTColon,temp);
|
||
|
Com::printF(Com::tSpaceSlash,Extruder::current->tempControl.targetTemperatureC,0);
|
||
|
#if HAVE_HEATED_BED
|
||
|
Com::printF(Com::tSpaceBColon,Extruder::getHeatedBedTemperature());
|
||
|
Com::printF(Com::tSpaceSlash,heatedBedController.targetTemperatureC,0);
|
||
|
if(showRaw)
|
||
|
{
|
||
|
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!
|
||
|
#endif
|
||
|
#endif
|
||
|
#if TEMP_PID
|
||
|
Com::printF(Com::tSpaceAtColon,(autotuneIndex==255?pwm_pos[Extruder::current->id]:pwm_pos[autotuneIndex])); // Show output of autotune when tuning!
|
||
|
#endif
|
||
|
#if NUM_EXTRUDER>1 && MIXING_EXTRUDER == 0
|
||
|
for(uint8_t i = 0; i < NUM_EXTRUDER; i++)
|
||
|
{
|
||
|
Com::printF(Com::tSpaceT,(int)i);
|
||
|
Com::printF(Com::tColon,extruder[i].tempControl.currentTemperatureC);
|
||
|
Com::printF(Com::tSpaceSlash,extruder[i].tempControl.targetTemperatureC,0);
|
||
|
#if TEMP_PID
|
||
|
Com::printF(Com::tSpaceAt,(int)i);
|
||
|
Com::printF(Com::tColon,(pwm_pos[extruder[i].tempControl.pwmIndex])); // Show output of autotune when tuning!
|
||
|
#endif
|
||
|
if(showRaw)
|
||
|
{
|
||
|
Com::printF(Com::tSpaceRaw,(int)i);
|
||
|
Com::printF(Com::tColon,(1023 << (2 - ANALOG_REDUCE_BITS)) - extruder[i].tempControl.currentTemperature);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
Com::println();
|
||
|
}
|
||
|
void Commands::changeFeedrateMultiply(int factor)
|
||
|
{
|
||
|
if(factor < 25) factor = 25;
|
||
|
if(factor > 500) factor = 500;
|
||
|
Printer::feedrate *= (float)factor / (float)Printer::feedrateMultiply;
|
||
|
Printer::feedrateMultiply = factor;
|
||
|
Com::printFLN(Com::tSpeedMultiply, factor);
|
||
|
}
|
||
|
void Commands::changeHorizontalRadius(float hradius)
|
||
|
{
|
||
|
if (hradius < 60) hradius = 60;
|
||
|
if (hradius > 150) hradius = 150;
|
||
|
Printer::radius0 = hradius;
|
||
|
Com::printFLN(Com::tHorizontalRadius, hradius);
|
||
|
// EEPROM::storeDataIntoEEPROM(false);
|
||
|
}
|
||
|
void Commands::changeFlowrateMultiply(int factor)
|
||
|
{
|
||
|
if(factor < 25) factor = 25;
|
||
|
if(factor > 200) factor = 200;
|
||
|
Printer::extrudeMultiply = factor;
|
||
|
if(Extruder::current->diameter <= 0)
|
||
|
Printer::extrusionFactor = 0.01f * static_cast<float>(factor);
|
||
|
else
|
||
|
Printer::extrusionFactor = 0.01f * static_cast<float>(factor) * 4.0f / (Extruder::current->diameter * Extruder::current->diameter * 3.141592654f);
|
||
|
Com::printFLN(Com::tFlowMultiply, factor);
|
||
|
}
|
||
|
|
||
|
void Commands::setFanSpeed(int speed,bool wait)
|
||
|
{
|
||
|
#if FAN_PIN>-1 && FEATURE_FAN_CONTROL
|
||
|
speed = constrain(speed,0,255);
|
||
|
Printer::setMenuMode(MENU_MODE_FAN_RUNNING,speed != 0);
|
||
|
if(wait)
|
||
|
Commands::waitUntilEndOfAllMoves(); // use only if neededthis to change the speed exactly at that point, but it may cause blobs if you do!
|
||
|
if(speed != pwm_pos[NUM_EXTRUDER + 2])
|
||
|
Com::printFLN(Com::tFanspeed,speed); // send only new values to break update loops!
|
||
|
pwm_pos[NUM_EXTRUDER + 2] = speed;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void Commands::reportPrinterUsage()
|
||
|
{
|
||
|
#if EEPROM_MODE!=0
|
||
|
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; i<NUM_EXTRUDER; i++)
|
||
|
if(tempController[i]->targetTemperatureC>15) alloff = false;
|
||
|
|
||
|
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::tSpaceHoursSpace,tmp);
|
||
|
Com::printFLN(Com::tSpaceMin);
|
||
|
#endif
|
||
|
}
|
||
|
#if STEPPER_CURRENT_CONTROL == CURRENT_CONTROL_DIGIPOT
|
||
|
// Digipot methods for controling current and microstepping
|
||
|
|
||
|
#if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
|
||
|
int digitalPotWrite(int address, unsigned int value) // From Arduino DigitalPotControl example
|
||
|
{
|
||
|
WRITE(DIGIPOTSS_PIN,LOW); // take the SS pin low to select the chip
|
||
|
HAL::spiSend(address); // send in the address and value via SPI:
|
||
|
HAL::spiSend(value);
|
||
|
WRITE(DIGIPOTSS_PIN,HIGH); // take the SS pin high to de-select the chip:
|
||
|
//delay(10);
|
||
|
}
|
||
|
|
||
|
void setMotorCurrent(uint8_t driver, unsigned int current)
|
||
|
{
|
||
|
const uint8_t digipot_ch[] = DIGIPOT_CHANNELS;
|
||
|
digitalPotWrite(digipot_ch[driver], current);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void motorCurrentControlInit() //Initialize Digipot Motor Current
|
||
|
{
|
||
|
#if DIGIPOTSS_PIN && DIGIPOTSS_PIN > -1
|
||
|
const uint8_t digipot_motor_current[] = MOTOR_CURRENT;
|
||
|
|
||
|
HAL::spiInit(0); //SPI.begin();
|
||
|
SET_OUTPUT(DIGIPOTSS_PIN);
|
||
|
for(int i = 0; i <= 4; i++)
|
||
|
//digitalPotWrite(digipot_ch[i], digipot_motor_current[i]);
|
||
|
setMotorCurrent(i,digipot_motor_current[i]);
|
||
|
#endif
|
||
|
}
|
||
|
#endif
|
||
|
#if STEPPER_CURRENT_CONTROL==CURRENT_CONTROL_PWM
|
||
|
// Controlling motor current directly using PWM
|
||
|
//unsigned int motor_current_setting[3] = MOTOR_CURRENT_PWM; //unsigned int motor_current_setting[3] = DEFAULT_PWM_MOTOR_CURRENT;
|
||
|
|
||
|
void setMotorCurrent(uint8_t driver, unsigned int current)
|
||
|
{
|
||
|
if (driver == 0) analogWrite(MOTOR_CURRENT_PWM_XY_PIN, current); //if (driver == 0) analogWrite(MOTOR_CURRENT_PWM_XY_PIN, 50);
|
||
|
if (driver == 1) analogWrite(MOTOR_CURRENT_PWM_Z_PIN, current); //if (driver == 1) analogWrite(MOTOR_CURRENT_PWM_Z_PIN, 50);
|
||
|
if (driver == 2) analogWrite(MOTOR_CURRENT_PWM_E_PIN, current); //if (driver == 2) analogWrite(MOTOR_CURRENT_PWM_E_PIN, 50);
|
||
|
|
||
|
/* OLD for setting current on eris and/or droplit. Use motor currents in configuration.h now
|
||
|
#if PRINTER == 4
|
||
|
if (driver == 0) analogWrite(MOTOR_CURRENT_PWM_XY_PIN, 50);
|
||
|
if (driver == 1) analogWrite(MOTOR_CURRENT_PWM_Z_PIN, 50);
|
||
|
if (driver == 2) analogWrite(MOTOR_CURRENT_PWM_E_PIN, 50);
|
||
|
#else
|
||
|
if (driver == 0) analogWrite(MOTOR_CURRENT_PWM_XY_PIN, motor_current_setting[0]); //if (driver == 0) analogWrite(MOTOR_CURRENT_PWM_XY_PIN, 50);
|
||
|
if (driver == 1) analogWrite(MOTOR_CURRENT_PWM_Z_PIN, motor_current_setting[1]); //if (driver == 1) analogWrite(MOTOR_CURRENT_PWM_Z_PIN, 50);
|
||
|
if (driver == 2) analogWrite(MOTOR_CURRENT_PWM_E_PIN, motor_current_setting[2]); //if (driver == 2) analogWrite(MOTOR_CURRENT_PWM_E_PIN, 50);
|
||
|
#endif
|
||
|
*/
|
||
|
}
|
||
|
void motorCurrentControlInit() //Initialize Digipot Motor Current
|
||
|
{
|
||
|
#if defined MOTOR_CURRENT_PWM_XY_PIN //copied from Marlin
|
||
|
const uint8_t pwm_motor_current[] = MOTOR_CURRENT_PWM;
|
||
|
SET_OUTPUT(MOTOR_CURRENT_PWM_XY_PIN);
|
||
|
SET_OUTPUT(MOTOR_CURRENT_PWM_Z_PIN);
|
||
|
SET_OUTPUT(MOTOR_CURRENT_PWM_E_PIN);
|
||
|
setMotorCurrent(0, pwm_motor_current[0]);
|
||
|
setMotorCurrent(1, pwm_motor_current[1]);
|
||
|
setMotorCurrent(2, pwm_motor_current[2]);
|
||
|
//Set timer5 to 31khz so the PWM of the motor power is as constant as possible. (removes a buzzing noise)
|
||
|
TCCR5B = (TCCR5B & ~(_BV(CS50) | _BV(CS51) | _BV(CS52))) | _BV(CS50);
|
||
|
#endif
|
||
|
}
|
||
|
#endif
|
||
|
#if STEPPER_CURRENT_CONTROL==CURRENT_CONTROL_LTC2600
|
||
|
|
||
|
void setMotorCurrent( uint8_t channel, unsigned short level )
|
||
|
{
|
||
|
const uint8_t ltc_channels[] = LTC2600_CHANNELS;
|
||
|
if(channel > LTC2600_NUM_CHANNELS) return;
|
||
|
uint8_t address = ltc_channels[channel];
|
||
|
char i;
|
||
|
|
||
|
|
||
|
// NOTE: Do not increase the current endlessly. In case the engine reaches its current saturation, the engine and the driver can heat up and loss power.
|
||
|
// When the saturation is reached, more current causes more heating and more power loss.
|
||
|
// In case of engines with lower quality, the saturation current may be reached before the nominal current.
|
||
|
|
||
|
// configure the pins
|
||
|
WRITE( LTC2600_CS_PIN, HIGH );
|
||
|
SET_OUTPUT( LTC2600_CS_PIN );
|
||
|
WRITE( LTC2600_SCK_PIN, LOW );
|
||
|
SET_OUTPUT( LTC2600_SCK_PIN );
|
||
|
WRITE( LTC2600_SDI_PIN, LOW );
|
||
|
SET_OUTPUT( LTC2600_SDI_PIN );
|
||
|
|
||
|
// enable the command interface of the LTC2600
|
||
|
WRITE( LTC2600_CS_PIN, LOW );
|
||
|
|
||
|
// transfer command and address
|
||
|
for( i = 7; i >= 0; i-- )
|
||
|
{
|
||
|
WRITE( LTC2600_SDI_PIN, address & (0x01 << i));
|
||
|
WRITE( LTC2600_SCK_PIN, 1 );
|
||
|
WRITE( LTC2600_SCK_PIN, 0 );
|
||
|
}
|
||
|
|
||
|
// transfer the data word
|
||
|
for( i = 15; i >= 0; i-- )
|
||
|
{
|
||
|
WRITE( LTC2600_SDI_PIN, level & (0x01 << i));
|
||
|
WRITE( LTC2600_SCK_PIN, 1 );
|
||
|
WRITE( LTC2600_SCK_PIN, 0 );
|
||
|
}
|
||
|
|
||
|
// disable the ommand interface of the LTC2600 -
|
||
|
// this carries out the specified command
|
||
|
WRITE( LTC2600_CS_PIN, HIGH );
|
||
|
|
||
|
} // setLTC2600
|
||
|
|
||
|
void motorCurrentControlInit() //Initialize LTC2600 Motor Current
|
||
|
{
|
||
|
const unsigned int ltc_current[] = MOTOR_CURRENT;
|
||
|
uint8_t i;
|
||
|
for(i=0; i<LTC2600_NUM_CHANNELS; i++)
|
||
|
{
|
||
|
setMotorCurrent(i, ltc_current[i] );
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if defined(X_MS1_PIN) && X_MS1_PIN > -1
|
||
|
void microstepMS(uint8_t driver, int8_t ms1, int8_t ms2)
|
||
|
{
|
||
|
if(ms1 > -1) switch(driver)
|
||
|
{
|
||
|
case 0:
|
||
|
WRITE( X_MS1_PIN,ms1);
|
||
|
break;
|
||
|
case 1:
|
||
|
WRITE( Y_MS1_PIN,ms1);
|
||
|
break;
|
||
|
case 2:
|
||
|
WRITE( Z_MS1_PIN,ms1);
|
||
|
break;
|
||
|
case 3:
|
||
|
WRITE(E0_MS1_PIN,ms1);
|
||
|
break;
|
||
|
case 4:
|
||
|
WRITE(E1_MS1_PIN,ms1);
|
||
|
break;
|
||
|
}
|
||
|
if(ms2 > -1) switch(driver)
|
||
|
{
|
||
|
case 0:
|
||
|
WRITE( X_MS2_PIN,ms2);
|
||
|
break;
|
||
|
case 1:
|
||
|
WRITE( Y_MS2_PIN,ms2);
|
||
|
break;
|
||
|
case 2:
|
||
|
WRITE( Z_MS2_PIN,ms2);
|
||
|
break;
|
||
|
case 3:
|
||
|
WRITE(E0_MS2_PIN,ms2);
|
||
|
break;
|
||
|
case 4:
|
||
|
WRITE(E1_MS2_PIN,ms2);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void microstepMode(uint8_t driver, uint8_t stepping_mode)
|
||
|
{
|
||
|
switch(stepping_mode)
|
||
|
{
|
||
|
case 1:
|
||
|
microstepMS(driver,MICROSTEP1);
|
||
|
break;
|
||
|
case 2:
|
||
|
microstepMS(driver,MICROSTEP2);
|
||
|
break;
|
||
|
case 4:
|
||
|
microstepMS(driver,MICROSTEP4);
|
||
|
break;
|
||
|
case 8:
|
||
|
microstepMS(driver,MICROSTEP8);
|
||
|
break;
|
||
|
case 16:
|
||
|
microstepMS(driver,MICROSTEP16);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
void microstepReadings()
|
||
|
{
|
||
|
Com::printFLN(Com::tMS1MS2Pins);
|
||
|
Com::printF(Com::tXColon,READ(X_MS1_PIN));
|
||
|
Com::printFLN(Com::tComma,READ(X_MS2_PIN));
|
||
|
Com::printF(Com::tYColon,READ(Y_MS1_PIN));
|
||
|
Com::printFLN(Com::tComma,READ(Y_MS2_PIN));
|
||
|
Com::printF(Com::tZColon,READ(Z_MS1_PIN));
|
||
|
Com::printFLN(Com::tComma,READ(Z_MS2_PIN));
|
||
|
Com::printF(Com::tE0Colon,READ(E0_MS1_PIN));
|
||
|
Com::printFLN(Com::tComma,READ(E0_MS2_PIN));
|
||
|
Com::printF(Com::tE1Colon,READ(E1_MS1_PIN));
|
||
|
Com::printFLN(Com::tComma,READ(E1_MS2_PIN));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void microstepInit()
|
||
|
{
|
||
|
#if defined(X_MS1_PIN) && X_MS1_PIN > -1
|
||
|
const uint8_t microstep_modes[] = MICROSTEP_MODES;
|
||
|
SET_OUTPUT(X_MS2_PIN);
|
||
|
SET_OUTPUT(Y_MS2_PIN);
|
||
|
SET_OUTPUT(Z_MS2_PIN);
|
||
|
SET_OUTPUT(E0_MS2_PIN);
|
||
|
SET_OUTPUT(E1_MS2_PIN);
|
||
|
for(int i=0; i<=4; i++) microstepMode(i,microstep_modes[i]);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief Execute the Arc command stored in com.
|
||
|
*/
|
||
|
#if ARC_SUPPORT
|
||
|
void Commands::processArc(GCode *com)
|
||
|
{
|
||
|
float position[Z_AXIS_ARRAY];
|
||
|
Printer::realPosition(position[X_AXIS],position[Y_AXIS],position[Z_AXIS]);
|
||
|
if(!Printer::setDestinationStepsFromGCode(com)) return; // For X Y Z E F
|
||
|
float offset[2] = {Printer::convertToMM(com->hasI() ? com->I : 0),Printer::convertToMM(com->hasJ() ? com->J : 0)};
|
||
|
float target[E_AXIS_ARRAY] = {Printer::realXPosition(),Printer::realYPosition(),Printer::realZPosition(),Printer::destinationSteps[E_AXIS]*Printer::invAxisStepsPerMM[E_AXIS]};
|
||
|
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.
|
||
|
|
||
|
|
||
|
T <-- Target position
|
||
|
|
||
|
^
|
||
|
Clockwise circles with this center | Clockwise circles with this center will have
|
||
|
will have > 180 deg of angular travel | < 180 deg of angular travel, which is a good thing!
|
||
|
\ | /
|
||
|
center of arc when h_x2_div_d is positive -> x <----- | -----> x <- center of arc when h_x2_div_d is negative
|
||
|
|
|
||
|
|
|
||
|
|
||
|
C <-- Current position */
|
||
|
|
||
|
|
||
|
// Negative R is g-code-alese 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 unadvisably 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[0] = 0.5*(x-(y*h_x2_div_d));
|
||
|
offset[1] = 0.5*(y+(x*h_x2_div_d));
|
||
|
|
||
|
}
|
||
|
else // Offset mode specific computations
|
||
|
{
|
||
|
r = hypot(offset[0], offset[1]); // Compute arc radius for arc
|
||
|
}
|
||
|
// 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 G command stored in com.
|
||
|
*/
|
||
|
void Commands::processGCode(GCode *com)
|
||
|
{
|
||
|
uint32_t codenum; //throw away variable
|
||
|
switch(com->G)
|
||
|
{
|
||
|
case 0: // G0 -> G1
|
||
|
case 1: // G1
|
||
|
if(com->hasS()) Printer::setNoDestinationCheck(com->S != 0);
|
||
|
if(Printer::setDestinationStepsFromGCode(com)) // For X Y Z E F
|
||
|
#if NONLINEAR_SYSTEM
|
||
|
if (!PrintLine::queueDeltaMove(ALWAYS_CHECK_ENDSTOPS, true, true))
|
||
|
{
|
||
|
Com::printWarningFLN(PSTR("executeGCode / queueDeltaMove returns error"));
|
||
|
}
|
||
|
#else
|
||
|
PrintLine::queueCartesianMove(ALWAYS_CHECK_ENDSTOPS, true);
|
||
|
#endif
|
||
|
#if UI_HAS_KEYS
|
||
|
// ui can only execute motion commands if we are not waiting inside a move for an
|
||
|
// old move to finish. For normal response times, we always leave one free after
|
||
|
// sending a line. Drawback: 1 buffer line less for limited time. Since input cache
|
||
|
// gets filled while waiting, the lost is neglectible.
|
||
|
PrintLine::waitForXFreeLines(1, true);
|
||
|
#endif // UI_HAS_KEYS
|
||
|
break;
|
||
|
#if ARC_SUPPORT
|
||
|
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();
|
||
|
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 )
|
||
|
{
|
||
|
GCode::readFromSerial();
|
||
|
Commands::checkForPeriodicalActions(true);
|
||
|
}
|
||
|
break;
|
||
|
#if FEATURE_RETRACTION && NUM_EXTRUDER > 0
|
||
|
case 10: // G10 S<1 = long retract, 0 = short retract = default> retracts filament accoridng to stored setting
|
||
|
#if NUM_EXTRUDER > 1
|
||
|
Extruder::current->retract(true, com->hasS() && com->S > 0);
|
||
|
#else
|
||
|
Extruder::current->retract(true, false);
|
||
|
#endif
|
||
|
break;
|
||
|
case 11: // G11 S<1 = long retract, 0 = short retract = default> = Undo retraction according to stored setting
|
||
|
#if NUM_EXTRUDER > 1
|
||
|
Extruder::current->retract(false, com->hasS() && com->S > 0);
|
||
|
#else
|
||
|
Extruder::current->retract(false, false);
|
||
|
#endif
|
||
|
break;
|
||
|
#endif // FEATURE_RETRACTION
|
||
|
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 Axis one at a time
|
||
|
{
|
||
|
uint8_t homeAllAxis = (com->hasNoXYZ() && !com->hasE());
|
||
|
if(com->hasE())
|
||
|
Printer::currentPositionSteps[E_AXIS] = 0;
|
||
|
if(homeAllAxis || !com->hasNoXYZ())
|
||
|
Printer::homeAxis(homeAllAxis || com->hasX(),homeAllAxis || com->hasY(),homeAllAxis || com->hasZ());
|
||
|
Printer::updateCurrentPosition();
|
||
|
if(Printer::isXMaxEndstopHit() || Printer::isYMaxEndstopHit() || Printer::isZMaxEndstopHit()){
|
||
|
GCode::executeFString(PSTR("M117 ENDSTOP ERROR"));
|
||
|
Com::printF(PSTR("Error: "));
|
||
|
if(Printer::isXMaxEndstopHit()) Com::printF(PSTR("X "));
|
||
|
if(Printer::isYMaxEndstopHit()) Com::printF(PSTR("Y "));
|
||
|
if(Printer::isZMaxEndstopHit()) Com::printF(PSTR("Z "));
|
||
|
Com::printFLN(PSTR("Endstop(s) not working properly"));
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
#if FEATURE_Z_PROBE
|
||
|
case 29: // G29 Probe for Endstop Offsets, Horizontal Radius, and Z Height
|
||
|
{
|
||
|
if(!accelerometer_status()){
|
||
|
delay(250);
|
||
|
if(!accelerometer_status()) {
|
||
|
Com::printFLN(PSTR("I2C Error - Calibration Aborted"));
|
||
|
GCode::executeFString(PSTR("M117 I2C Error. Aborting"));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
GCode::executeFString(PSTR("M104 S0\nM140 S0\nM107"));
|
||
|
float xProbe = 0, yProbe = 0, zProbe = 0, verify = 0, oldFeedrate = Printer::feedrate;
|
||
|
int32_t probeSensitivity = Z_PROBE_SENSITIVITY;
|
||
|
bool failedProbe = false;
|
||
|
EEPROM::setDeltaTowerXOffsetSteps(0); // set X offset to 0
|
||
|
EEPROM::setDeltaTowerYOffsetSteps(0); // set Y offset to 0
|
||
|
EEPROM::setDeltaTowerZOffsetSteps(0); // set Z offset to 0
|
||
|
EEPROM::storeDataIntoEEPROM(); // store offsets to 0 before doing anything
|
||
|
EEPROM::readDataFromEEPROM();
|
||
|
|
||
|
//Crank up the max Z accel for the Eris
|
||
|
#if PRINTER == 3
|
||
|
Printer::maxTravelAccelerationMMPerSquareSecond[Z_AXIS] = 1850;
|
||
|
Printer::updateDerivedParameter();
|
||
|
#endif
|
||
|
|
||
|
do{
|
||
|
Printer::homeAxis(true,true,true);
|
||
|
if(Printer::isXMaxEndstopHit() || Printer::isYMaxEndstopHit() || Printer::isZMaxEndstopHit()){
|
||
|
GCode::executeFString(PSTR("M117 ENDSTOP ERROR"));
|
||
|
Com::printF(PSTR("Error: "));
|
||
|
if(Printer::isXMaxEndstopHit()) Com::printF(PSTR("X "));
|
||
|
if(Printer::isYMaxEndstopHit()) Com::printF(PSTR("Y "));
|
||
|
if(Printer::isZMaxEndstopHit()) Com::printF(PSTR("Z "));
|
||
|
Com::printFLN(PSTR("Endstop(s) not working properly"));
|
||
|
failedProbe = true;
|
||
|
break;
|
||
|
}
|
||
|
GCode::executeFString(Com::tZProbeStartScript);
|
||
|
Printer::setAutolevelActive(false);
|
||
|
Printer::moveTo(EEPROM::zProbeX1(),EEPROM::zProbeY1(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
xProbe = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false); //First tap
|
||
|
verify = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false); //Second tap
|
||
|
if ((xProbe - verify) > Z_PROBE_TOLERANCE || (xProbe - verify) < - Z_PROBE_TOLERANCE){ //tap reports distance, if more or less than .1mm, it will re-run
|
||
|
Com::printFLN(PSTR("Z probe (X Tower) failed on sensitivity: "), probeSensitivity );
|
||
|
if(probeSensitivity < Z_PROBE_MAX_SENSITIVITY){
|
||
|
accelerometer_recv(0x32);
|
||
|
probeSensitivity+=2;
|
||
|
Com::printFLN(PSTR("Setting Probe Sensitivity To:"), probeSensitivity );
|
||
|
accelerometer_write(0x32,uint8_t(probeSensitivity)); //INT1 THRESHOLD
|
||
|
accelerometer_write(0x3A,uint8_t(probeSensitivity)); //CLICK THRESHOLD
|
||
|
accelerometer_recv(0x32);
|
||
|
}else{
|
||
|
Com::printFLN(PSTR("Calibration Failed"));
|
||
|
GCode::executeFString(PSTR("M117 CALIBRATION FAILED"));
|
||
|
Com::printErrorFLN(Com::tZProbeFailed);
|
||
|
break;
|
||
|
}
|
||
|
xProbe = -1; failedProbe = true;
|
||
|
continue;
|
||
|
}else{
|
||
|
xProbe = (xProbe + verify) / 2;
|
||
|
}
|
||
|
int32_t offsetX = ((xProbe * AXIS_STEPS_PER_MM) - (Z_PROBE_BED_DISTANCE * AXIS_STEPS_PER_MM)), offsetStepsX = EEPROM::deltaTowerXOffsetSteps();
|
||
|
|
||
|
if(com->hasS() && com->S == 2){
|
||
|
Printer::homeAxis(true,true,true);
|
||
|
GCode::executeFString(Com::tZProbeStartScript);
|
||
|
Printer::setAutolevelActive(false);
|
||
|
}
|
||
|
Printer::moveTo(EEPROM::zProbeX2(),EEPROM::zProbeY2(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
yProbe = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false); //First tap
|
||
|
verify = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false); //Second tap
|
||
|
if ((yProbe - verify) > Z_PROBE_TOLERANCE || (yProbe - verify) < - Z_PROBE_TOLERANCE){ //tap reports distance, if more or less than .1mm, it will re-run
|
||
|
Com::printFLN(PSTR("Z probe (Y Tower) failed on sensitivity: "), probeSensitivity );
|
||
|
if(probeSensitivity < Z_PROBE_MAX_SENSITIVITY){
|
||
|
accelerometer_recv(0x32);
|
||
|
probeSensitivity+=2;
|
||
|
Com::printFLN(PSTR("Setting Probe Sensitivity To:"), probeSensitivity );
|
||
|
accelerometer_write(0x32,uint8_t(probeSensitivity)); //INT1 THRESHOLD
|
||
|
accelerometer_write(0x3A,uint8_t(probeSensitivity)); //CLICK THRESHOLD
|
||
|
accelerometer_recv(0x32);
|
||
|
}else{
|
||
|
Com::printFLN(PSTR("Calibration Failed"));
|
||
|
GCode::executeFString(PSTR("M117 CALIBRATION FAILED"));
|
||
|
Com::printErrorFLN(Com::tZProbeFailed);
|
||
|
break;
|
||
|
}
|
||
|
yProbe = -1; failedProbe = true;
|
||
|
continue;
|
||
|
}else{
|
||
|
yProbe = (yProbe + verify) / 2;
|
||
|
}
|
||
|
int32_t offsetY = ((yProbe * AXIS_STEPS_PER_MM) - (Z_PROBE_BED_DISTANCE * AXIS_STEPS_PER_MM)), offsetStepsY = EEPROM::deltaTowerYOffsetSteps();
|
||
|
|
||
|
if(com->hasS() && com->S == 2){
|
||
|
Printer::homeAxis(true,true,true);
|
||
|
GCode::executeFString(Com::tZProbeStartScript);
|
||
|
Printer::setAutolevelActive(false);
|
||
|
}
|
||
|
Printer::moveTo(EEPROM::zProbeX3(),EEPROM::zProbeY3(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
zProbe = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false); //First tap
|
||
|
verify = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false); //Second tap
|
||
|
if ((zProbe - verify) > Z_PROBE_TOLERANCE || (zProbe - verify) < - Z_PROBE_TOLERANCE){ //tap reports distance, if more or less than .1mm, it will re-run
|
||
|
Com::printFLN(PSTR("Z probe (Z Tower) failed on sensitivity: "), probeSensitivity );
|
||
|
if(probeSensitivity < Z_PROBE_MAX_SENSITIVITY){
|
||
|
accelerometer_recv(0x32);
|
||
|
probeSensitivity+=2;
|
||
|
Com::printFLN(PSTR("Setting Probe Sensitivity To:"), probeSensitivity );
|
||
|
accelerometer_write(0x32,uint8_t(probeSensitivity)); //INT1 THRESHOLD
|
||
|
accelerometer_write(0x3A,uint8_t(probeSensitivity)); //CLICK THRESHOLD
|
||
|
accelerometer_recv(0x32);
|
||
|
}else{
|
||
|
Com::printFLN(PSTR("Calibration Failed"));
|
||
|
GCode::executeFString(PSTR("M117 CALIBRATION FAILED"));
|
||
|
Com::printErrorFLN(Com::tZProbeFailed);
|
||
|
break;
|
||
|
}
|
||
|
zProbe = -1; failedProbe = true;
|
||
|
continue;
|
||
|
}else{
|
||
|
zProbe = (zProbe + verify) / 2;
|
||
|
}
|
||
|
int32_t offsetZ = ((zProbe * AXIS_STEPS_PER_MM) - (Z_PROBE_BED_DISTANCE * AXIS_STEPS_PER_MM)), offsetStepsZ = EEPROM::deltaTowerZOffsetSteps();
|
||
|
|
||
|
Printer::updateCurrentPosition();
|
||
|
Printer::updateDerivedParameter();
|
||
|
Com::printInfoFLN(Com::tZProbeZReset);
|
||
|
Com::printFLN(Com::tZProbePrinterHeight,Printer::zLength);
|
||
|
Printer::feedrate = oldFeedrate;
|
||
|
|
||
|
if(offsetX < offsetY && offsetX < offsetZ)
|
||
|
{
|
||
|
offsetY = offsetStepsY + (offsetY - offsetX);
|
||
|
offsetZ = offsetStepsZ + (offsetZ - offsetX);
|
||
|
offsetX = 0;
|
||
|
}
|
||
|
else if(offsetY < offsetX && offsetY < offsetZ)
|
||
|
{
|
||
|
offsetX = offsetStepsX + (offsetX - offsetY);
|
||
|
offsetZ = offsetStepsZ + (offsetZ - offsetY);
|
||
|
offsetY = 0;
|
||
|
}
|
||
|
else if(offsetZ < offsetX && offsetZ < offsetY)
|
||
|
{
|
||
|
offsetX = offsetStepsX + (offsetX - offsetZ);
|
||
|
offsetY = offsetStepsY + (offsetY - offsetZ);
|
||
|
offsetZ = 0;
|
||
|
}
|
||
|
if(offsetX > 400 || offsetY > 400 || offsetZ > 400){
|
||
|
xProbe = -1; yProbe = -1; zProbe = -1;
|
||
|
Com::printFLN(PSTR("OFFSETS OFF BY TOO MUCH. Aborting. Sensitivity: "), probeSensitivity);
|
||
|
GCode::executeFString(PSTR("M117 Endstop Offset Error"));
|
||
|
Com::printFLN(PSTR("X: "), offsetX);
|
||
|
Com::printFLN(PSTR("Y: "), offsetY);
|
||
|
Com::printFLN(PSTR("Z: "), offsetZ);
|
||
|
failedProbe = true;
|
||
|
break;
|
||
|
}else{
|
||
|
EEPROM::setDeltaTowerXOffsetSteps(offsetX);
|
||
|
EEPROM::setDeltaTowerYOffsetSteps(offsetY);
|
||
|
EEPROM::setDeltaTowerZOffsetSteps(offsetZ);
|
||
|
EEPROM::storeDataIntoEEPROM();
|
||
|
failedProbe = false;
|
||
|
}
|
||
|
}while(failedProbe);
|
||
|
|
||
|
if(failedProbe) break;
|
||
|
Printer::updateCurrentPosition(true);
|
||
|
Printer::feedrate = oldFeedrate;
|
||
|
printCurrentPosition(PSTR("G69 "));
|
||
|
GCode::executeFString(Com::tZProbeEndScript);
|
||
|
|
||
|
//Horizontal Radius Calc and Z Height
|
||
|
float cProbe, hradius;
|
||
|
#if PRINTER == 5
|
||
|
float defaultRadius = 144.0;
|
||
|
#else
|
||
|
float defaultRadius = PRINTER_RADIUS-END_EFFECTOR_HORIZONTAL_OFFSET-CARRIAGE_HORIZONTAL_OFFSET;
|
||
|
#endif
|
||
|
float oldRadius;
|
||
|
int radiusLoop;
|
||
|
radiusLoop = 0;
|
||
|
|
||
|
do{
|
||
|
radiusLoop++;
|
||
|
oldRadius = Printer::radius0;
|
||
|
failedProbe = false;
|
||
|
EEPROM::storeDataIntoEEPROM(); //save firmware horizontal radius before calibration
|
||
|
EEPROM::readDataFromEEPROM();
|
||
|
Printer::setAutolevelActive(true);
|
||
|
Printer::homeAxis(true,true,true);
|
||
|
Printer::setAutolevelActive(false);
|
||
|
GCode::executeFString(Com::tZProbeStartScript);
|
||
|
Printer::moveTo(0,0,IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
cProbe = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false);
|
||
|
verify = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false);
|
||
|
if ((cProbe - verify) > Z_PROBE_TOLERANCE || (cProbe - verify) < - Z_PROBE_TOLERANCE){ //tap reports distance, if more or less than .1mm, it will re-run
|
||
|
Com::printFLN(PSTR("Z probe (HR - Center Point) failed on sensitivity: "), probeSensitivity );
|
||
|
if(probeSensitivity < Z_PROBE_MAX_SENSITIVITY){
|
||
|
accelerometer_recv(0x32);
|
||
|
probeSensitivity+=2;
|
||
|
radiusLoop--;
|
||
|
Com::printFLN(PSTR("Setting Probe Sensitivity To:"), probeSensitivity );
|
||
|
accelerometer_write(0x32,uint8_t(probeSensitivity)); //INT1 THRESHOLD
|
||
|
accelerometer_write(0x3A,uint8_t(probeSensitivity)); //CLICK THRESHOLD
|
||
|
accelerometer_recv(0x32);
|
||
|
}else{
|
||
|
Com::printFLN(PSTR("Calibration Failed"));
|
||
|
GCode::executeFString(PSTR("M117 CALIBRATION FAILED"));
|
||
|
Com::printErrorFLN(Com::tZProbeFailed);
|
||
|
break;
|
||
|
}
|
||
|
cProbe = -1; failedProbe = true;
|
||
|
continue;
|
||
|
}else{
|
||
|
cProbe = (cProbe + verify) / 2;
|
||
|
Com::printFLN(PSTR("Old Z Height:"), Printer::zLength );
|
||
|
Printer::zLength += cProbe - Printer::currentPosition[Z_AXIS];
|
||
|
Printer::updateDerivedParameter();
|
||
|
Com::printFLN(PSTR("New Z Height:"), Printer::zLength );
|
||
|
}
|
||
|
|
||
|
Printer::moveTo(EEPROM::zProbeX3(),EEPROM::zProbeY3(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
zProbe = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false);
|
||
|
verify = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false);
|
||
|
if ((zProbe - verify) > Z_PROBE_TOLERANCE || (zProbe - verify) < - Z_PROBE_TOLERANCE){ //tap reports distance, if more or less than .1mm, it will re-run
|
||
|
Com::printFLN(PSTR("Z probe (HR - Z tower) failed on sensitivity: "), probeSensitivity );
|
||
|
if(probeSensitivity < Z_PROBE_MAX_SENSITIVITY){
|
||
|
accelerometer_recv(0x32);
|
||
|
probeSensitivity+=2;
|
||
|
Com::printFLN(PSTR("Setting Probe Sensitivity To:"), probeSensitivity );
|
||
|
accelerometer_write(0x32,uint8_t(probeSensitivity)); //INT1 THRESHOLD
|
||
|
accelerometer_write(0x3A,uint8_t(probeSensitivity)); //CLICK THRESHOLD
|
||
|
accelerometer_recv(0x32);
|
||
|
}else{
|
||
|
Com::printFLN(PSTR("Calibration Failed"));
|
||
|
GCode::executeFString(PSTR("M117 CALIBRATION FAILED"));
|
||
|
Com::printErrorFLN(Com::tZProbeFailed);
|
||
|
break;
|
||
|
}
|
||
|
zProbe = -1; failedProbe = true;
|
||
|
continue;
|
||
|
}else{
|
||
|
zProbe = (zProbe + verify) / 2;
|
||
|
}
|
||
|
|
||
|
hradius = (cProbe - zProbe)*AXIS_STEPS_PER_MM;
|
||
|
if(hradius<0)
|
||
|
{
|
||
|
hradius=-hradius;
|
||
|
hradius = (hradius / Printer::radius0)*2;
|
||
|
Com::printFLN(Com::tZProbeAverage,hradius);
|
||
|
Printer::radius0 = Printer::radius0 - hradius;
|
||
|
}else{
|
||
|
hradius = (hradius / Printer::radius0)*2;
|
||
|
Printer::radius0 = Printer::radius0 + hradius;
|
||
|
}
|
||
|
|
||
|
if(Printer::radius0 / defaultRadius > 1.1 || Printer::radius0 / defaultRadius < 0.9){
|
||
|
Com::printFLN(PSTR("Calculated Radius is bad: "), Printer::radius0 );
|
||
|
Printer::radius0 = defaultRadius;
|
||
|
}
|
||
|
Com::printFLN(PSTR("Old Horizontal Radius: "), oldRadius );
|
||
|
Com::printFLN(PSTR("New Horizontal Radius: "), Printer::radius0 );
|
||
|
}while(radiusLoop < 4 && (failedProbe || ((Printer::radius0 - oldRadius) > Z_PROBE_TOLERANCE) || ((Printer::radius0 - oldRadius) < -Z_PROBE_TOLERANCE) ));
|
||
|
|
||
|
//Reset the max Z accel for the Eris
|
||
|
#if PRINTER == 3
|
||
|
Printer::maxTravelAccelerationMMPerSquareSecond[Z_AXIS] = 400;
|
||
|
Printer::updateDerivedParameter();
|
||
|
#endif
|
||
|
Printer::setAutolevelActive(true);
|
||
|
Printer::updateCurrentPosition(true);
|
||
|
printCurrentPosition(PSTR("hehe"));
|
||
|
GCode::executeFString(Com::tZProbeEndScript);
|
||
|
Printer::feedrate = oldFeedrate;
|
||
|
Printer::homeAxis(true,true,true);
|
||
|
EEPROM::storeDataIntoEEPROM();
|
||
|
#if SDSUPPORT == 1
|
||
|
if(sd.selectFile("g29cal.gcode", true)){
|
||
|
sd.stopPrint();
|
||
|
sd.deleteFile("g29cal.gcode");
|
||
|
sd.initsd();
|
||
|
}
|
||
|
#endif
|
||
|
GCode::executeFString(PSTR("M117 CALIBRATION COMPLETE"));
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 30: // G30 single probe set Z0
|
||
|
{
|
||
|
if(com->hasS() && com->S == 2){
|
||
|
float sum = 0, sum1 = 0,last,oldFeedrate = Printer::feedrate;
|
||
|
do{
|
||
|
if(com->hasS() && com->S == 2){ // only reset eeprom if saving new value
|
||
|
Printer::zLength = Z_MAX_LENGTH; // set Z height to firmware default
|
||
|
EEPROM::storeDataIntoEEPROM(); // store default before calibration
|
||
|
EEPROM::readDataFromEEPROM(); // would not take effect unless read!
|
||
|
}
|
||
|
Printer::homeAxis(true,true,true);
|
||
|
GCode::executeFString(Com::tZProbeStartScript);
|
||
|
Printer::setAutolevelActive(false);
|
||
|
Printer::moveTo(0,0,IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
sum1 = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false); // First tap
|
||
|
sum = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false); // Second tap
|
||
|
if ((sum1 - sum) > Z_PROBE_TOLERANCE || (sum1 - sum) < - Z_PROBE_TOLERANCE){ //tap reports distance, if more or less than .1mm, it will re-run
|
||
|
Com::printErrorFLN(Com::tZProbeFailed);
|
||
|
sum = -1;
|
||
|
}else{
|
||
|
sum = (sum + sum1) / 2;
|
||
|
}
|
||
|
}while(sum < 1);
|
||
|
if(com->hasS() && com->S)
|
||
|
{
|
||
|
Printer::zLength += sum - Printer::currentPosition[Z_AXIS];
|
||
|
Printer::updateDerivedParameter();
|
||
|
}
|
||
|
Printer::feedrate = oldFeedrate;
|
||
|
Printer::setAutolevelActive(true);
|
||
|
if(com->hasS() && com->S == 2)
|
||
|
EEPROM::storeDataIntoEEPROM();
|
||
|
Printer::updateCurrentPosition(true);
|
||
|
printCurrentPosition(PSTR("G30 "));
|
||
|
GCode::executeFString(Com::tZProbeEndScript);
|
||
|
Printer::feedrate = oldFeedrate;
|
||
|
Printer::homeAxis(true,true,true);
|
||
|
}else{
|
||
|
/*
|
||
|
if(com->hasP() && com->P >= 10){
|
||
|
for(int i=0;i<10;i++){
|
||
|
Com::printF(PSTR("Point "), i);
|
||
|
Com::printFLN(PSTR(" - PROBE OFFSET:"), probes[i] );
|
||
|
}
|
||
|
}else{
|
||
|
*/
|
||
|
#if PRINTER == 3
|
||
|
Printer::maxTravelAccelerationMMPerSquareSecond[Z_AXIS] = 1850;
|
||
|
Printer::updateDerivedParameter();
|
||
|
#endif
|
||
|
float pProbe, verify;
|
||
|
int32_t probeSensitivity = Z_PROBE_SENSITIVITY;
|
||
|
if(com->hasX() && com->hasY()){
|
||
|
if(com->hasF()){ Printer::moveTo(com->X,com->Y,IGNORE_COORDINATE,IGNORE_COORDINATE,com->F); }
|
||
|
else{ Printer::moveTo(com->X,com->Y,IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed()); }
|
||
|
}
|
||
|
pProbe = Printer::runZProbe(true,false,1,false);
|
||
|
pProbe -= Printer::currentPosition[Z_AXIS];
|
||
|
verify = Printer::runZProbe(false,true,1,false);
|
||
|
verify -= Printer::currentPosition[Z_AXIS];
|
||
|
if ((pProbe - verify) > Z_PROBE_TOLERANCE || (pProbe - verify) < - Z_PROBE_TOLERANCE){
|
||
|
Com::printFLN(PSTR("Probes do not match. Off by "), (pProbe - verify) );
|
||
|
if(probeSensitivity < Z_PROBE_MAX_SENSITIVITY){
|
||
|
accelerometer_recv(0x32);
|
||
|
probeSensitivity+=2;
|
||
|
Com::printFLN(PSTR("Setting Probe Sensitivity To:"), probeSensitivity );
|
||
|
accelerometer_write(0x32,uint8_t(probeSensitivity)); //INT1 THRESHOLD
|
||
|
accelerometer_write(0x3A,uint8_t(probeSensitivity)); //CLICK THRESHOLD
|
||
|
accelerometer_recv(0x32);
|
||
|
GCode::executeFString(PSTR("G30"));
|
||
|
}
|
||
|
}else{
|
||
|
pProbe = (pProbe + verify) / 2;
|
||
|
//if(com->hasP()){
|
||
|
// if(com->P < 10){ probes[com->P] = pProbe; }
|
||
|
//}else{
|
||
|
Com::printFLN(PSTR("PROBE-ZOFFSET:"), pProbe );
|
||
|
//}
|
||
|
}
|
||
|
#if PRINTER == 3
|
||
|
Printer::maxTravelAccelerationMMPerSquareSecond[Z_AXIS] = 400;
|
||
|
Printer::updateDerivedParameter();
|
||
|
#endif
|
||
|
//}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case 31: // G31 display hall sensor output
|
||
|
Com::printF(Com::tZProbeState);
|
||
|
Com::print(Printer::isZProbeHit() ? 'H' : 'L');
|
||
|
Com::println();
|
||
|
break;
|
||
|
#if FEATURE_AUTOLEVEL
|
||
|
case 32: // G32 Auto-Bed leveling
|
||
|
{
|
||
|
GCode::executeFString(Com::tZProbeStartScript);
|
||
|
//bool iterate = com->hasP() && com->P>0;
|
||
|
Printer::coordinateOffset[X_AXIS] = Printer::coordinateOffset[Y_AXIS] = Printer::coordinateOffset[Z_AXIS] = 0;
|
||
|
Printer::setAutolevelActive(false); // iterate
|
||
|
float h1,h2,h3,hc,oldFeedrate = Printer::feedrate;
|
||
|
Printer::moveTo(EEPROM::zProbeX1(),EEPROM::zProbeY1(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
h1 = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false);
|
||
|
if(h1 < 0) break;
|
||
|
Printer::moveTo(EEPROM::zProbeX2(),EEPROM::zProbeY2(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
h2 = Printer::runZProbe(false,false);
|
||
|
if(h2 < 0) break;
|
||
|
Printer::moveTo(EEPROM::zProbeX3(),EEPROM::zProbeY3(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
h3 = Printer::runZProbe(false,true);
|
||
|
if(h3 < 0) break;
|
||
|
Printer::buildTransformationMatrix(h1,h2,h3);
|
||
|
//-(Rxx*Ryz*y-Rxz*Ryx*y+(Rxz*Ryy-Rxy*Ryz)*x)/(Rxy*Ryx-Rxx*Ryy)
|
||
|
// z = z-deviation from origin due to bed transformation
|
||
|
float z = -((Printer::autolevelTransformation[0] * Printer::autolevelTransformation[5] -
|
||
|
Printer::autolevelTransformation[2] * Printer::autolevelTransformation[3]) *
|
||
|
(float)Printer::currentPositionSteps[Y_AXIS] * Printer::invAxisStepsPerMM[Y_AXIS] +
|
||
|
(Printer::autolevelTransformation[2] * Printer::autolevelTransformation[4] -
|
||
|
Printer::autolevelTransformation[1] * Printer::autolevelTransformation[5]) *
|
||
|
(float)Printer::currentPositionSteps[X_AXIS] * Printer::invAxisStepsPerMM[X_AXIS]) /
|
||
|
(Printer::autolevelTransformation[1] * Printer::autolevelTransformation[3] - Printer::autolevelTransformation[0] * Printer::autolevelTransformation[4]);
|
||
|
Printer::zMin = 0;
|
||
|
if(com->hasS() && com->S < 3 && com->S > 0)
|
||
|
{
|
||
|
#if MAX_HARDWARE_ENDSTOP_Z
|
||
|
#if DRIVE_SYSTEM == DELTA
|
||
|
Printer::zLength += (h3 + z) - Printer::currentPosition[Z_AXIS];
|
||
|
#else
|
||
|
int32_t zBottom = Printer::currentPositionSteps[Z_AXIS] = (h3 + z) * Printer::axisStepsPerMM[Z_AXIS];
|
||
|
Printer::zLength = Printer::runZMaxProbe() + zBottom * Printer::invAxisStepsPerMM[Z_AXIS] - ENDSTOP_Z_BACK_ON_HOME;
|
||
|
#endif
|
||
|
Com::printFLN(Com::tZProbePrinterHeight,Printer::zLength);
|
||
|
#else // max hardware endstop
|
||
|
#if DRIVE_SYSTEM != DELTA
|
||
|
Printer::currentPositionSteps[Z_AXIS] = (h3 + z) * Printer::axisStepsPerMM[Z_AXIS];
|
||
|
#endif
|
||
|
#endif
|
||
|
Printer::setAutolevelActive(true);
|
||
|
if(com->S == 2)
|
||
|
EEPROM::storeDataIntoEEPROM();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#if DRIVE_SYSTEM != DELTA
|
||
|
Printer::currentPositionSteps[Z_AXIS] = (h3 + z) * Printer::axisStepsPerMM[Z_AXIS];
|
||
|
#endif
|
||
|
if(com->hasS() && com->S == 3)
|
||
|
EEPROM::storeDataIntoEEPROM();
|
||
|
}
|
||
|
Printer::setAutolevelActive(true);
|
||
|
Printer::updateDerivedParameter();
|
||
|
Printer::updateCurrentPosition(true);
|
||
|
printCurrentPosition(PSTR("G32 "));
|
||
|
#if DRIVE_SYSTEM == DELTA
|
||
|
Printer::homeAxis(true, true, true);
|
||
|
#endif
|
||
|
Printer::feedrate = oldFeedrate;
|
||
|
}
|
||
|
break;
|
||
|
#endif
|
||
|
case 68: // probes center X0 Y0 then probes x/y 3rd position, commonly the z tower on deltas
|
||
|
{
|
||
|
#if DISTORTION_CORRECTION
|
||
|
float oldFeedrate = Printer::feedrate;
|
||
|
Printer::measureDistortion();
|
||
|
Printer::feedrate = oldFeedrate;
|
||
|
#else
|
||
|
//bool oldAutolevel = Printer::isAutolevelActive();
|
||
|
float sum = 0, sum1 = 0, last, hradius,oldFeedrate = Printer::feedrate;
|
||
|
int32_t probeSensitivity = Z_PROBE_SENSITIVITY;
|
||
|
float defaultRadius = PRINTER_RADIUS-END_EFFECTOR_HORIZONTAL_OFFSET-CARRIAGE_HORIZONTAL_OFFSET;
|
||
|
float oldRadius;
|
||
|
do{
|
||
|
//Printer::radius0 = PRINTER_RADIUS-END_EFFECTOR_HORIZONTAL_OFFSET-CARRIAGE_HORIZONTAL_OFFSET; // set horizontal radius to firmware default
|
||
|
oldRadius = Printer::radius0;
|
||
|
EEPROM::storeDataIntoEEPROM(); //save firmware horizontal radius before calibration
|
||
|
EEPROM::readDataFromEEPROM();
|
||
|
Printer::homeAxis(true,true,true);
|
||
|
GCode::executeFString(Com::tZProbeStartScript);
|
||
|
Printer::setAutolevelActive(false);
|
||
|
Printer::moveTo(0,0,IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
sum1 = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false);
|
||
|
sum = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false);
|
||
|
if ((sum1 - sum) > Z_PROBE_TOLERANCE || (sum1 - sum) < - Z_PROBE_TOLERANCE){ //tap reports distance, if more or less than .1mm, it will re-run
|
||
|
Com::printFLN(PSTR("Z probe failed on sensitivity: "), probeSensitivity );
|
||
|
if(probeSensitivity < Z_PROBE_MAX_SENSITIVITY){
|
||
|
accelerometer_recv(0x32);
|
||
|
probeSensitivity+=2;
|
||
|
Com::printFLN(PSTR("Setting Probe Sensitivity To:"), probeSensitivity );
|
||
|
accelerometer_write(0x32,uint8_t(probeSensitivity)); //INT1 THRESHOLD
|
||
|
accelerometer_write(0x3A,uint8_t(probeSensitivity)); //CLICK THRESHOLD
|
||
|
accelerometer_recv(0x32);
|
||
|
}
|
||
|
sum = -1;
|
||
|
continue;
|
||
|
}else{
|
||
|
sum = (sum + sum1) / 2;
|
||
|
}
|
||
|
|
||
|
Printer::moveTo(EEPROM::zProbeX3(),EEPROM::zProbeY3(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
|
||
|
sum1 = Printer::runZProbe(false,true); // First tap
|
||
|
last = Printer::runZProbe(false,true); // Second tap
|
||
|
if ((sum1 - last) > Z_PROBE_TOLERANCE || (sum1 - last) < - Z_PROBE_TOLERANCE){
|
||
|
Com::printFLN(PSTR("Z probe failed on sensitivity: "), probeSensitivity );
|
||
|
accelerometer_recv(0x32);
|
||
|
probeSensitivity+=2;
|
||
|
Com::printFLN(PSTR("Setting Probe Sensitivity To:"), probeSensitivity );
|
||
|
accelerometer_write(0x32,uint8_t(probeSensitivity)); //INT1 THRESHOLD
|
||
|
accelerometer_write(0x3A,uint8_t(probeSensitivity)); //CLICK THRESHOLD
|
||
|
accelerometer_recv(0x32);
|
||
|
sum = -1;
|
||
|
continue;
|
||
|
}else{
|
||
|
last = (last + sum1) / 2;
|
||
|
}
|
||
|
} while (sum < 0);
|
||
|
|
||
|
sum = (sum - last)*AXIS_STEPS_PER_MM;
|
||
|
if(sum<0)
|
||
|
{
|
||
|
sum=-sum;
|
||
|
Com::printFLN(Com::tZProbeAverage,sum);
|
||
|
hradius = (sum / Printer::radius0)*2;
|
||
|
Com::printFLN(Com::tZProbeAverage,hradius);
|
||
|
Printer::radius0 = Printer::radius0 - hradius;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hradius = (sum / Printer::radius0)*2;
|
||
|
Printer::radius0 = Printer::radius0 + hradius;
|
||
|
}
|
||
|
if(Printer::radius0 / defaultRadius > 1.1 || Printer::radius0 / defaultRadius < 0.9){
|
||
|
Printer::radius0 = defaultRadius;
|
||
|
Com::printFLN(PSTR("Calculated Radius is bad :"), Printer::radius0 );
|
||
|
}else{
|
||
|
Com::printFLN(PSTR("Old Radius: "), oldRadius );
|
||
|
Com::printFLN(PSTR("New Radius: "), Printer::radius0 );
|
||
|
}
|
||
|
Printer::feedrate = oldFeedrate;
|
||
|
//Printer::setAutolevelActive(oldAutolevel);
|
||
|
Printer::setAutolevelActive(true);
|
||
|
Printer::updateCurrentPosition(true);
|
||
|
printCurrentPosition(PSTR("hehe"));
|
||
|
GCode::executeFString(Com::tZProbeEndScript);
|
||
|
Printer::feedrate = oldFeedrate;
|
||
|
Printer::homeAxis(true,true,true);
|
||
|
EEPROM::storeDataIntoEEPROM();
|
||
|
#endif // DISTORTION_CORRECTION
|
||
|
}
|
||
|
break;
|
||
|
case 69: // G69 3 points, probe endstop offsets
|
||
|
{
|
||
|
#if DISTORTION_CORRECTION
|
||
|
float oldFeedrate = Printer::feedrate;
|
||
|
Printer::measureDistortion();
|
||
|
Printer::feedrate = oldFeedrate;
|
||
|
#else
|
||
|
//bool oldAutolevel = Printer::isAutolevelActive();
|
||
|
float sum1 = 0, sum = 0, last,oldFeedrate = Printer::feedrate;
|
||
|
int32_t probeSensitivity = Z_PROBE_SENSITIVITY;
|
||
|
do{
|
||
|
if(com->hasS() && com->S == 2){ // only wipe values if saving the new values
|
||
|
EEPROM::setDeltaTowerXOffsetSteps(0); // set X offset to 0
|
||
|
EEPROM::setDeltaTowerYOffsetSteps(0); // set Y offset to 0
|
||
|
EEPROM::setDeltaTowerZOffsetSteps(0); // set Z offset to 0
|
||
|
EEPROM::storeDataIntoEEPROM(); // store offsets to 0 before doing anything
|
||
|
EEPROM::readDataFromEEPROM();
|
||
|
}
|
||
|
Printer::homeAxis(true,true,true);
|
||
|
GCode::executeFString(Com::tZProbeStartScript);
|
||
|
Printer::setAutolevelActive(false);
|
||
|
Printer::moveTo(EEPROM::zProbeX1(),EEPROM::zProbeY1(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
|
||
|
sum1 = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false); //First tap
|
||
|
sum = Printer::runZProbe(true,false,Z_PROBE_REPETITIONS,false); //Second tap
|
||
|
if ((sum1 - sum) > Z_PROBE_TOLERANCE || (sum1 - sum) < - Z_PROBE_TOLERANCE){ //tap reports distance, if more or less than .1mm, it will re-run
|
||
|
Com::printFLN(PSTR("Z probe failed on sensitivity: "), probeSensitivity );
|
||
|
if(probeSensitivity < Z_PROBE_MAX_SENSITIVITY){
|
||
|
accelerometer_recv(0x32);
|
||
|
if ( com->hasS() )
|
||
|
{
|
||
|
probeSensitivity+=2;
|
||
|
Com::printFLN(PSTR("Setting Probe Sensitivity To:"), probeSensitivity );
|
||
|
accelerometer_write(0x32,uint8_t(probeSensitivity)); //INT1 THRESHOLD
|
||
|
accelerometer_write(0x3A,uint8_t(probeSensitivity)); //CLICK THRESHOLD
|
||
|
accelerometer_recv(0x32);
|
||
|
}
|
||
|
}
|
||
|
sum = -1;
|
||
|
continue;
|
||
|
}else{
|
||
|
sum = (sum + sum1) / 2;
|
||
|
}
|
||
|
|
||
|
int32_t offsetX = ((sum * AXIS_STEPS_PER_MM) - (Z_PROBE_BED_DISTANCE * AXIS_STEPS_PER_MM)), offsetStepsX = EEPROM::deltaTowerXOffsetSteps();
|
||
|
Printer::moveTo(EEPROM::zProbeX2(),EEPROM::zProbeY2(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
|
||
|
sum1 = Printer::runZProbe(false,false); //First tap Y tower
|
||
|
last = Printer::runZProbe(false,false); //Second tap Y tower
|
||
|
if ((sum1 - last) > Z_PROBE_TOLERANCE || (sum1 - last) < - Z_PROBE_TOLERANCE){
|
||
|
Com::printFLN(PSTR("Z probe failed on sensitivity: "), probeSensitivity );
|
||
|
if(probeSensitivity < Z_PROBE_MAX_SENSITIVITY){
|
||
|
accelerometer_recv(0x32);
|
||
|
probeSensitivity+=2;
|
||
|
Com::printFLN(PSTR("Setting Probe Sensitivity To:"), probeSensitivity );
|
||
|
accelerometer_write(0x32,uint8_t(probeSensitivity)); //INT1 THRESHOLD
|
||
|
accelerometer_write(0x3A,uint8_t(probeSensitivity)); //CLICK THRESHOLD
|
||
|
accelerometer_recv(0x32);
|
||
|
}
|
||
|
last = -1; // fail flag to stop probe
|
||
|
continue;
|
||
|
}else{
|
||
|
last = (last + sum1) / 2;
|
||
|
}
|
||
|
|
||
|
int32_t offsetY = ((last * AXIS_STEPS_PER_MM) - (Z_PROBE_BED_DISTANCE * AXIS_STEPS_PER_MM)), offsetStepsY = EEPROM::deltaTowerYOffsetSteps();
|
||
|
Printer::moveTo(EEPROM::zProbeX3(),EEPROM::zProbeY3(),IGNORE_COORDINATE,IGNORE_COORDINATE,EEPROM::zProbeXYSpeed());
|
||
|
|
||
|
sum1 = Printer::runZProbe(false,true); //First tap Z tower
|
||
|
last = Printer::runZProbe(false,true); //Second tap Z tower
|
||
|
if((sum1 - last) > Z_PROBE_TOLERANCE || (sum1 - last) < - Z_PROBE_TOLERANCE){
|
||
|
Com::printFLN(PSTR("Z probe failed on sensitivity: "), probeSensitivity );
|
||
|
if(probeSensitivity < Z_PROBE_MAX_SENSITIVITY){
|
||
|
accelerometer_recv(0x32);
|
||
|
probeSensitivity+=2;
|
||
|
Com::printFLN(PSTR("Setting Probe Sensitivity To:"), probeSensitivity );
|
||
|
accelerometer_write(0x32,uint8_t(probeSensitivity)); //INT1 THRESHOLD
|
||
|
accelerometer_write(0x3A,uint8_t(probeSensitivity)); //CLICK THRESHOLD
|
||
|
accelerometer_recv(0x32);
|
||
|
}
|
||
|
last = -1; // fail flag to stop probe
|
||
|
continue;
|
||
|
}else{
|
||
|
last = (last + sum1) / 2;
|
||
|
}
|
||
|
|
||
|
int32_t offsetZ = ((last * AXIS_STEPS_PER_MM) - (Z_PROBE_BED_DISTANCE * AXIS_STEPS_PER_MM)), offsetStepsZ = EEPROM::deltaTowerZOffsetSteps();
|
||
|
|
||
|
if(com->hasS() && com->S)
|
||
|
{
|
||
|
Printer::updateCurrentPosition();
|
||
|
Printer::updateDerivedParameter();
|
||
|
//Printer::homeAxis(true,true,true); added to end of main g69
|
||
|
Com::printInfoFLN(Com::tZProbeZReset);
|
||
|
Com::printFLN(Com::tZProbePrinterHeight,Printer::zLength);
|
||
|
}
|
||
|
Printer::feedrate = oldFeedrate;
|
||
|
//Printer::setAutolevelActive(oldAutolevel);
|
||
|
Printer::setAutolevelActive(true);
|
||
|
|
||
|
if(com->hasS() && com->S == 2)
|
||
|
{
|
||
|
if(offsetX < offsetY && offsetX < offsetZ)
|
||
|
{
|
||
|
offsetY = offsetStepsY + (offsetY - offsetX);
|
||
|
offsetZ = offsetStepsZ + (offsetZ - offsetX);
|
||
|
offsetX = 0;
|
||
|
EEPROM::setDeltaTowerYOffsetSteps(offsetY);
|
||
|
EEPROM::setDeltaTowerZOffsetSteps(offsetZ);
|
||
|
}
|
||
|
else if(offsetY < offsetX && offsetY < offsetZ)
|
||
|
{
|
||
|
offsetX = offsetStepsX + (offsetX - offsetY);
|
||
|
offsetZ = offsetStepsZ + (offsetZ - offsetY);
|
||
|
EEPROM::setDeltaTowerXOffsetSteps(offsetX);
|
||
|
EEPROM::setDeltaTowerZOffsetSteps(offsetZ);
|
||
|
offsetY = 0;
|
||
|
}
|
||
|
else if(offsetZ < offsetX && offsetZ < offsetY)
|
||
|
{
|
||
|
offsetX = offsetStepsX + (offsetX - offsetZ);
|
||
|
offsetY = offsetStepsY + (offsetY - offsetZ);
|
||
|
EEPROM::setDeltaTowerXOffsetSteps(offsetX);
|
||
|
EEPROM::setDeltaTowerYOffsetSteps(offsetY);
|
||
|
offsetZ = 0;
|
||
|
}
|
||
|
if(offsetX > 400 || offsetY > 400 || offsetZ > 400){
|
||
|
sum = -1;
|
||
|
Com::printFLN(PSTR("OFFSETS OFF BY TOO MUCH _ TRYING AGAIN: "), probeSensitivity);
|
||
|
Com::printFLN(PSTR("X: "), offsetX);
|
||
|
Com::printFLN(PSTR("Y: "), offsetY);
|
||
|
Com::printFLN(PSTR("Z: "), offsetZ);
|
||
|
}else{
|
||
|
EEPROM::storeDataIntoEEPROM();
|
||
|
}
|
||
|
}
|
||
|
}while(sum < 0 || last < 0);
|
||
|
Printer::updateCurrentPosition(true);
|
||
|
printCurrentPosition(PSTR("G69 "));
|
||
|
GCode::executeFString(Com::tZProbeEndScript);
|
||
|
Printer::feedrate = oldFeedrate;
|
||
|
Printer::homeAxis(true,true,true);
|
||
|
#endif // DISTORTION_CORRECTION
|
||
|
}
|
||
|
break;
|
||
|
#endif
|
||
|
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
|
||
|
{
|
||
|
float xOff = Printer::coordinateOffset[X_AXIS];
|
||
|
float yOff = Printer::coordinateOffset[Y_AXIS];
|
||
|
float zOff = Printer::coordinateOffset[Z_AXIS];
|
||
|
if(com->hasX()) xOff = Printer::convertToMM(com->X) - Printer::currentPosition[X_AXIS];
|
||
|
if(com->hasY()) yOff = Printer::convertToMM(com->Y) - Printer::currentPosition[Y_AXIS];
|
||
|
if(com->hasZ()) zOff = Printer::convertToMM(com->Z) - Printer::currentPosition[Z_AXIS];
|
||
|
Printer::setOrigin(xOff, yOff, zOff);
|
||
|
if(com->hasE())
|
||
|
{
|
||
|
Printer::currentPositionSteps[E_AXIS] = Printer::convertToMM(com->E) * Printer::axisStepsPerMM[E_AXIS];
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
#if DRIVE_SYSTEM == DELTA
|
||
|
case 100: // G100 Calibrate floor or rod radius
|
||
|
{
|
||
|
// Using manual control, adjust hot end to contact floor.
|
||
|
// G100 <no arguments> No action. Avoid accidental floor reset.
|
||
|
// G100 [X] [Y] [Z] set floor for argument passed in. Number ignored and may be absent.
|
||
|
// G100 R with X Y or Z flag error, sets only floor or radius, not both.
|
||
|
// G100 R[n] Add n to radius. Adjust to be above floor if necessary
|
||
|
// G100 R[0] set radius based on current z measurement. Moves to (0,0,0)
|
||
|
float currentZmm = Printer::currentPosition[Z_AXIS];
|
||
|
if (currentZmm/Printer::zLength > 0.1)
|
||
|
{
|
||
|
Com::printErrorFLN(PSTR("Calibration code is limited to bottom 10% of Z height"));
|
||
|
break;
|
||
|
}
|
||
|
if (com->hasR())
|
||
|
{
|
||
|
if (com->hasX() || com->hasY() || com->hasZ())
|
||
|
Com::printErrorFLN(PSTR("Cannot set radius and floor at same time."));
|
||
|
else if (com->R != 0)
|
||
|
{
|
||
|
//add r to radius
|
||
|
if (abs(com->R) <= 10) EEPROM::incrementRodRadius(com->R);
|
||
|
else Com::printErrorFLN(PSTR("Calibration movement is limited to 10mm."));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// auto set radius. Head must be at 0,0 and touching
|
||
|
// Z offset will be corrected for.
|
||
|
if (Printer::currentPosition[X_AXIS] == 0
|
||
|
&& Printer::currentPosition[Y_AXIS] == 0)
|
||
|
{
|
||
|
if(Printer::isLargeMachine())
|
||
|
{
|
||
|
// calculate radius assuming we are at surface
|
||
|
// If Z is greater than 0 it will get calculated out for correct radius
|
||
|
// Use either A or B tower as they acnhor x cartesian axis and always have
|
||
|
// Radius distance to center in simplest set up.
|
||
|
float h = Printer::deltaDiagonalStepsSquaredB.f;
|
||
|
unsigned long bSteps = Printer::currentDeltaPositionSteps[B_TOWER];
|
||
|
// The correct Rod Radius would put us here at z==0 and B height is
|
||
|
// square root (rod length squared minus rod radius squared)
|
||
|
// Reverse that to get calculated Rod Radius given B height
|
||
|
h -= RMath::sqr((float)bSteps);
|
||
|
h = sqrt(h);
|
||
|
EEPROM::setRodRadius(h*Printer::invAxisStepsPerMM[Z_AXIS]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// calculate radius assuming we are at surface
|
||
|
// If Z is greater than 0 it will get calculated out for correct radius
|
||
|
// Use either A or B tower as they acnhor x cartesian axis and always have
|
||
|
// Radius distance to center in simplest set up.
|
||
|
unsigned long h = Printer::deltaDiagonalStepsSquaredB.l;
|
||
|
unsigned long bSteps = Printer::currentDeltaPositionSteps[B_TOWER];
|
||
|
// The correct Rod Radius would put us here at z==0 and B height is
|
||
|
// square root (rod length squared minus rod radius squared)
|
||
|
// Reverse that to get calculated Rod Radius given B height
|
||
|
h -= RMath::sqr(bSteps);
|
||
|
h = SQRT(h);
|
||
|
EEPROM::setRodRadius(h*Printer::invAxisStepsPerMM[Z_AXIS]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
Com::printErrorFLN(PSTR("First move to touch at x,y=0,0 to auto-set radius."));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bool tooBig = false;
|
||
|
if (com->hasX())
|
||
|
{
|
||
|
if (abs(com->X) <= 10)
|
||
|
EEPROM::setTowerXFloor(com->X + currentZmm + Printer::xMin);
|
||
|
else tooBig = true;
|
||
|
}
|
||
|
if (com->hasY())
|
||
|
{
|
||
|
if (abs(com->Y) <= 10)
|
||
|
EEPROM::setTowerYFloor(com->Y + currentZmm + Printer::yMin);
|
||
|
else tooBig = true;
|
||
|
}
|
||
|
if (com->hasZ())
|
||
|
{
|
||
|
if (abs(com->Z) <= 10)
|
||
|
EEPROM::setTowerZFloor(com->Z + currentZmm + Printer::zMin);
|
||
|
else tooBig = true;
|
||
|
}
|
||
|
if (tooBig)
|
||
|
Com::printErrorFLN(PSTR("Calibration movement is limited to 10mm."));
|
||
|
}
|
||
|
// after adjusting zero, physical position is out of sync with memory position
|
||
|
// this could cause jerky movement or push head into print surface.
|
||
|
// moving gets back into safe zero'ed position with respect to newle set floor or Radius.
|
||
|
Printer::moveTo(IGNORE_COORDINATE,IGNORE_COORDINATE,12.0,IGNORE_COORDINATE,IGNORE_COORDINATE);
|
||
|
break;
|
||
|
}
|
||
|
case 131: // G131 Remove offset
|
||
|
{
|
||
|
float cx,cy,cz;
|
||
|
Printer::realPosition(cx,cy,cz);
|
||
|
float oldfeedrate = Printer::feedrate;
|
||
|
Printer::offsetX = 0;
|
||
|
Printer::offsetY = 0;
|
||
|
Printer::moveToReal(cx,cy,cz,IGNORE_COORDINATE,Printer::homingFeedrate[X_AXIS]);
|
||
|
Printer::feedrate = oldfeedrate;
|
||
|
Printer::updateCurrentPosition();
|
||
|
}
|
||
|
break;
|
||
|
case 132: // G132 Calibrate endstop offsets
|
||
|
{
|
||
|
// This has the probably unintended side effect of turning off leveling.
|
||
|
Printer::setAutolevelActive(false); // don't let transformations change result!
|
||
|
Printer::coordinateOffset[X_AXIS] = 0;
|
||
|
Printer::coordinateOffset[Y_AXIS] = 0;
|
||
|
Printer::coordinateOffset[Z_AXIS] = 0;
|
||
|
// I think this is coded incorrectly, as it depends on the biginning position of the
|
||
|
// of the hot end, and so should first move to x,y,z= 0,0,0, but as that may not
|
||
|
// be possible if the printer is not in the homes/zeroed state, the printer
|
||
|
// cannot safely move to 0 z coordinate without crashong into the print surface.
|
||
|
// so other than commenting, I'm not meddling.
|
||
|
// but you will always get different counts from different positions.
|
||
|
Printer::deltaMoveToTopEndstops(Printer::homingFeedrate[Z_AXIS]);
|
||
|
int32_t m = RMath::max(Printer::stepsRemainingAtXHit,RMath::max(Printer::stepsRemainingAtYHit,Printer::stepsRemainingAtZHit));
|
||
|
int32_t offx = m-Printer::stepsRemainingAtXHit;
|
||
|
int32_t offy = m-Printer::stepsRemainingAtYHit;
|
||
|
int32_t offz = m-Printer::stepsRemainingAtZHit;
|
||
|
Com::printFLN(Com::tTower1,offx);
|
||
|
Com::printFLN(Com::tTower2,offy);
|
||
|
Com::printFLN(Com::tTower3,offz);
|
||
|
#if EEPROM_MODE != 0
|
||
|
if(com->hasS() && com->S > 0)
|
||
|
{
|
||
|
EEPROM::setDeltaTowerXOffsetSteps(offx);
|
||
|
EEPROM::setDeltaTowerYOffsetSteps(offy);
|
||
|
EEPROM::setDeltaTowerZOffsetSteps(offz);
|
||
|
}
|
||
|
#endif
|
||
|
Printer::homeAxis(true,true,true);
|
||
|
}
|
||
|
break;
|
||
|
case 133: // G133 Measure steps to top
|
||
|
{
|
||
|
bool oldAuto = Printer::isAutolevelActive();
|
||
|
Printer::setAutolevelActive(false); // don't let transformations change result!
|
||
|
Printer::currentPositionSteps[X_AXIS] = 0;
|
||
|
Printer::currentPositionSteps[Y_AXIS] = 0;
|
||
|
Printer::currentPositionSteps[Z_AXIS] = 0;
|
||
|
Printer::coordinateOffset[X_AXIS] = 0;
|
||
|
Printer::coordinateOffset[Y_AXIS] = 0;
|
||
|
Printer::coordinateOffset[Z_AXIS] = 0;
|
||
|
Printer::currentDeltaPositionSteps[A_TOWER] = 0;
|
||
|
Printer::currentDeltaPositionSteps[B_TOWER] = 0;
|
||
|
Printer::currentDeltaPositionSteps[C_TOWER] = 0;
|
||
|
// similar to comment above, this will get a different answer from any different starting point
|
||
|
// so it is unclear how this is helpful. It must start at a well defined point.
|
||
|
Printer::deltaMoveToTopEndstops(Printer::homingFeedrate[Z_AXIS]);
|
||
|
int32_t offx = HOME_DISTANCE_STEPS-Printer::stepsRemainingAtXHit;
|
||
|
int32_t offy = HOME_DISTANCE_STEPS-Printer::stepsRemainingAtYHit;
|
||
|
int32_t offz = HOME_DISTANCE_STEPS-Printer::stepsRemainingAtZHit;
|
||
|
Com::printFLN(Com::tTower1,offx);
|
||
|
Com::printFLN(Com::tTower2,offy);
|
||
|
Com::printFLN(Com::tTower3,offz);
|
||
|
Printer::setAutolevelActive(oldAuto);
|
||
|
Printer::homeAxis(true,true,true);
|
||
|
}
|
||
|
break;
|
||
|
case 134: // G134
|
||
|
Com::printF(PSTR("CompDelta:"),Printer::currentDeltaPositionSteps[A_TOWER]);
|
||
|
Com::printF(Com::tComma,Printer::currentDeltaPositionSteps[B_TOWER]);
|
||
|
Com::printFLN(Com::tComma,Printer::currentDeltaPositionSteps[C_TOWER]);
|
||
|
#ifdef DEBUG_REAL_POSITION
|
||
|
Com::printF(PSTR("RealDelta:"),Printer::realDeltaPositionSteps[A_TOWER]);
|
||
|
Com::printF(Com::tComma,Printer::realDeltaPositionSteps[B_TOWER]);
|
||
|
Com::printFLN(Com::tComma,Printer::realDeltaPositionSteps[C_TOWER]);
|
||
|
#endif
|
||
|
Printer::updateCurrentPosition();
|
||
|
Com::printF(PSTR("PosFromSteps:"));
|
||
|
printCurrentPosition(PSTR("G134 "));
|
||
|
break;
|
||
|
|
||
|
#endif // DRIVE_SYSTEM
|
||
|
default:
|
||
|
if(Printer::debugErrors())
|
||
|
{
|
||
|
Com::printF(Com::tUnknownCommand);
|
||
|
com->printCommand();
|
||
|
}
|
||
|
}
|
||
|
previousMillisCmd = HAL::timeInMilliseconds();
|
||
|
}
|
||
|
/**
|
||
|
\brief Execute the G command stored in com.
|
||
|
*/
|
||
|
void Commands::processMCode(GCode *com)
|
||
|
{
|
||
|
uint32_t codenum; //throw away variable
|
||
|
switch( com->M )
|
||
|
{
|
||
|
case 17: //M17 Enable all Steppers
|
||
|
Printer::enableXStepper();
|
||
|
Printer::enableYStepper();
|
||
|
Printer::enableZStepper();
|
||
|
break;
|
||
|
case 18: //M18 Disable all Steppers
|
||
|
Printer::disableXStepper();
|
||
|
Printer::disableYStepper();
|
||
|
Printer::disableZStepper();
|
||
|
break;
|
||
|
#if SDSUPPORT
|
||
|
|
||
|
case 20: // M20 - list SD card
|
||
|
sd.ls();
|
||
|
break;
|
||
|
case 21: // M21 - init SD card
|
||
|
sd.mount();
|
||
|
break;
|
||
|
case 22: //M22 - release SD card
|
||
|
sd.unmount();
|
||
|
break;
|
||
|
case 23: //M23 - Select file
|
||
|
if(com->hasString())
|
||
|
{
|
||
|
sd.fat.chdir();
|
||
|
sd.selectFile(com->text);
|
||
|
}
|
||
|
break;
|
||
|
case 24: //M24 - Start SD print
|
||
|
sd.startPrint();
|
||
|
break;
|
||
|
case 25: //M25 - Pause SD print
|
||
|
sd.pausePrint();
|
||
|
break;
|
||
|
case 26: //M26 - Set SD index
|
||
|
if(com->hasS())
|
||
|
sd.setIndex(com->S);
|
||
|
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
|
||
|
case 42: //M42 -Change pin status via gcode
|
||
|
if (com->hasP())
|
||
|
{
|
||
|
int pin_number = com->P;
|
||
|
for(uint8_t i = 0; i < (uint8_t)sizeof(sensitive_pins); i++)
|
||
|
{
|
||
|
if (pgm_read_byte(&sensitive_pins[i]) == pin_number)
|
||
|
{
|
||
|
pin_number = -1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (pin_number > -1)
|
||
|
{
|
||
|
if(com->hasS())
|
||
|
{
|
||
|
if(com->S >= 0 && com->S <= 255)
|
||
|
{
|
||
|
pinMode(pin_number, OUTPUT);
|
||
|
digitalWrite(pin_number, com->S);
|
||
|
analogWrite(pin_number, com->S);
|
||
|
Com::printF(Com::tSetOutputSpace, pin_number);
|
||
|
Com::printFLN(Com::tSpaceToSpace,(int)com->S);
|
||
|
}
|
||
|
else
|
||
|
Com::printErrorFLN(PSTR("Illegal S value for M42"));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pinMode(pin_number, INPUT_PULLUP);
|
||
|
Com::printF(Com::tSpaceToSpace, pin_number);
|
||
|
Com::printFLN(Com::tSpaceIsSpace, digitalRead(pin_number));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Com::printErrorFLN(PSTR("Pin can not be set by M42, may in invalid or in use. "));
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 80: // M80 - ATX Power On
|
||
|
#if PS_ON_PIN>-1
|
||
|
Commands::waitUntilEndOfAllMoves();
|
||
|
previousMillisCmd = HAL::timeInMilliseconds();
|
||
|
SET_OUTPUT(PS_ON_PIN); //GND
|
||
|
Printer::setPowerOn(true);
|
||
|
WRITE(PS_ON_PIN, (POWER_INVERTING ? HIGH : LOW));
|
||
|
#endif
|
||
|
break;
|
||
|
case 81: // M81 - ATX Power Off
|
||
|
#if PS_ON_PIN>-1
|
||
|
Commands::waitUntilEndOfAllMoves();
|
||
|
SET_OUTPUT(PS_ON_PIN); //GND
|
||
|
Printer::setPowerOn(false);
|
||
|
WRITE(PS_ON_PIN,(POWER_INVERTING ? LOW : HIGH));
|
||
|
#endif
|
||
|
break;
|
||
|
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
|
||
|
{
|
||
|
if(com->hasP()){
|
||
|
switch(com->P){
|
||
|
case 0:
|
||
|
Printer::disableXStepper();
|
||
|
break;
|
||
|
|
||
|
case 1:
|
||
|
Printer::disableYStepper();
|
||
|
break;
|
||
|
|
||
|
case 2:
|
||
|
Printer::disableZStepper();
|
||
|
break;
|
||
|
|
||
|
case 3:
|
||
|
Extruder::disableCurrentExtruderMotor();
|
||
|
break;
|
||
|
|
||
|
case 4:
|
||
|
Extruder::disableAllExtruderMotors();
|
||
|
break;
|
||
|
}
|
||
|
}else{
|
||
|
Commands::waitUntilEndOfAllMoves();
|
||
|
Printer::kill(true);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case 85: // M85
|
||
|
if(com->hasS())
|
||
|
maxInactiveTime = (int32_t)com->S * 1000;
|
||
|
else
|
||
|
maxInactiveTime = 0;
|
||
|
break;
|
||
|
case 92: // M92
|
||
|
if(com->hasX()) Printer::axisStepsPerMM[X_AXIS] = com->X;
|
||
|
if(com->hasY()) Printer::axisStepsPerMM[Y_AXIS] = com->Y;
|
||
|
if(com->hasZ()) Printer::axisStepsPerMM[Z_AXIS] = com->Z;
|
||
|
Printer::updateDerivedParameter();
|
||
|
if(com->hasE())
|
||
|
{
|
||
|
Extruder::current->stepsPerMM = com->E;
|
||
|
Extruder::selectExtruderById(Extruder::current->id);
|
||
|
}
|
||
|
break;
|
||
|
case 99: // M99 S<time>
|
||
|
{
|
||
|
millis_t wait = 10000;
|
||
|
if(com->hasS())
|
||
|
wait = 1000*com->S;
|
||
|
if(com->hasX())
|
||
|
Printer::disableXStepper();
|
||
|
if(com->hasY())
|
||
|
Printer::disableYStepper();
|
||
|
if(com->hasZ())
|
||
|
Printer::disableZStepper();
|
||
|
wait += HAL::timeInMilliseconds();
|
||
|
#ifdef DEBUG_PRINT
|
||
|
debugWaitLoop = 2;
|
||
|
#endif
|
||
|
while(wait-HAL::timeInMilliseconds() < 100000)
|
||
|
{
|
||
|
Printer::defaultLoopActions();
|
||
|
}
|
||
|
if(com->hasX())
|
||
|
Printer::enableXStepper();
|
||
|
if(com->hasY())
|
||
|
Printer::enableYStepper();
|
||
|
if(com->hasZ())
|
||
|
Printer::enableZStepper();
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 104: // M104 temperature
|
||
|
#if NUM_EXTRUDER > 0
|
||
|
if(reportTempsensorError()) break;
|
||
|
previousMillisCmd = HAL::timeInMilliseconds();
|
||
|
if(Printer::debugDryrun()) break;
|
||
|
#ifdef EXACT_TEMPERATURE_TIMING
|
||
|
Commands::waitUntilEndOfAllMoves();
|
||
|
#else
|
||
|
if(com->hasP() || (com->hasS() && com->S == 0))
|
||
|
Commands::waitUntilEndOfAllMoves();
|
||
|
#endif
|
||
|
if (com->hasS())
|
||
|
{
|
||
|
#if NUM_EXTRUDER > 1
|
||
|
if(com->hasT()){
|
||
|
if(com->T == Extruder::current->id){
|
||
|
for(uint8_t i = 0; i < NUM_EXTRUDER; i++){
|
||
|
Extruder::setTemperatureForExtruder(com->S,i,com->hasF() && com->F>0);
|
||
|
}
|
||
|
}
|
||
|
else break;
|
||
|
}
|
||
|
else
|
||
|
for(uint8_t i = 0; i < NUM_EXTRUDER; i++){
|
||
|
Extruder::setTemperatureForExtruder(com->S,i,com->hasF() && com->F>0);
|
||
|
}
|
||
|
#else
|
||
|
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
|
||
|
}
|
||
|
#endif
|
||
|
break;
|
||
|
case 140: // M140 set bed temp
|
||
|
if(reportTempsensorError()) break;
|
||
|
previousMillisCmd = HAL::timeInMilliseconds();
|
||
|
if(Printer::debugDryrun()) break;
|
||
|
if (com->hasS()) Extruder::setHeatedBedTemperature(com->S,com->hasF() && com->F>0);
|
||
|
break;
|
||
|
case 105: // M105 get temperature. Always returns the current temperature, doesn't wait until move stopped
|
||
|
printTemperatures(com->hasX());
|
||
|
break;
|
||
|
case 109: // M109 - Wait for extruder heater to reach target.
|
||
|
#if NUM_EXTRUDER>0
|
||
|
{
|
||
|
if(reportTempsensorError()) break;
|
||
|
previousMillisCmd = HAL::timeInMilliseconds();
|
||
|
if(Printer::debugDryrun()) break;
|
||
|
UI_STATUS_UPD(UI_TEXT_HEATING_EXTRUDER);
|
||
|
Commands::waitUntilEndOfAllMoves();
|
||
|
Extruder *actExtruder = Extruder::current;
|
||
|
#if NUM_EXTRUDER > 1
|
||
|
if(com->hasT()){
|
||
|
if(com->T == Extruder::current->id){
|
||
|
for(uint8_t i = 0; i < NUM_EXTRUDER; i++){
|
||
|
Extruder::setTemperatureForExtruder(com->S,i,com->hasF() && com->F>0);
|
||
|
}
|
||
|
}
|
||
|
else break;
|
||
|
}
|
||
|
else
|
||
|
for(uint8_t i = 0; i < NUM_EXTRUDER; i++){
|
||
|
Extruder::setTemperatureForExtruder(com->S,i,com->hasF() && com->F>0);
|
||
|
}
|
||
|
#else
|
||
|
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);
|
||
|
#endif
|
||
|
#if defined(SKIP_M109_IF_WITHIN) && SKIP_M109_IF_WITHIN > 0
|
||
|
if(abs(actExtruder->tempControl.currentTemperatureC - actExtruder->tempControl.targetTemperatureC)<(SKIP_M109_IF_WITHIN)) break; // Already in range
|
||
|
#endif
|
||
|
bool dirRising = actExtruder->tempControl.targetTemperature > actExtruder->tempControl.currentTemperature;
|
||
|
millis_t printedTime = HAL::timeInMilliseconds();
|
||
|
millis_t waituntil = 0;
|
||
|
#if RETRACT_DURING_HEATUP
|
||
|
uint8_t retracted = 0;
|
||
|
#endif
|
||
|
millis_t currentTime;
|
||
|
do
|
||
|
{
|
||
|
previousMillisCmd = currentTime = HAL::timeInMilliseconds();
|
||
|
if( (currentTime - printedTime) > 1000 ) //Print Temp Reading every 1 second while heating up.
|
||
|
{
|
||
|
printTemperatures();
|
||
|
printedTime = currentTime;
|
||
|
}
|
||
|
Commands::checkForPeriodicalActions(true);
|
||
|
//gcode_read_serial();
|
||
|
#if RETRACT_DURING_HEATUP
|
||
|
if (actExtruder == Extruder::current && actExtruder->waitRetractUnits > 0 && !retracted && dirRising && actExtruder->tempControl.currentTemperatureC > actExtruder->waitRetractTemperature)
|
||
|
{
|
||
|
PrintLine::moveRelativeDistanceInSteps(0,0,0,-actExtruder->waitRetractUnits * Printer::axisStepsPerMM[E_AXIS],actExtruder->maxFeedrate,false,false);
|
||
|
retracted = 1;
|
||
|
}
|
||
|
#endif
|
||
|
if((waituntil == 0 &&
|
||
|
(dirRising ? actExtruder->tempControl.currentTemperatureC >= actExtruder->tempControl.targetTemperatureC - 1
|
||
|
: actExtruder->tempControl.currentTemperatureC <= actExtruder->tempControl.targetTemperatureC+1))
|
||
|
#if defined(TEMP_HYSTERESIS) && TEMP_HYSTERESIS>=1
|
||
|
|| (waituntil!=0 && (abs(actExtruder->tempControl.currentTemperatureC - actExtruder->tempControl.targetTemperatureC))>TEMP_HYSTERESIS)
|
||
|
#endif
|
||
|
)
|
||
|
{
|
||
|
waituntil = currentTime+1000UL*(millis_t)actExtruder->watchPeriod; // now wait for temp. to stabalize
|
||
|
}
|
||
|
}
|
||
|
while(waituntil==0 || (waituntil!=0 && (millis_t)(waituntil-currentTime)<2000000000UL));
|
||
|
#if RETRACT_DURING_HEATUP
|
||
|
if (retracted && actExtruder==Extruder::current)
|
||
|
{
|
||
|
PrintLine::moveRelativeDistanceInSteps(0,0,0,actExtruder->waitRetractUnits * Printer::axisStepsPerMM[E_AXIS],actExtruder->maxFeedrate,false,false);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
UI_CLEAR_STATUS;
|
||
|
#endif
|
||
|
previousMillisCmd = HAL::timeInMilliseconds();
|
||
|
break;
|
||
|
case 190: // M190 - Wait bed for heater to reach target.
|
||
|
#if HAVE_HEATED_BED
|
||
|
if(Printer::debugDryrun()) break;
|
||
|
UI_STATUS_UPD(UI_TEXT_HEATING_BED);
|
||
|
Commands::waitUntilEndOfAllMoves();
|
||
|
#if HAVE_HEATED_BED
|
||
|
if (com->hasS()) Extruder::setHeatedBedTemperature(com->S,com->hasF() && com->F>0);
|
||
|
#if defined(SKIP_M190_IF_WITHIN) && SKIP_M190_IF_WITHIN>0
|
||
|
if(abs(heatedBedController.currentTemperatureC-heatedBedController.targetTemperatureC)<SKIP_M190_IF_WITHIN) break;
|
||
|
#endif
|
||
|
codenum = HAL::timeInMilliseconds();
|
||
|
while(heatedBedController.currentTemperatureC + 0.5 < heatedBedController.targetTemperatureC)
|
||
|
{
|
||
|
if( (HAL::timeInMilliseconds()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up.
|
||
|
{
|
||
|
printTemperatures();
|
||
|
codenum = previousMillisCmd = HAL::timeInMilliseconds();
|
||
|
}
|
||
|
Commands::checkForPeriodicalActions(true);
|
||
|
}
|
||
|
#endif
|
||
|
#endif
|
||
|
UI_CLEAR_STATUS;
|
||
|
previousMillisCmd = HAL::timeInMilliseconds();
|
||
|
break;
|
||
|
case 116: // Wait for temperatures to reach target temperature
|
||
|
if(Printer::debugDryrun()) break;
|
||
|
{
|
||
|
bool allReached = false;
|
||
|
codenum = HAL::timeInMilliseconds();
|
||
|
while(!allReached)
|
||
|
{
|
||
|
allReached = true;
|
||
|
if( (HAL::timeInMilliseconds()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up.
|
||
|
{
|
||
|
printTemperatures();
|
||
|
codenum = HAL::timeInMilliseconds();
|
||
|
}
|
||
|
Commands::checkForPeriodicalActions(true);
|
||
|
for(uint8_t h = 0; h < NUM_TEMPERATURE_LOOPS; h++)
|
||
|
{
|
||
|
TemperatureController *act = tempController[h];
|
||
|
if(act->targetTemperatureC > 30 && fabs(act->targetTemperatureC-act->currentTemperatureC) > 1)
|
||
|
allReached = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
#if FAN_PIN>-1 && FEATURE_FAN_CONTROL
|
||
|
case 106: // M106 Fan On
|
||
|
setFanSpeed(com->hasS()?com->S:255,com->hasP());
|
||
|
break;
|
||
|
case 107: // M107 Fan Off
|
||
|
setFanSpeed(0,com->hasP());
|
||
|
break;
|
||
|
#endif
|
||
|
case 111: // M111 enable/disable run time debug flags
|
||
|
if(com->hasS()) Printer::debugLevel = com->S;
|
||
|
if(com->hasP())
|
||
|
{
|
||
|
if (com->P > 0) Printer::debugLevel |= com->P;
|
||
|
else Printer::debugLevel &= ~(-com->P);
|
||
|
}
|
||
|
if(Printer::debugDryrun()) // simulate movements without printing
|
||
|
{
|
||
|
Extruder::setTemperatureForExtruder(0,0);
|
||
|
#if NUM_EXTRUDER>1
|
||
|
for(uint8_t i=0; i<NUM_EXTRUDER; i++)
|
||
|
Extruder::setTemperatureForExtruder(0,i);
|
||
|
#else
|
||
|
Extruder::setTemperatureForExtruder(0,0);
|
||
|
#endif
|
||
|
#if HEATED_BED_TYPE!=0
|
||
|
target_bed_raw = 0;
|
||
|
#endif
|
||
|
}
|
||
|
break;
|
||
|
case 115: // M115
|
||
|
Com::printFLN(Com::tFirmware);
|
||
|
reportPrinterUsage();
|
||
|
break;
|
||
|
case 114: // M114
|
||
|
printCurrentPosition(PSTR("M114 "));
|
||
|
break;
|
||
|
case 117: // M117 message to lcd
|
||
|
if(com->hasString())
|
||
|
{
|
||
|
UI_STATUS_UPD_RAM(com->text);
|
||
|
}
|
||
|
break;
|
||
|
case 119: // M119
|
||
|
Commands::waitUntilEndOfAllMoves();
|
||
|
#if (X_MIN_PIN > -1) && MIN_HARDWARE_ENDSTOP_X
|
||
|
Com::printF(Com::tXMinColon);
|
||
|
Com::printF(Printer::isXMinEndstopHit()?Com::tHSpace:Com::tLSpace);
|
||
|
#endif
|
||
|
#if (X_MAX_PIN > -1) && MAX_HARDWARE_ENDSTOP_X
|
||
|
Com::printF(Com::tXMaxColon);
|
||
|
Com::printF(Printer::isXMaxEndstopHit()?Com::tHSpace:Com::tLSpace);
|
||
|
#endif
|
||
|
#if (Y_MIN_PIN > -1) && MIN_HARDWARE_ENDSTOP_Y
|
||
|
Com::printF(Com::tYMinColon);
|
||
|
Com::printF(Printer::isYMinEndstopHit()?Com::tHSpace:Com::tLSpace);
|
||
|
#endif
|
||
|
#if (Y_MAX_PIN > -1) && MAX_HARDWARE_ENDSTOP_Y
|
||
|
Com::printF(Com::tYMaxColon);
|
||
|
Com::printF(Printer::isYMaxEndstopHit()?Com::tHSpace:Com::tLSpace);
|
||
|
#endif
|
||
|
#if (Z_MIN_PIN > -1) && MIN_HARDWARE_ENDSTOP_Z
|
||
|
Com::printF(Com::tZMinColon);
|
||
|
Com::printF(Printer::isZMinEndstopHit()?Com::tHSpace:Com::tLSpace);
|
||
|
#endif
|
||
|
#if (Z_MAX_PIN > -1) && MAX_HARDWARE_ENDSTOP_Z
|
||
|
Com::printF(Com::tZMaxColon);
|
||
|
Com::printF(Printer::isZMaxEndstopHit()?Com::tHSpace:Com::tLSpace);
|
||
|
#endif
|
||
|
Com::println();
|
||
|
break;
|
||
|
#if BEEPER_TYPE>0
|
||
|
case 120: // M120 Test beeper function
|
||
|
if(com->hasS() && com->hasP())
|
||
|
beep(com->S,com->P); // Beep test
|
||
|
break;
|
||
|
#endif
|
||
|
#if MIXING_EXTRUDER > 0
|
||
|
case 163: // M163 S<extruderNum> P<weight> - Set weight for this mixing extruder drive
|
||
|
if(com->hasS() && com->hasP() && com->S < NUM_EXTRUDER && com->S >= 0)
|
||
|
Extruder::setMixingWeight(com->S,com->P);
|
||
|
break;
|
||
|
case 164: /// M164 S<virtNum> P<0 = dont store eeprom,1 = store to eeprom> - Store weights as virtual extruder S
|
||
|
if(!com->hasS() || com->S < 0 || com->S >= VIRTUAL_EXTRUDER) break; // ignore illigal values
|
||
|
for(uint8_t i = 0; i < NUM_EXTRUDER; i++)
|
||
|
{
|
||
|
extruder[i].virtualWeights[com->S] = extruder[i].mixingW;
|
||
|
}
|
||
|
#if EEPROM_MODE != 0
|
||
|
if(com->hasP() && com->P != 0) // store permanently to eeprom
|
||
|
EEPROM::storeMixingRatios();
|
||
|
#endif
|
||
|
break;
|
||
|
#endif // MIXING_EXTRUDER
|
||
|
case 200: // M200 T<extruder> D<diameter>
|
||
|
{
|
||
|
uint8_t extruderId = Extruder::current->id;
|
||
|
if(com->hasT() && com->T < NUM_EXTRUDER)
|
||
|
extruderId = com->T;
|
||
|
float d = 0;
|
||
|
if(com->hasR())
|
||
|
d = com->R;
|
||
|
if(com->hasD())
|
||
|
d = com->D;
|
||
|
extruder[extruderId].diameter = d;
|
||
|
if(extruderId == Extruder::current->id)
|
||
|
changeFlowrateMultiply(Printer::extrudeMultiply);
|
||
|
if(d == 0)
|
||
|
{
|
||
|
Com::printFLN(PSTR("Disabled volumetric extrusion for extruder "),static_cast<int>(extruderId));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Com::printF(PSTR("Set volumetric extrusion for extruder "),static_cast<int>(extruderId));
|
||
|
Com::printFLN(PSTR(" to "),d);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
#if RAMP_ACCELERATION
|
||
|
case 201: // M201
|
||
|
if(com->hasX()) Printer::maxAccelerationMMPerSquareSecond[X_AXIS] = com->X;
|
||
|
if(com->hasY()) Printer::maxAccelerationMMPerSquareSecond[Y_AXIS] = com->Y;
|
||
|
if(com->hasZ()) Printer::maxAccelerationMMPerSquareSecond[Z_AXIS] = com->Z;
|
||
|
if(com->hasE()) Printer::maxAccelerationMMPerSquareSecond[E_AXIS] = com->E;
|
||
|
Printer::updateDerivedParameter();
|
||
|
break;
|
||
|
case 202: // M202
|
||
|
if(com->hasX()) Printer::maxTravelAccelerationMMPerSquareSecond[X_AXIS] = com->X;
|
||
|
if(com->hasY()) Printer::maxTravelAccelerationMMPerSquareSecond[Y_AXIS] = com->Y;
|
||
|
if(com->hasZ()) Printer::maxTravelAccelerationMMPerSquareSecond[Z_AXIS] = com->Z;
|
||
|
if(com->hasE()) Printer::maxTravelAccelerationMMPerSquareSecond[E_AXIS] = com->E;
|
||
|
Printer::updateDerivedParameter();
|
||
|
break;
|
||
|
#endif
|
||
|
case 203: // M203 Temperature monitor
|
||
|
if(com->hasS())
|
||
|
{
|
||
|
if(com->S<NUM_EXTRUDER) manageMonitor = com->S;
|
||
|
#if HAVE_HEATED_BED
|
||
|
else manageMonitor=NUM_EXTRUDER; // Set 100 to heated bed
|
||
|
#endif
|
||
|
}
|
||
|
break;
|
||
|
case 204: // M204
|
||
|
{
|
||
|
TemperatureController *temp = &Extruder::current->tempControl;
|
||
|
if(com->hasS())
|
||
|
{
|
||
|
if(com->S<0) break;
|
||
|
if(com->S<NUM_EXTRUDER) temp = &extruder[com->S].tempControl;
|
||
|
#if HAVE_HEATED_BED
|
||
|
else temp = &heatedBedController;
|
||
|
#else
|
||
|
else break;
|
||
|
#endif
|
||
|
}
|
||
|
if(com->hasX()) temp->pidPGain = com->X;
|
||
|
if(com->hasY()) temp->pidIGain = com->Y;
|
||
|
if(com->hasZ()) temp->pidDGain = com->Z;
|
||
|
temp->updateTempControlVars();
|
||
|
}
|
||
|
break;
|
||
|
case 205: // M205 Show EEPROM settings
|
||
|
EEPROM::writeSettings();
|
||
|
break;
|
||
|
case 206: // M206 T[type] P[pos] [Sint(long] [Xfloat] Set eeprom value
|
||
|
EEPROM::update(com);
|
||
|
break;
|
||
|
case 207: // M207 X<XY jerk> Z<Z Jerk>
|
||
|
if(com->hasX())
|
||
|
Printer::maxJerk = com->X;
|
||
|
if(com->hasE())
|
||
|
{
|
||
|
Extruder::current->maxStartFeedrate = com->E;
|
||
|
Extruder::selectExtruderById(Extruder::current->id);
|
||
|
}
|
||
|
#if DRIVE_SYSTEM != DELTA
|
||
|
if(com->hasZ())
|
||
|
Printer::maxZJerk = com->Z;
|
||
|
Com::printF(Com::tJerkColon,Printer::maxJerk);
|
||
|
Com::printFLN(Com::tZJerkColon,Printer::maxZJerk);
|
||
|
#else
|
||
|
Com::printFLN(Com::tJerkColon,Printer::maxJerk);
|
||
|
#endif
|
||
|
break;
|
||
|
case 209: // M209 S<0/1> Enable/disable autoretraction
|
||
|
if(com->hasS())
|
||
|
Printer::setAutoretract(com->S != 0);
|
||
|
break;
|
||
|
case 220: // M220 S<Feedrate multiplier in percent>
|
||
|
changeFeedrateMultiply(com->getS(100));
|
||
|
break;
|
||
|
case 221: // M221 S<Extrusion flow multiplier in percent>
|
||
|
changeFlowrateMultiply(com->getS(100));
|
||
|
break;
|
||
|
#if USE_ADVANCE
|
||
|
case 223: // M223 Extruder interrupt test
|
||
|
if(com->hasS())
|
||
|
{
|
||
|
InterruptProtectedBlock noInts;
|
||
|
Printer::extruderStepsNeeded += com->S;
|
||
|
}
|
||
|
break;
|
||
|
case 232: // M232
|
||
|
Com::printF(Com::tLinearStepsColon,maxadv2);
|
||
|
#if ENABLE_QUADRATIC_ADVANCE
|
||
|
Com::printF(Com::tQuadraticStepsColon,maxadv);
|
||
|
#endif
|
||
|
Com::printFLN(Com::tCommaSpeedEqual,maxadvspeed);
|
||
|
#if ENABLE_QUADRATIC_ADVANCE
|
||
|
maxadv=0;
|
||
|
#endif
|
||
|
maxadv2=0;
|
||
|
maxadvspeed=0;
|
||
|
break;
|
||
|
#endif
|
||
|
#if USE_ADVANCE
|
||
|
case 233: // M233
|
||
|
if(com->hasY())
|
||
|
Extruder::current->advanceL = com->Y;
|
||
|
Com::printF(Com::tLinearLColon,Extruder::current->advanceL);
|
||
|
#if ENABLE_QUADRATIC_ADVANCE
|
||
|
if(com->hasX())
|
||
|
Extruder::current->advanceK = com->X;
|
||
|
Com::printF(Com::tQuadraticKColon,Extruder::current->advanceK);
|
||
|
#endif
|
||
|
Com::println();
|
||
|
Printer::updateAdvanceFlags();
|
||
|
break;
|
||
|
#endif
|
||
|
#if Z_HOME_DIR>0 && MAX_HARDWARE_ENDSTOP_Z
|
||
|
case 251: // M251
|
||
|
Printer::zLength -= Printer::currentPosition[Z_AXIS];
|
||
|
Printer::currentPositionSteps[Z_AXIS] = 0;
|
||
|
Printer::updateDerivedParameter();
|
||
|
#if NONLINEAR_SYSTEM
|
||
|
transformCartesianStepsToDeltaSteps(Printer::currentPositionSteps, Printer::currentDeltaPositionSteps);
|
||
|
#endif
|
||
|
Printer::updateCurrentPosition();
|
||
|
Com::printFLN(Com::tZProbePrinterHeight,Printer::zLength);
|
||
|
#if EEPROM_MODE != 0
|
||
|
EEPROM::storeDataIntoEEPROM(false);
|
||
|
Com::printFLN(Com::tEEPROMUpdated);
|
||
|
#endif
|
||
|
Commands::printCurrentPosition(PSTR("M251 "));
|
||
|
break;
|
||
|
#endif
|
||
|
|
||
|
case 260: // M260
|
||
|
accelerometer_init();
|
||
|
break;
|
||
|
case 261: // M261
|
||
|
Com::printFLN( PSTR("INT PIN: "), digitalRead(Z_PROBE_PIN) );
|
||
|
accelerometer_status();
|
||
|
break;
|
||
|
case 262: // M262
|
||
|
accelerometer_recv(0x32);
|
||
|
if ( com->hasS() )
|
||
|
{
|
||
|
Com::printFLN(PSTR("Setting Threshold To:"), com->S );
|
||
|
accelerometer_write(0x32,uint8_t(com->S)); //INT1 THRESHOLD
|
||
|
accelerometer_write(0x3A,uint8_t(com->S)); //CLICK THRESHOLD
|
||
|
accelerometer_recv(0x32);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
#if FEATURE_DITTO_PRINTING
|
||
|
case 280: // M280
|
||
|
if(com->hasS()) // Set ditto mode S: 0 = off, 1 = 1 extra extruder, 2 = 2 extra extruder, 3 = 3 extra extruders
|
||
|
{
|
||
|
Extruder::dittoMode = com->S;
|
||
|
}
|
||
|
break;
|
||
|
#endif
|
||
|
case 281: // Trigger watchdog
|
||
|
#if FEATURE_WATCHDOG
|
||
|
{
|
||
|
Com::printInfoFLN(PSTR("Triggering watchdog. If activated, the printer will reset."));
|
||
|
Printer::kill(false);
|
||
|
HAL::delayMilliseconds(200); // write output, make sure heaters are off for safety
|
||
|
InterruptProtectedBlock noInts;
|
||
|
while(1) {} // Endless loop
|
||
|
}
|
||
|
#else
|
||
|
Com::printInfoFLN(PSTR("Watchdog feature was not compiled into this version!"));
|
||
|
#endif
|
||
|
break;
|
||
|
#if defined(BEEPER_PIN) && 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;
|
||
|
#endif
|
||
|
case 302: // M302 S<0 or 1> - allow cold extrusion. Without S parameter it will allow. S1 will disallow.
|
||
|
Printer::setColdExtrusionAllowed(!com->hasS() || (com->hasS() && com->S != 0));
|
||
|
break;
|
||
|
case 303: // M303
|
||
|
{
|
||
|
#if defined(TEMP_PID) && NUM_TEMPERATURE_LOOPS>0
|
||
|
int temp = 150;
|
||
|
int cont = 0;
|
||
|
if(com->hasS()) temp = com->S;
|
||
|
if(com->hasP()) cont = com->P;
|
||
|
if(cont>=NUM_TEMPERATURE_LOOPS) cont = NUM_TEMPERATURE_LOOPS;
|
||
|
tempController[cont]->autotunePID(temp,cont,com->hasX());
|
||
|
#endif
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
#if FEATURE_AUTOLEVEL
|
||
|
case 320: // M320 Activate autolevel
|
||
|
Printer::setAutolevelActive(true);
|
||
|
if(com->hasS() && com->S)
|
||
|
{
|
||
|
EEPROM::storeDataIntoEEPROM();
|
||
|
}
|
||
|
break;
|
||
|
case 321: // M321 Deactivate autoleveling
|
||
|
Printer::setAutolevelActive(false);
|
||
|
if(com->hasS() && com->S)
|
||
|
{
|
||
|
if(com->S == 3)
|
||
|
Printer::resetTransformationMatrix(false);
|
||
|
EEPROM::storeDataIntoEEPROM();
|
||
|
}
|
||
|
break;
|
||
|
case 322: // M322 Reset autoeveling matrix
|
||
|
Printer::resetTransformationMatrix(false);
|
||
|
if(com->hasS() && com->S)
|
||
|
{
|
||
|
EEPROM::storeDataIntoEEPROM();
|
||
|
}
|
||
|
break;
|
||
|
#endif // FEATURE_AUTOLEVEL
|
||
|
#if DISTORTION_CORRECTION
|
||
|
case 323: // M323 S0/S1 enable disable distortion correction P0 = not permanent, P1 = permanent = default
|
||
|
if(com->hasS())
|
||
|
{
|
||
|
if(com->S > 0)
|
||
|
Printer::distortion.enable(!com->hasP() || com->P == 1);
|
||
|
else
|
||
|
Printer::distortion.disable(!com->hasP() || com->P == 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Printer::distortion.reportStatus();
|
||
|
}
|
||
|
break;
|
||
|
#endif // DISTORTION_CORRECTION
|
||
|
#if FEATURE_SERVO
|
||
|
case 340: // M340
|
||
|
if(com->hasP() && com->P<4 && com->P>=0)
|
||
|
{
|
||
|
int s = 0;
|
||
|
if(com->hasS())
|
||
|
s = com->S;
|
||
|
HAL::servoMicroseconds(com->P,s);
|
||
|
}
|
||
|
break;
|
||
|
#endif // FEATURE_SERVO
|
||
|
case 350: // M350 Set microstepping mode. Warning: Steps per unit remains unchanged. S code sets stepping mode for all drivers.
|
||
|
{
|
||
|
OUT_P_LN("Set Microstepping");
|
||
|
#if defined(X_MS1_PIN) && X_MS1_PIN > -1
|
||
|
if(com->hasS()) for(int i = 0; i <= 4; i++) microstepMode(i, com->S);
|
||
|
if(com->hasX()) microstepMode(0, (uint8_t)com->X);
|
||
|
if(com->hasY()) microstepMode(1, (uint8_t)com->Y);
|
||
|
if(com->hasZ()) microstepMode(2, (uint8_t)com->Z);
|
||
|
if(com->hasE()) microstepMode(3, (uint8_t)com->E);
|
||
|
if(com->hasP()) microstepMode(4, com->P); // Original B but is not supported here
|
||
|
microstepReadings();
|
||
|
#endif
|
||
|
}
|
||
|
break;
|
||
|
case 355: // M355 S<0/1> - Turn case light on/off, no S = report status
|
||
|
if(com->hasS()) {
|
||
|
Printer::setCaseLight(com->S);
|
||
|
} else
|
||
|
Printer::reportCaseLightStatus();
|
||
|
break;
|
||
|
case 360: // M360 - show configuration
|
||
|
Printer::showConfiguration();
|
||
|
break;
|
||
|
case 400: // M400 Finish all moves
|
||
|
Commands::waitUntilEndOfAllMoves();
|
||
|
break;
|
||
|
case 401: // M401 Memory position
|
||
|
Printer::MemoryPosition();
|
||
|
break;
|
||
|
case 402: // M402 Go to stored position
|
||
|
Printer::GoToMemoryPosition(com->hasX(),com->hasY(),com->hasZ(),com->hasE(),(com->hasF() ? com->F : Printer::feedrate));
|
||
|
break;
|
||
|
case 500: // M500
|
||
|
{
|
||
|
#if EEPROM_MODE != 0
|
||
|
EEPROM::storeDataIntoEEPROM(false);
|
||
|
Com::printInfoFLN(Com::tConfigStoredEEPROM);
|
||
|
#else
|
||
|
Com::printErrorFLN(Com::tNoEEPROMSupport);
|
||
|
#endif
|
||
|
}
|
||
|
break;
|
||
|
case 501: // M501
|
||
|
{
|
||
|
#if EEPROM_MODE != 0
|
||
|
EEPROM::readDataFromEEPROM();
|
||
|
Extruder::selectExtruderById(Extruder::current->id);
|
||
|
Com::printInfoFLN(Com::tConfigLoadedEEPROM);
|
||
|
#else
|
||
|
Com::printErrorFLN(Com::tNoEEPROMSupport);
|
||
|
#endif
|
||
|
}
|
||
|
break;
|
||
|
case 502: // M502
|
||
|
EEPROM::restoreEEPROMSettingsFromConfiguration();
|
||
|
break;
|
||
|
|
||
|
#ifdef DEBUG_QUEUE_MOVE
|
||
|
case 533: // M533 Write move data
|
||
|
Com::printF(PSTR("Buf:"),(int)PrintLine::linesCount);
|
||
|
Com::printF(PSTR(",LP:"),(int)PrintLine::linesPos);
|
||
|
Com::printFLN(PSTR(",WP:"),(int)PrintLine::linesWritePos);
|
||
|
if(PrintLine::cur == NULL)
|
||
|
{
|
||
|
Com::printFLN(PSTR("No move"));
|
||
|
if(PrintLine::linesCount>0)
|
||
|
{
|
||
|
PrintLine &cur = PrintLine::lines[PrintLine::linesPos];
|
||
|
Com::printF(PSTR("JFlags:"),(int)cur.joinFlags);
|
||
|
Com::printFLN(PSTR("Flags:"),(int)cur.flags);
|
||
|
if(cur.isWarmUp())
|
||
|
{
|
||
|
Com::printFLN(PSTR("warmup:"),(int)cur.getWaitForXLinesFilled());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Com::printF(PSTR("Rem:"),PrintLine::cur->stepsRemaining);
|
||
|
Com::printFLN(PSTR("Int:"),Printer::interval);
|
||
|
}
|
||
|
break;
|
||
|
#endif // DEBUG_QUEUE_MOVE
|
||
|
#ifdef DEBUG_SEGMENT_LENGTH
|
||
|
case 534: // M534
|
||
|
Com::printFLN(PSTR("Max. segment size:"),Printer::maxRealSegmentLength);
|
||
|
if(com->hasS())
|
||
|
Printer::maxRealSegmentLength = 0;
|
||
|
break;
|
||
|
#endif
|
||
|
#ifdef DEBUG_REAL_JERK
|
||
|
Com::printFLN(PSTR("Max. jerk measured:"),Printer::maxRealJerk);
|
||
|
if(com->hasS())
|
||
|
Printer::maxRealJerk = 0;
|
||
|
break;
|
||
|
#endif
|
||
|
/* case 535: // M535
|
||
|
Com::printF(PSTR("Last commanded position:"),Printer::lastCmdPos[X_AXIS]);
|
||
|
Com::printF(Com::tComma,Printer::lastCmdPos[Y_AXIS]);
|
||
|
Com::printFLN(Com::tComma,Printer::lastCmdPos[Z_AXIS]);
|
||
|
Com::printF(PSTR("Current position:"),Printer::currentPosition[X_AXIS]);
|
||
|
Com::printF(Com::tComma,Printer::currentPosition[Y_AXIS]);
|
||
|
Com::printFLN(Com::tComma,Printer::currentPosition[Z_AXIS]);
|
||
|
Com::printF(PSTR("Position steps:"),Printer::currentPositionSteps[X_AXIS]);
|
||
|
Com::printF(Com::tComma,Printer::currentPositionSteps[Y_AXIS]);
|
||
|
Com::printFLN(Com::tComma,Printer::currentPositionSteps[Z_AXIS]);
|
||
|
#if NONLINEAR_SYSTEM
|
||
|
Com::printF(PSTR("Nonlin. position steps:"),Printer::currentDeltaPositionSteps[A_TOWER]);
|
||
|
Com::printF(Com::tComma,Printer::currentDeltaPositionSteps[B_TOWER]);
|
||
|
Com::printFLN(Com::tComma,Printer::currentDeltaPositionSteps[C_TOWER]);
|
||
|
#endif // NONLINEAR_SYSTEM
|
||
|
break;*/
|
||
|
/* case 700: // M700 test new square root function
|
||
|
if(com->hasS())
|
||
|
Com::printFLN(Com::tInfo,(int32_t)HAL::integerSqrt(com->S));
|
||
|
break;*/
|
||
|
#if FEATURE_CONTROLLER != NO_CONTROLLER && FEATURE_RETRACTION
|
||
|
case 600:
|
||
|
uid.executeAction(UI_ACTION_WIZARD_FILAMENTCHANGE, true);
|
||
|
break;
|
||
|
#endif
|
||
|
case 908: // M908 Control digital trimpot directly.
|
||
|
{
|
||
|
#if STEPPER_CURRENT_CONTROL != CURRENT_CONTROL_MANUAL
|
||
|
Com::printFLN(PSTR("Setting motor current..."));
|
||
|
uint8_t channel,current;
|
||
|
if(com->hasP() && com->hasS())
|
||
|
setMotorCurrent((uint8_t)com->P, (unsigned int)com->S);
|
||
|
#endif
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
if(Printer::debugErrors())
|
||
|
{
|
||
|
Com::printF(Com::tUnknownCommand);
|
||
|
com->printCommand();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief Execute the command stored in com.
|
||
|
*/
|
||
|
void Commands::executeGCode(GCode *com)
|
||
|
{
|
||
|
if (INCLUDE_DEBUG_COMMUNICATION)
|
||
|
{
|
||
|
if(Printer::debugCommunication())
|
||
|
{
|
||
|
if(com->hasG() || (com->hasM() && com->M != 111))
|
||
|
{
|
||
|
previousMillisCmd = HAL::timeInMilliseconds();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if(com->hasG()) processGCode(com);
|
||
|
else if(com->hasM()) processMCode(com);
|
||
|
else if(com->hasT()) // Process T code
|
||
|
{
|
||
|
Commands::waitUntilEndOfAllMoves();
|
||
|
Extruder::selectExtruderById(com->T);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(Printer::debugErrors())
|
||
|
{
|
||
|
Com::printF(Com::tUnknownCommand);
|
||
|
com->printCommand();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Commands::emergencyStop()
|
||
|
{
|
||
|
#if defined(KILL_METHOD) && KILL_METHOD == 1
|
||
|
HAL::resetHardware();
|
||
|
#else
|
||
|
//HAL::forbidInterrupts(); // Don't allow interrupts to do their work
|
||
|
Printer::kill(false);
|
||
|
Extruder::manageTemperatures();
|
||
|
for(uint8_t i = 0; i < NUM_EXTRUDER + 3; i++)
|
||
|
pwm_pos[i] = 0;
|
||
|
#if EXT0_HEATER_PIN>-1
|
||
|
WRITE(EXT0_HEATER_PIN,HEATER_PINS_INVERTED);
|
||
|
#endif
|
||
|
/*
|
||
|
#if defined(EXT1_HEATER_PIN) && EXT1_HEATER_PIN>-1 && NUM_EXTRUDER>1
|
||
|
WRITE(EXT1_HEATER_PIN,HEATER_PINS_INVERTED);
|
||
|
#endif
|
||
|
*/
|
||
|
#if defined(EXT2_HEATER_PIN) && EXT2_HEATER_PIN>-1 && NUM_EXTRUDER>2
|
||
|
WRITE(EXT2_HEATER_PIN,HEATER_PINS_INVERTED);
|
||
|
#endif
|
||
|
#if defined(EXT3_HEATER_PIN) && EXT3_HEATER_PIN>-1 && NUM_EXTRUDER>3
|
||
|
WRITE(EXT3_HEATER_PIN,HEATER_PINS_INVERTED);
|
||
|
#endif
|
||
|
#if defined(EXT4_HEATER_PIN) && EXT4_HEATER_PIN>-1 && NUM_EXTRUDER>4
|
||
|
WRITE(EXT4_HEATER_PIN,HEATER_PINS_INVERTED);
|
||
|
#endif
|
||
|
#if defined(EXT5_HEATER_PIN) && EXT5_HEATER_PIN>-1 && NUM_EXTRUDER>5
|
||
|
WRITE(EXT5_HEATER_PIN,HEATER_PINS_INVERTED);
|
||
|
#endif
|
||
|
#if FAN_PIN>-1 && FEATURE_FAN_CONTROL
|
||
|
WRITE(FAN_PIN,0);
|
||
|
#endif
|
||
|
#if HEATED_BED_HEATER_PIN>-1
|
||
|
WRITE(HEATED_BED_HEATER_PIN,HEATER_PINS_INVERTED);
|
||
|
#endif
|
||
|
HAL::delayMilliseconds(200);
|
||
|
InterruptProtectedBlock noInts;
|
||
|
while(1) {}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void Commands::checkFreeMemory()
|
||
|
{
|
||
|
int newfree = HAL::getFreeRam();
|
||
|
if(newfree < lowestRAMValue)
|
||
|
lowestRAMValue = newfree;
|
||
|
}
|
||
|
|
||
|
void Commands::writeLowestFreeRAM()
|
||
|
{
|
||
|
if(lowestRAMValueSend>lowestRAMValue)
|
||
|
{
|
||
|
lowestRAMValueSend = lowestRAMValue;
|
||
|
Com::printFLN(Com::tFreeRAM, lowestRAMValue);
|
||
|
}
|
||
|
}
|
||
|
|