From 5f9ae5b087d0074c242fd7edb3de9bbe9e253da8 Mon Sep 17 00:00:00 2001 From: Markus Hitter Date: Sun, 4 Mar 2012 21:23:50 +0100 Subject: [PATCH] Implement M82/M83 and handle relative movements entirely different. Instead of converting them to absolute first, then back to relative and having all the fuzz with working on the queue's start vs. working at the queue's end, mark a movement as relative and use this directly. --- dda.c | 71 ++++++++++++++++++++---------- dda.h | 6 +++ gcode_parse.c | 12 +++-- gcode_parse.h | 1 - gcode_process.c | 115 +++++++++++++++++++++++++++++++++--------------- home.c | 12 ++--- mendel.c | 3 ++ 7 files changed, 146 insertions(+), 74 deletions(-) diff --git a/dda.c b/dda.c index 48630d9..bb122b6 100644 --- a/dda.c +++ b/dda.c @@ -222,28 +222,55 @@ void dda_create(DDA *dda, TARGET *target) { // we end at the passed target memcpy(&(dda->endpoint), target, sizeof(TARGET)); - x_delta_um = (uint32_t)labs(target->X - startpoint.X); - y_delta_um = (uint32_t)labs(target->Y - startpoint.Y); - z_delta_um = (uint32_t)labs(target->Z - startpoint.Z); - e_delta_um = (uint32_t)labs(target->E - startpoint.E); +// TODO TODO: We should really make up a loop for all axes. +// Think of what happens when a sixth axis (multi colour extruder) +// appears? + if (target->all_relative) { + x_delta_um = labs(target->X); + um_to_steps_x(dda->x_delta, x_delta_um); + dda->x_direction = (target->X < 0)?1:0; - um_to_steps_x(steps, target->X); - dda->x_delta = labs(steps - startpoint_steps.X); - startpoint_steps.X = steps; - um_to_steps_y(steps, target->Y); - dda->y_delta = labs(steps - startpoint_steps.Y); - startpoint_steps.Y = steps; - um_to_steps_z(steps, target->Z); - dda->z_delta = labs(steps - startpoint_steps.Z); - startpoint_steps.Z = steps; - um_to_steps_e(steps, target->E); - dda->e_delta = labs(steps - startpoint_steps.E); - startpoint_steps.E = steps; + y_delta_um = labs(target->Y); + um_to_steps_y(dda->y_delta, y_delta_um); + dda->y_direction = (target->Y < 0)?1:0; - dda->x_direction = (target->X >= startpoint.X)?1:0; - dda->y_direction = (target->Y >= startpoint.Y)?1:0; - dda->z_direction = (target->Z >= startpoint.Z)?1:0; - dda->e_direction = (target->E >= startpoint.E)?1:0; + z_delta_um = labs(target->Z); + um_to_steps_z(dda->z_delta, z_delta_um); + dda->z_direction = (target->Z < 0)?1:0; + } + else { + x_delta_um = (uint32_t)labs(target->X - startpoint.X); + y_delta_um = (uint32_t)labs(target->Y - startpoint.Y); + z_delta_um = (uint32_t)labs(target->Z - startpoint.Z); + + um_to_steps_x(steps, target->X); + dda->x_delta = labs(steps - startpoint_steps.X); + startpoint_steps.X = steps; + um_to_steps_y(steps, target->Y); + dda->y_delta = labs(steps - startpoint_steps.Y); + startpoint_steps.Y = steps; + um_to_steps_z(steps, target->Z); + dda->z_delta = labs(steps - startpoint_steps.Z); + startpoint_steps.Z = steps; + + dda->x_direction = (target->X >= startpoint.X)?1:0; + dda->y_direction = (target->Y >= startpoint.Y)?1:0; + dda->z_direction = (target->Z >= startpoint.Z)?1:0; + } + + // This if() matches Sprinter's behaviour as of March 2012. + if (target->all_relative || target->e_relative) { + e_delta_um = labs(target->E); + um_to_steps_e(dda->e_delta, e_delta_um); + dda->e_direction = (target->E < 0)?1:0; + } + else { + e_delta_um = (uint32_t)labs(target->E - startpoint.E); + um_to_steps_e(steps, target->E); + dda->e_delta = labs(steps - startpoint_steps.E); + startpoint_steps.E = steps; + dda->e_direction = (target->E >= startpoint.E)?1:0; + } if (DEBUG_DDA && (debug_flags & DEBUG_DDA)) sersendf_P(PSTR("%ld,%ld,%ld,%ld] ["), target->X - startpoint.X, target->Y - startpoint.Y, target->Z - startpoint.Z, target->E - startpoint.E); @@ -455,10 +482,6 @@ void dda_create(DDA *dda, TARGET *target) { // next dda starts where we finish memcpy(&startpoint, target, sizeof(TARGET)); - // if E is relative, reset it here - #ifndef E_ABSOLUTE - startpoint.E = startpoint_steps.E = 0; - #endif } /*! Start a prepared DDA diff --git a/dda.h b/dda.h index 463d452..508893f 100644 --- a/dda.h +++ b/dda.h @@ -97,11 +97,17 @@ X, Y, Z and E are in micrometers unless explcitely stated. F is in mm/min. */ typedef struct { +// TODO TODO: We should really make up a loop for all axes. +// Think of what happens when a sixth axis (multi colour extruder) +// appears? int32_t X; int32_t Y; int32_t Z; int32_t E; uint32_t F; + + uint8_t all_relative :1; ///< bool: relative coordinates? + uint8_t e_relative :1; ///< bool: e axis relative? Overrides all_relative } TARGET; /** diff --git a/gcode_parse.c b/gcode_parse.c index e2c16f7..2c63649 100644 --- a/gcode_parse.c +++ b/gcode_parse.c @@ -75,6 +75,8 @@ static int32_t decfloat_to_int(decfloat *df, uint32_t multiplicand) { return df->sign ? -(int32_t)r : (int32_t)r; } +// TODO TODO: write a gcode_init(), next_target is used uninitialised. For a hint on what to do, see line 340ff. + /// Character Received - add it to our command /// \param c the next character to process void gcode_parse_char(uint8_t c) { @@ -344,16 +346,12 @@ void gcode_parse_char(uint8_t c) { next_target.seen_G = 1; next_target.G = 1; - if (next_target.option_relative) { + if (next_target.target.all_relative) { next_target.target.X = next_target.target.Y = next_target.target.Z = 0; - #ifdef E_ABSOLUTE - next_target.target.E = 0; - #endif } - #ifndef E_ABSOLUTE - // E always relative + if (next_target.target.all_relative || next_target.target.e_relative) { next_target.target.E = 0; - #endif + } } } diff --git a/gcode_parse.h b/gcode_parse.h index 749cf3d..298eb17 100644 --- a/gcode_parse.h +++ b/gcode_parse.h @@ -40,7 +40,6 @@ typedef struct { uint8_t seen_checksum :1; ///< seen a checksum? uint8_t seen_semi_comment :1; ///< seen a semicolon? uint8_t seen_parens_comment :1; ///< seen an open parenthesis - uint8_t option_relative :1; ///< relative or absolute coordinates? uint8_t option_inches :1; ///< inches or millimeters? }; uint16_t flags; diff --git a/gcode_process.c b/gcode_process.c index c5e28dd..8941bf7 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -41,9 +41,7 @@ uint8_t next_tool; #if E_STARTSTOP_STEPS > 0 /// move E by a certain amount at a certain speed static void SpecialMoveE(int32_t e, uint32_t f) { - TARGET t = startpoint; - t.E += e; - t.F = f; + TARGET t = { 0L, 0L, 0L, e, f, 1, 1 }; enqueue(&t); } #endif /* E_STARTSTOP_STEPS > 0 */ @@ -61,45 +59,66 @@ static void SpecialMoveE(int32_t e, uint32_t f) { void process_gcode_command() { uint32_t backup_f; - // convert relative to absolute - if (next_target.option_relative) { - next_target.target.X += startpoint.X; - next_target.target.Y += startpoint.Y; - next_target.target.Z += startpoint.Z; - #ifdef E_ABSOLUTE - next_target.target.E += startpoint.E; - #endif - } - // E ALWAYS relative, otherwise we overflow our registers after only a few layers - // next_target.target.E += startpoint.E; - // easier way to do this - // startpoint.E = 0; - // moved to dda.c, end of dda_create() and dda_queue.c, next_move() - // implement axis limits #ifdef X_MIN - if (next_target.target.X < X_MIN * 1000.) - next_target.target.X = X_MIN * 1000.; + if (next_target.target.all_relative) { + if (next_target.target.X += startpoint.X < X_MIN * 1000.) + next_target.target.X = X_MIN * 1000. + startpoint.X; + } + else { + if (next_target.target.X < X_MIN * 1000.) + next_target.target.X = X_MIN * 1000.; + } #endif #ifdef X_MAX - if (next_target.target.X > X_MAX * 1000.) - next_target.target.X = X_MAX * 1000.; + if (next_target.target.all_relative) { + if (next_target.target.X += startpoint.X > X_MAX * 1000.) + next_target.target.X = X_MIN * 1000. - startpoint.X; + } + else { + if (next_target.target.X > X_MAX * 1000.) + next_target.target.X = X_MAX * 1000.; + } #endif #ifdef Y_MIN - if (next_target.target.Y < Y_MIN * 1000.) - next_target.target.Y = Y_MIN * 1000.; + if (next_target.target.all_relative) { + if (next_target.target.Y += startpoint.Y < Y_MIN * 1000.) + next_target.target.Y = Y_MIN * 1000. + startpoint.Y; + } + else { + if (next_target.target.Y < Y_MIN * 1000.) + next_target.target.Y = Y_MIN * 1000.; + } #endif #ifdef Y_MAX - if (next_target.target.Y > Y_MAX * 1000.) - next_target.target.Y = Y_MAX * 1000.; + if (next_target.target.all_relative) { + if (next_target.target.Y += startpoint.Y > Y_MAX * 1000.) + next_target.target.Y = Y_MIN * 1000. - startpoint.Y; + } + else { + if (next_target.target.Y > Y_MAX * 1000.) + next_target.target.Y = Y_MAX * 1000.; + } #endif #ifdef Z_MIN - if (next_target.target.Z < Z_MIN * 1000.) - next_target.target.Z = Z_MIN * 1000.; + if (next_target.target.all_relative) { + if (next_target.target.Z += startpoint.Z < Z_MIN * 1000.) + next_target.target.Z = Z_MIN * 1000. + startpoint.Z; + } + else { + if (next_target.target.Z < Z_MIN * 1000.) + next_target.target.Z = Z_MIN * 1000.; + } #endif #ifdef Z_MAX - if (next_target.target.Z > Z_MAX * 1000.) - next_target.target.Z = Z_MAX * 1000.; + if (next_target.target.all_relative) { + if (next_target.target.Z += startpoint.Z > Z_MAX * 1000.) + next_target.target.Z = Z_MIN * 1000. - startpoint.Z; + } + else { + if (next_target.target.Z > Z_MAX * 1000.) + next_target.target.Z = Z_MAX * 1000.; + } #endif @@ -115,6 +134,7 @@ void process_gcode_command() { next_tool = next_target.T; } +// TODO TODO: really? // if we didn't see an axis word, set it to startpoint. this fixes incorrect moves after homing if (next_target.seen_X == 0) next_target.target.X = startpoint.X; @@ -253,9 +273,15 @@ void process_gcode_command() { //? //? Example: G90 //? - //? All coordinates from now on are absolute relative to the origin of the machine. (This is the RepRap default.) + //? All coordinates from now on are absolute relative to the origin + //? of the machine. This is the RepRap default. //? - next_target.option_relative = 0; + + // No queue_wait() needed. + next_target.target.all_relative = 0; + // TODO: What's about startpoint, next_target an friends? + // What should a machine do when returning from relative + // to absolute mode? break; case 91: @@ -265,7 +291,9 @@ void process_gcode_command() { //? //? All coordinates from now on are relative to the last position. //? - next_target.option_relative = 1; + + // No queue_wait() needed. + next_target.target.all_relative = 1; break; case 92: @@ -393,11 +421,25 @@ void process_gcode_command() { tool = next_tool; break; - // M82 - Set E codes absolute (default) - // not implemented + case 82: + //? --- M82 - Set E codes absolute --- + //? + //? This is the default. M82/M82 is not documented in the + //? RepRap wiki, behaviours was taken from Strinter as of March 2012. + + // No wait_queue() needed. + next_target.target.e_relative = 0; + break; // M83 - Set E codes relative while in Absolute Coordinates (G90) mode - // not implemented + case 83: + //? --- M83 - Set E codes relative --- + //? + //? Counterpart to M82. + + // No wait_queue() needed. + next_target.target.e_relative = 1; + break; // M84- stop idle hold case 84: @@ -407,6 +449,7 @@ void process_gcode_command() { z_disable(); e_disable(); break; + // M3/M101- extruder on case 3: case 101: diff --git a/home.c b/home.c index 325b1c3..443b72a 100644 --- a/home.c +++ b/home.c @@ -34,7 +34,7 @@ void home() { /// find X MIN endstop void home_x_negative() { #if defined X_MIN_PIN - TARGET t = startpoint; + TARGET t = { 0L, 0L, 0L, 0L, 0L, 1, 1 }; t.X = -1000000; #ifdef SLOW_HOMING @@ -70,7 +70,7 @@ void home_x_positive() { #warning X_MAX_PIN defined, but not X_MAX. home_x_positive() disabled. #endif #if defined X_MAX_PIN && defined X_MAX - TARGET t = startpoint; + TARGET t = { 0L, 0L, 0L, 0L, 0L, 1, 1 }; t.X = +1000000; #ifdef SLOW_HOMING @@ -104,7 +104,7 @@ void home_x_positive() { /// fund Y MIN endstop void home_y_negative() { #if defined Y_MIN_PIN - TARGET t = startpoint; + TARGET t = { 0L, 0L, 0L, 0L, 0L, 1, 1 }; t.Y = -1000000; #ifdef SLOW_HOMING @@ -140,7 +140,7 @@ void home_y_positive() { #warning Y_MAX_PIN defined, but not Y_MAX. home_y_positive() disabled. #endif #if defined Y_MAX_PIN && defined Y_MAX - TARGET t = startpoint; + TARGET t = { 0L, 0L, 0L, 0L, 0L, 1, 1 }; t.Y = +1000000; #ifdef SLOW_HOMING @@ -174,7 +174,7 @@ void home_y_positive() { /// find Z MIN endstop void home_z_negative() { #if defined Z_MIN_PIN - TARGET t = startpoint; + TARGET t = { 0L, 0L, 0L, 0L, 0L, 1, 1 }; t.Z = -1000000; #ifdef SLOW_HOMING @@ -211,7 +211,7 @@ void home_z_positive() { #warning Z_MAX_PIN defined, but not Z_MAX. home_z_positive() disabled. #endif #if defined Z_MAX_PIN && defined Z_MAX - TARGET t = startpoint; + TARGET t = { 0L, 0L, 0L, 0L, 0L, 1, 1 }; t.Z = +1000000; #ifdef SLOW_HOMING diff --git a/mendel.c b/mendel.c index efbfcd4..8282164 100644 --- a/mendel.c +++ b/mendel.c @@ -274,6 +274,9 @@ void init(void) { // set up serial serial_init(); + // set up G-code parsing + // gcode_init(); + // set up inputs and outputs io_init();