diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 3cbe131c9..b47233a02 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -270,6 +270,17 @@ // Enable the option to stop SD printing when hitting and endstops, needs to be enabled from the LCD menu when this option is enabled. //#define ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED +// Babystepping enables the user to control the axis in tiny amounts, independently from the normal printing process +// it can e.g. be used to change z-positions in the print startup phase in realtime +// does not respect endstops! + +//#define BABYSTEPPING +//#define BABYSTEP_XY //not only z, but also XY + +#ifdef COREXY + #error BABYSTEPPING not implemented for COREXY yet. +#endif + // extruder advance constant (s2/mm3) // // advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2 diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 8b39a41d6..1dc3902b3 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -997,6 +997,116 @@ void quickStop() ENABLE_STEPPER_DRIVER_INTERRUPT(); } +#ifdef BABYSTEPPING + + +void babystep(const uint8_t axis,const bool direction) +{ + //MUST ONLY BE CALLED BY A ISR, it depends on that no other ISR interrupts this + //store initial pin states + switch(axis) + { + case X_AXIS: + { + enable_x(); + uint8_t old_x_dir_pin= READ(X_DIR_PIN); //if dualzstepper, both point to same direction. + + //setup new step + WRITE(X_DIR_PIN,(INVERT_X_DIR)^direction); + #ifdef DUAL_X_CARRIAGE + WRITE(X2_DIR_PIN,(INVERT_X_DIR)^direction); + #endif + + //perform step + WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN); + #ifdef DUAL_X_CARRIAGE + WRITE(X2_STEP_PIN, !INVERT_X_STEP_PIN); + #endif + { + float x=1./float(axis+1)/float(axis+2); //wait a tiny bit + } + WRITE(X_STEP_PIN, INVERT_X_STEP_PIN); + #ifdef DUAL_X_CARRIAGE + WRITE(X2_STEP_PIN, INVERT_X_STEP_PIN); + #endif + + //get old pin state back. + WRITE(X_DIR_PIN,old_x_dir_pin); + #ifdef DUAL_X_CARRIAGE + WRITE(X2_DIR_PIN,old_x_dir_pin); + #endif + + } + break; + case Y_AXIS: + { + enable_y(); + uint8_t old_y_dir_pin= READ(Y_DIR_PIN); //if dualzstepper, both point to same direction. + + //setup new step + WRITE(Y_DIR_PIN,(INVERT_Y_DIR)^direction); + #ifdef DUAL_Y_CARRIAGE + WRITE(Y2_DIR_PIN,(INVERT_Y_DIR)^direction); + #endif + + //perform step + WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN); + #ifdef DUAL_Y_CARRIAGE + WRITE(Y2_STEP_PIN, !INVERT_Y_STEP_PIN); + #endif + { + float x=1./float(axis+1)/float(axis+2); //wait a tiny bit + } + WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN); + #ifdef DUAL_Y_CARRIAGE + WRITE(Y2_STEP_PIN, INVERT_Y_STEP_PIN); + #endif + + //get old pin state back. + WRITE(Y_DIR_PIN,old_y_dir_pin); + #ifdef DUAL_Y_CARRIAGE + WRITE(Y2_DIR_PIN,old_y_dir_pin); + #endif + + } + break; + case Z_AXIS: + { + enable_z(); + uint8_t old_z_dir_pin= READ(Z_DIR_PIN); //if dualzstepper, both point to same direction. + //setup new step + WRITE(Z_DIR_PIN,(INVERT_Z_DIR)^direction); + #ifdef Z_DUAL_STEPPER_DRIVERS + WRITE(Z2_DIR_PIN,(INVERT_Z_DIR)^direction); + #endif + //perform step + WRITE(Z_STEP_PIN, !INVERT_Z_STEP_PIN); + #ifdef Z_DUAL_STEPPER_DRIVERS + WRITE(Z2_STEP_PIN, !INVERT_Z_STEP_PIN); + #endif + //wait a tiny bit + { + float x=1./float(axis+1); //absolutely useless + } + WRITE(Z_STEP_PIN, INVERT_Z_STEP_PIN); + #ifdef Z_DUAL_STEPPER_DRIVERS + WRITE(Z2_STEP_PIN, INVERT_Z_STEP_PIN); + #endif + + //get old pin state back. + WRITE(Z_DIR_PIN,old_z_dir_pin); + #ifdef Z_DUAL_STEPPER_DRIVERS + WRITE(Z2_DIR_PIN,old_z_dir_pin); + #endif + + } + break; + + default: break; + } +} +#endif //BABYSTEPPING + void digitalPotWrite(int address, int value) // From Arduino DigitalPotControl example { #if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1 diff --git a/Marlin/stepper.h b/Marlin/stepper.h index 82b41c90d..3a1cb0b5d 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -92,4 +92,10 @@ void digipot_current(uint8_t driver, int current); void microstep_init(); void microstep_readings(); +#ifdef BABYSTEPPING + void babystep(const uint8_t axis,const bool direction); // perform a short step with a single stepper motor, outside of any convention +#endif + + + #endif diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 9d87c54bb..decab104d 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -66,6 +66,10 @@ float current_temperature_bed = 0.0; unsigned char fanSpeedSoftPwm; #endif +#ifdef BABYSTEPPING + volatile int babystepsTodo[3]={0,0,0}; +#endif + //=========================================================================== //=============================private variables============================ //=========================================================================== @@ -1252,7 +1256,26 @@ ISR(TIMER0_COMPB_vect) bed_max_temp_error(); } #endif - } + } + +#ifdef BABYSTEPPING + for(uint8_t axis=0;axis<3;axis++) + { + int curTodo=babystepsTodo[axis]; //get rid of volatile for performance + + if(curTodo>0) + { + babystep(axis,/*fwd*/true); + babystepsTodo[axis]--; //less to do next time + } + else + if(curTodo<0) + { + babystep(axis,/*fwd*/false); + babystepsTodo[axis]++; //less to do next time + } + } +#endif //BABYSTEPPING } #ifdef PIDTEMP diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 75ffcd06b..a5974241c 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -53,6 +53,11 @@ extern float current_temperature_bed; extern float bedKp,bedKi,bedKd; #endif + +#ifdef BABYSTEPPING + extern volatile int babystepsTodo[3]; +#endif + //high level conversion routines, for use outside of temperature.cpp //inline so that there is no performance decrease. //deg=degreeCelsius diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index 05ace2d49..0a0df8f9e 100644 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -322,6 +322,68 @@ static void lcd_cooldown() lcd_return_to_status(); } +#ifdef BABYSTEPPING +static void lcd_babystep_x() +{ + if (encoderPosition != 0) + { + babystepsTodo[X_AXIS]+=(int)encoderPosition; + encoderPosition=0; + lcdDrawUpdate = 1; + } + if (lcdDrawUpdate) + { + lcd_implementation_drawedit(PSTR("Babystepping X"),""); + } + if (LCD_CLICKED) + { + lcd_quick_feedback(); + currentMenu = lcd_tune_menu; + encoderPosition = 0; + } +} + +static void lcd_babystep_y() +{ + if (encoderPosition != 0) + { + babystepsTodo[Y_AXIS]+=(int)encoderPosition; + encoderPosition=0; + lcdDrawUpdate = 1; + } + if (lcdDrawUpdate) + { + lcd_implementation_drawedit(PSTR("Babystepping Y"),""); + } + if (LCD_CLICKED) + { + lcd_quick_feedback(); + currentMenu = lcd_tune_menu; + encoderPosition = 0; + } +} + +static void lcd_babystep_z() +{ + if (encoderPosition != 0) + { + babystepsTodo[Z_AXIS]+=(int)encoderPosition; + encoderPosition=0; + lcdDrawUpdate = 1; + } + if (lcdDrawUpdate) + { + lcd_implementation_drawedit(PSTR("Babystepping Z"),""); + } + if (LCD_CLICKED) + { + lcd_quick_feedback(); + currentMenu = lcd_tune_menu; + encoderPosition = 0; + } +} +#endif //BABYSTEPPING + static void lcd_tune_menu() { START_MENU(); @@ -339,6 +401,14 @@ static void lcd_tune_menu() #endif MENU_ITEM_EDIT(int3, MSG_FAN_SPEED, &fanSpeed, 0, 255); MENU_ITEM_EDIT(int3, MSG_FLOW, &extrudemultiply, 10, 999); + +#ifdef BABYSTEPPING + #ifdef BABYSTEP_XY + MENU_ITEM(submenu, "Babystep X", lcd_babystep_x); + MENU_ITEM(submenu, "Babystep Y", lcd_babystep_y); + #endif //BABYSTEP_XY + MENU_ITEM(submenu, "Babystep Z", lcd_babystep_z); +#endif #ifdef FILAMENTCHANGEENABLE MENU_ITEM(gcode, MSG_FILAMENTCHANGE, PSTR("M600")); #endif