Add the socalled "Babystepping" feature.

It is a realtime control over the head position via the LCD menu system that works _while_ printing.
Using it, one can e.g. tune the z-position in realtime, while printing the first layer.
Also, lost steps can be manually added/removed, but thats not the prime feature.
Stuff is placed into the Tune->Babystep *

It is not possible to have realtime control via gcode sending due to the buffering, so I did not include a gcode yet. However, it could be added, but it movements will not be realtime then.

Historically, a very similar thing was implemented for the "Kaamermaker" project, while Joris was babysitting his offspring, hence the name.

say goodby to fuddling around with the z-axis.
This commit is contained in:
bkubicek 2013-10-06 21:14:51 +02:00
parent bca353cc12
commit d147a057ac
6 changed files with 226 additions and 1 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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