From ff82489da7773dd9a90e9a0e5bebcd3361411df2 Mon Sep 17 00:00:00 2001 From: Sonny Jeon Date: Mon, 8 Oct 2012 15:57:58 -0600 Subject: [PATCH] Limit pin internal pull-resistors enabled. Re-wrote read_double() function. Correctly changed all 'double's to 'float's. - Limit pin internal pull-resistors now enabled. Normal high operation. This will be the standard going forward. - Updated all of the 'double' variable types to 'float' to reflect what happens when compiled for the Arduino. Also done for compatibility reasons to @jgeisler0303 's Grbl simulator code. - G-code parser will now ignore 'E' exponent values, since they are reserved g-code characters for some machines. Thanks @csdexter! - The read_double() function was re-written and optimized for use in Grbl. The strtod() avr lib was removed. --- config.h | 3 +- gcode.c | 31 ++++++++-------- limits.c | 11 +++--- main.c | 2 +- motion_control.c | 44 +++++++++++------------ motion_control.h | 8 ++--- nuts_bolts.c | 93 ++++++++++++++++++++++++++++++++++++++++++------ nuts_bolts.h | 10 +++--- planner.c | 32 ++++++++--------- planner.h | 10 +++--- print.c | 2 +- print.h | 2 +- protocol.c | 2 +- settings.c | 16 ++++----- settings.h | 14 ++++---- stepper.c | 13 ++++--- 16 files changed, 183 insertions(+), 110 deletions(-) diff --git a/config.h b/config.h index 2ac197f..dd0a9dc 100755 --- a/config.h +++ b/config.h @@ -42,6 +42,7 @@ #define LIMIT_DDR DDRB #define LIMIT_PIN PINB +#define LIMIT_PORT PORTB #define X_LIMIT_BIT 1 // Uno Digital Pin 9 #define Y_LIMIT_BIT 2 // Uno Digital Pin 10 #define Z_LIMIT_BIT 3 // Uno Digital Pin 11 @@ -175,7 +176,5 @@ // Limit step rate for homing #define LIMIT_DEBOUNCE 50 // Limit switch debounce delay (in ms) -// #define LIMIT_INVERT_MASK 0 // -// #define LIMIT_NORMAL_HIGH 1 // Normal low 0 or normal high 1 #endif diff --git a/gcode.c b/gcode.c index 171eef8..e4e22d6 100755 --- a/gcode.c +++ b/gcode.c @@ -77,8 +77,8 @@ typedef struct { uint8_t program_flow; // {M0, M1, M2, M30} int8_t spindle_direction; // 1 = CW, -1 = CCW, 0 = Stop {M3, M4, M5} uint8_t coolant_mode; // 0 = Disable, 1 = Flood Enable {M8, M9} - double feed_rate, seek_rate; // Millimeters/second - double position[3]; // Where the interpreter considers the tool to be at this point in the code + float feed_rate, seek_rate; // Millimeters/second + float position[3]; // Where the interpreter considers the tool to be at this point in the code uint8_t tool; uint16_t spindle_speed; // RPM/100 uint8_t plane_axis_0, @@ -89,7 +89,7 @@ static parser_state_t gc; #define FAIL(status) gc.status_code = status; -static int next_statement(char *letter, double *double_ptr, char *line, uint8_t *char_counter); +static int next_statement(char *letter, float *float_ptr, char *line, uint8_t *char_counter); static void select_plane(uint8_t axis_0, uint8_t axis_1, uint8_t axis_2) { @@ -120,7 +120,7 @@ void gc_clear_position() clear_vector(gc.position); } -static float to_millimeters(double value) +static float to_millimeters(float value) { return(gc.inches_mode ? (value * MM_PER_INCH) : value); } @@ -133,17 +133,17 @@ uint8_t gc_execute_line(char *line) { uint8_t char_counter = 0; char letter; - double value; + float value; int int_value; uint16_t modal_group_words = 0; // Bitflag variable to track and check modal group words in block uint8_t axis_words = 0; // Bitflag to track which XYZ(ABC) parameters exist in block - double inverse_feed_rate = -1; // negative inverse_feed_rate means no inverse_feed_rate specified + float inverse_feed_rate = -1; // negative inverse_feed_rate means no inverse_feed_rate specified uint8_t absolute_override = false; // true(1) = absolute motion for this block only {G53} uint8_t non_modal_action = NON_MODAL_NONE; // Tracks the actions of modal group 0 (non-modal) - double target[3], offset[3]; + float target[3], offset[3]; clear_vector(target); // XYZ(ABC) axes parameters. clear_vector(offset); // IJK Arc offsets are incremental. Value of zero indicates no change. @@ -248,11 +248,12 @@ uint8_t gc_execute_line(char *line) /* Pass 2: Parameters. All units converted according to current block commands. Position parameters are converted and flagged to indicate a change. These can have multiple connotations for different commands. Each will be converted to their proper value upon execution. */ - double p = 0, r = 0; + float p = 0, r = 0; uint8_t l = 0; char_counter = 0; while(next_statement(&letter, &value, line, &char_counter)) { switch(letter) { + case 'G': case 'M': break; // Ignore command statements case 'F': if (value <= 0) { FAIL(STATUS_INVALID_COMMAND); } // Must be greater than zero if (gc.inverse_feed_rate_mode) { @@ -276,6 +277,7 @@ uint8_t gc_execute_line(char *line) case 'X': target[X_AXIS] = to_millimeters(value); bit_true(axis_words,bit(X_AXIS)); break; case 'Y': target[Y_AXIS] = to_millimeters(value); bit_true(axis_words,bit(Y_AXIS)); break; case 'Z': target[Z_AXIS] = to_millimeters(value); bit_true(axis_words,bit(Z_AXIS)); break; + default: FAIL(STATUS_UNSUPPORTED_STATEMENT); } } @@ -342,7 +344,6 @@ uint8_t gc_execute_line(char *line) mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], settings.default_seek_rate, false); } mc_go_home(); -// clear_vector(gc.position); // Assumes home is at [0,0,0] axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags. break; case NON_MODAL_SET_COORDINATE_OFFSET: @@ -473,11 +474,11 @@ uint8_t gc_execute_line(char *line) */ // Calculate the change in position along each selected axis - double x = target[gc.plane_axis_0]-gc.position[gc.plane_axis_0]; - double y = target[gc.plane_axis_1]-gc.position[gc.plane_axis_1]; + float x = target[gc.plane_axis_0]-gc.position[gc.plane_axis_0]; + float y = target[gc.plane_axis_1]-gc.position[gc.plane_axis_1]; clear_vector(offset); - double h_x2_div_d = -sqrt(4 * r*r - x*x - y*y)/hypot(x,y); // == -(h * 2 / d) + float 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)) { FAIL(STATUS_FLOATING_POINT_ERROR); return(gc.status_code); } @@ -535,7 +536,7 @@ uint8_t gc_execute_line(char *line) // As far as the parser is concerned, the position is now == target. In reality the // motion control system might still be processing the action and the real tool position // in any intermediate location. - memcpy(gc.position, target, sizeof(double)*3); // gc.position[] = target[]; + memcpy(gc.position, target, sizeof(float)*3); // gc.position[] = target[]; } // M0,M1,M2,M30: Perform non-running program flow actions. During a program pause, the buffer may @@ -556,7 +557,7 @@ uint8_t gc_execute_line(char *line) // Parses the next statement and leaves the counter on the first character following // the statement. Returns 1 if there was a statements, 0 if end of string was reached // or there was an error (check state.status_code). -static int next_statement(char *letter, double *double_ptr, char *line, uint8_t *char_counter) +static int next_statement(char *letter, float *float_ptr, char *line, uint8_t *char_counter) { if (line[*char_counter] == 0) { return(0); // No more statements @@ -568,7 +569,7 @@ static int next_statement(char *letter, double *double_ptr, char *line, uint8_t return(0); } (*char_counter)++; - if (!read_double(line, char_counter, double_ptr)) { + if (!read_float(line, char_counter, float_ptr)) { FAIL(STATUS_BAD_NUMBER_FORMAT); return(0); }; diff --git a/limits.c b/limits.c index 5e8bfa1..535c681 100755 --- a/limits.c +++ b/limits.c @@ -35,18 +35,19 @@ void limits_init() { - LIMIT_DDR &= ~(LIMIT_MASK); + LIMIT_DDR &= ~(LIMIT_MASK); // Input pin + LIMIT_PORT |= (LIMIT_MASK); // Enable internal pull-up resistors for normal high } // Moves all specified axes in same specified direction (positive=true, negative=false) // and at the homing rate. Homing is a special motion case, where there is only an // acceleration followed by abrupt asynchronous stops by each axes reaching their limit -// switch independently. Instead of showhorning homing cycles into the main stepper +// switch independently. Instead of shoehorning homing cycles into the main stepper // algorithm and overcomplicate things, a stripped-down, lite version of the stepper // algorithm is written here. This also lets users hack and tune this code freely for // their own particular needs without affecting the rest of Grbl. // NOTE: Only the abort runtime command can interrupt this process. -static void homing_cycle(bool x_axis, bool y_axis, bool z_axis, int8_t pos_dir, double homing_rate) +static void homing_cycle(bool x_axis, bool y_axis, bool z_axis, int8_t pos_dir, float homing_rate) { // Determine governing axes with finest step resolution per distance for the Bresenham // algorithm. This solves the issue when homing multiple axes that have different @@ -67,7 +68,7 @@ static void homing_cycle(bool x_axis, bool y_axis, bool z_axis, int8_t pos_dir, // used in the main planner to account for distance traveled when moving multiple axes. // NOTE: When axis acceleration independence is installed, this will be updated to move // all axes at their maximum acceleration and rate. - double ds = step_event_count/sqrt(x_axis+y_axis+z_axis); + float ds = step_event_count/sqrt(x_axis+y_axis+z_axis); // Compute the adjusted step rate change with each acceleration tick. (in step/min/acceleration_tick) uint32_t delta_rate = ceil( ds*settings.acceleration/(60*ACCELERATION_TICKS_PER_SECOND)); @@ -180,5 +181,5 @@ void limits_go_home() limit_switches_present & (1< #include -int read_double(char *line, uint8_t *char_counter, double *double_ptr) -{ - char *start = line + *char_counter; - char *end; - - *double_ptr = strtod(start, &end); - if(end == start) { - return(false); - }; +#define MAX_INT_DIGITS 8 // Maximum number of digits in int32 (and float) +extern float __floatunsisf (unsigned long); - *char_counter = end - line; +// Extracts a floating point value from a string. The following code is based loosely on +// the avr-libc strtod() function by Michael Stumpf and Dmitry Xmelkov and many freely +// available conversion method examples, but has been highly optimized for Grbl. For known +// CNC applications, the typical decimal value is expected to be in the range of E0 to E-4. +// Scientific notation is officially not supported by g-code, and the 'E' character may +// be a g-code word on some CNC systems. So, 'E' notation will not be recognized. +// NOTE: Thanks to Radu-Eosif Mihailescu for identifying the issues with using strtod(). +int read_float(char *line, uint8_t *char_counter, float *float_ptr) +{ + char *ptr = line + *char_counter; + unsigned char c; + + // Grab first character and increment pointer. No spaces assumed in line. + c = *ptr++; + + // Capture initial positive/minus character + bool isnegative = false; + if (c == '-') { + isnegative = true; + c = *ptr++; + } else if (c == '+') { + c = *ptr++; + } + + // Extract number into fast integer. Track decimal in terms of exponent value. + uint32_t intval = 0; + int8_t exp = 0; + uint8_t ndigit = 0; + bool isdecimal = false; + while(1) { + c -= '0'; + if (c <= 9) { + ndigit++; + if (ndigit <= MAX_INT_DIGITS) { + if (isdecimal) { exp--; } + intval = (((intval << 2) + intval) << 1) + c; // intval*10 + c + } else { + if (!(isdecimal)) { exp++; } // Drop overflow digits + } + } else if (c == (('.'-'0') & 0xff) && !(isdecimal)) { + isdecimal = true; + } else { + break; + } + c = *ptr++; + } + + // Return if no digits have been read. + if (!ndigit) { return(false); }; + + // Convert integer into floating point. + float fval; + fval = __floatunsisf(intval); + + // Apply decimal. Should perform no more than two floating point multiplications for the + // expected range of E0 to E-4. + if (fval != 0) { + while (exp <= -2) { + fval *= 0.01; + exp += 2; + } + if (exp < 0) { + fval *= 0.1; + } else if (exp > 0) { + do { + fval *= 10.0; + } while (--exp > 0); + } + } + + // Assign floating point value with correct sign. + if (isnegative) { + *float_ptr = -fval; + } else { + *float_ptr = fval; + } + + *char_counter = ptr - line - 1; // Set char_counter to next statement + return(true); } + // Delays variable defined milliseconds. Compiler compatibility fix for _delay_ms(), // which only accepts constants in future compiler releases. void delay_ms(uint16_t ms) @@ -45,6 +117,7 @@ void delay_ms(uint16_t ms) while ( ms-- ) { _delay_ms(1); } } + // Delays variable defined microseconds. Compiler compatibility fix for _delay_us(), // which only accepts constants in future compiler releases. Written to perform more // efficiently with larger delays, as the counter adds parasitic time in each iteration. diff --git a/nuts_bolts.h b/nuts_bolts.h index 5909876..e262d38 100755 --- a/nuts_bolts.h +++ b/nuts_bolts.h @@ -38,7 +38,7 @@ // Useful macros #define clear_vector(a) memset(a, 0, sizeof(a)) -#define clear_vector_double(a) memset(a, 0.0, sizeof(a)) +#define clear_vector_float(a) memset(a, 0.0, sizeof(a)) #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) @@ -74,10 +74,10 @@ typedef struct { // NOTE: This may need to be a volatile variable, if problems arise. uint8_t coord_select; // Active work coordinate system number. Default: 0=G54. - double coord_system[N_COORDINATE_SYSTEM][3]; // Work coordinate systems (G54+). Stores offset from + float coord_system[N_COORDINATE_SYSTEM][3]; // Work coordinate systems (G54+). Stores offset from // absolute machine position in mm. // Rows: Work system number (0=G54,1=G55,...5=G59), Columns: XYZ Offsets - double coord_offset[3]; // Retains the G92 coordinate offset (work coordinates) relative to + float coord_offset[3]; // Retains the G92 coordinate offset (work coordinates) relative to // machine zero in mm. volatile uint8_t cycle_start; // Cycle start flag. Set by stepper subsystem or main program. @@ -86,9 +86,9 @@ typedef struct { extern system_t sys; // Read a floating point value from a string. Line points to the input buffer, char_counter -// is the indexer pointing to the current character of the line, while double_ptr is +// is the indexer pointing to the current character of the line, while float_ptr is // a pointer to the result variable. Returns true when it succeeds -int read_double(char *line, uint8_t *char_counter, double *double_ptr); +int read_float(char *line, uint8_t *char_counter, float *float_ptr); // Delays variable-defined milliseconds. Compiler compatibility fix for _delay_ms(). void delay_ms(uint16_t ms); diff --git a/planner.c b/planner.c index 750af75..0d09cc4 100755 --- a/planner.c +++ b/planner.c @@ -46,8 +46,8 @@ typedef struct { int32_t position[3]; // The planner position of the tool in absolute steps. Kept separate // from g-code position for movements requiring multiple line motions, // i.e. arcs, canned cycles, and backlash compensation. - double previous_unit_vec[3]; // Unit vector of previous path line segment - double previous_nominal_speed; // Nominal speed of previous path line segment + float previous_unit_vec[3]; // Unit vector of previous path line segment + float previous_nominal_speed; // Nominal speed of previous path line segment } planner_t; static planner_t pl; @@ -72,7 +72,7 @@ static uint8_t prev_block_index(uint8_t block_index) // Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the // given acceleration: -static double estimate_acceleration_distance(double initial_rate, double target_rate, double acceleration) +static float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) { return( (target_rate*target_rate-initial_rate*initial_rate)/(2*acceleration) ); } @@ -91,7 +91,7 @@ static double estimate_acceleration_distance(double initial_rate, double target_ // you started at speed initial_rate and accelerated until this point and want to end at the final_rate after // a total travel of distance. This can be used to compute the intersection point between acceleration and // deceleration in the cases where the trapezoid has no plateau (i.e. never reaches maximum speed) -static double intersection_distance(double initial_rate, double final_rate, double acceleration, double distance) +static float intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) { return( (2*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/(4*acceleration) ); } @@ -102,7 +102,7 @@ static double intersection_distance(double initial_rate, double final_rate, doub // NOTE: sqrt() reimplimented here from prior version due to improved planner logic. Increases speed // in time critical computations, i.e. arcs or rapid short lines from curves. Guaranteed to not exceed // BLOCK_BUFFER_SIZE calls per planner cycle. -static double max_allowable_speed(double acceleration, double target_velocity, double distance) +static float max_allowable_speed(float acceleration, float target_velocity, float distance) { return( sqrt(target_velocity*target_velocity-2*acceleration*distance) ); } @@ -162,7 +162,7 @@ static void planner_forward_pass_kernel(block_t *previous, block_t *current, blo // If nominal length is true, max junction speed is guaranteed to be reached. No need to recheck. if (!previous->nominal_length_flag) { if (previous->entry_speed < current->entry_speed) { - double entry_speed = min( current->entry_speed, + float entry_speed = min( current->entry_speed, max_allowable_speed(-settings.acceleration,previous->entry_speed,previous->millimeters) ); // Check for junction speed change @@ -205,7 +205,7 @@ static void planner_forward_pass() // The factors represent a factor of braking and must be in the range 0.0-1.0. // This converts the planner parameters to the data required by the stepper controller. // NOTE: Final rates must be computed in terms of their respective blocks. -static void calculate_trapezoid_for_block(block_t *block, double entry_factor, double exit_factor) +static void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exit_factor) { block->initial_rate = ceil(block->nominal_rate*entry_factor); // (step/min) block->final_rate = ceil(block->nominal_rate*exit_factor); // (step/min) @@ -347,7 +347,7 @@ void plan_synchronize() // All position data passed to the planner must be in terms of machine position to keep the planner // independent of any coordinate system changes and offsets, which are handled by the g-code parser. // NOTE: Assumes buffer is available. Buffer checks are handled at a higher level by motion_control. -void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t invert_feed_rate) +void plan_buffer_line(float x, float y, float z, float feed_rate, uint8_t invert_feed_rate) { // Prepare to set up new block block_t *block = &block_buffer[block_buffer_head]; @@ -374,17 +374,17 @@ void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t in if (block->step_event_count == 0) { return; }; // Compute path vector in terms of absolute step target and current positions - double delta_mm[3]; + float delta_mm[3]; delta_mm[X_AXIS] = (target[X_AXIS]-pl.position[X_AXIS])/settings.steps_per_mm[X_AXIS]; delta_mm[Y_AXIS] = (target[Y_AXIS]-pl.position[Y_AXIS])/settings.steps_per_mm[Y_AXIS]; delta_mm[Z_AXIS] = (target[Z_AXIS]-pl.position[Z_AXIS])/settings.steps_per_mm[Z_AXIS]; block->millimeters = sqrt(delta_mm[X_AXIS]*delta_mm[X_AXIS] + delta_mm[Y_AXIS]*delta_mm[Y_AXIS] + delta_mm[Z_AXIS]*delta_mm[Z_AXIS]); - double inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides + float inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides // Calculate speed in mm/minute for each axis. No divide by zero due to previous checks. // NOTE: Minimum stepper speed is limited by MINIMUM_STEPS_PER_MINUTE in stepper.c - double inverse_minute; + float inverse_minute; if (!invert_feed_rate) { inverse_minute = feed_rate * inverse_millimeters; } else { @@ -404,7 +404,7 @@ void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t in settings.acceleration / (60 * ACCELERATION_TICKS_PER_SECOND )); // (step/min/acceleration_tick) // Compute path unit vector - double unit_vec[3]; + float unit_vec[3]; unit_vec[X_AXIS] = delta_mm[X_AXIS]*inverse_millimeters; unit_vec[Y_AXIS] = delta_mm[Y_AXIS]*inverse_millimeters; @@ -419,13 +419,13 @@ void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t in // path width or max_jerk in the previous grbl version. This approach does not actually deviate // from path, but used as a robust way to compute cornering speeds, as it takes into account the // nonlinearities of both the junction angle and junction velocity. - double vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed + float vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed // Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles. if ((block_buffer_head != block_buffer_tail) && (pl.previous_nominal_speed > 0.0)) { // Compute cosine of angle between previous and current path. (prev_unit_vec is negative) // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity. - double cos_theta = - pl.previous_unit_vec[X_AXIS] * unit_vec[X_AXIS] + float cos_theta = - pl.previous_unit_vec[X_AXIS] * unit_vec[X_AXIS] - pl.previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS] - pl.previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ; @@ -435,7 +435,7 @@ void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t in // Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds. if (cos_theta > -0.95) { // Compute maximum junction velocity based on maximum acceleration and junction deviation - double sin_theta_d2 = sqrt(0.5*(1.0-cos_theta)); // Trig half angle identity. Always positive. + float sin_theta_d2 = sqrt(0.5*(1.0-cos_theta)); // Trig half angle identity. Always positive. vmax_junction = min(vmax_junction, sqrt(settings.acceleration * settings.junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) ); } @@ -444,7 +444,7 @@ void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t in block->max_entry_speed = vmax_junction; // Initialize block entry speed. Compute based on deceleration to user-defined MINIMUM_PLANNER_SPEED. - double v_allowable = max_allowable_speed(-settings.acceleration,MINIMUM_PLANNER_SPEED,block->millimeters); + float v_allowable = max_allowable_speed(-settings.acceleration,MINIMUM_PLANNER_SPEED,block->millimeters); block->entry_speed = min(vmax_junction, v_allowable); // Initialize planner efficiency flags diff --git a/planner.h b/planner.h index a1adc26..9c77f90 100755 --- a/planner.h +++ b/planner.h @@ -34,10 +34,10 @@ typedef struct { int32_t step_event_count; // The number of step events required to complete this block // Fields used by the motion planner to manage acceleration - double nominal_speed; // The nominal speed for this block in mm/min - double entry_speed; // Entry speed at previous-current block junction in mm/min - double max_entry_speed; // Maximum allowable junction entry speed in mm/min - double millimeters; // The total travel of this block in mm + float nominal_speed; // The nominal speed for this block in mm/min + float entry_speed; // Entry speed at previous-current block junction in mm/min + float max_entry_speed; // Maximum allowable junction entry speed in mm/min + float millimeters; // The total travel of this block in mm uint8_t recalculate_flag; // Planner flag to recalculate trapezoids on entry junction uint8_t nominal_length_flag; // Planner flag for nominal speed always reached @@ -57,7 +57,7 @@ void plan_init(); // Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in // millimaters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed // rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes. -void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t invert_feed_rate); +void plan_buffer_line(float x, float y, float z, float feed_rate, uint8_t invert_feed_rate); // Called when the current block is no longer needed. Discards the block and makes the memory // availible for new blocks. diff --git a/print.c b/print.c index 83a8db5..35f8d96 100755 --- a/print.c +++ b/print.c @@ -105,7 +105,7 @@ void printInteger(long n) print_uint32_base10(n); } -void printFloat(double n) +void printFloat(float n) { if (n < 0) { serial_write('-'); diff --git a/print.h b/print.h index f0dff4c..9983aee 100755 --- a/print.h +++ b/print.h @@ -33,6 +33,6 @@ void printInteger(long n); void print_uint8_base2(uint8_t n); -void printFloat(double n); +void printFloat(float n); #endif \ No newline at end of file diff --git a/protocol.c b/protocol.c index 2646f49..a5c9e87 100755 --- a/protocol.c +++ b/protocol.c @@ -245,7 +245,7 @@ void protocol_process() // Enable comments flag and ignore all characters until ')' or EOL. iscomment = true; } else if (char_counter >= LINE_BUFFER_SIZE-1) { - // Throw away any characters beyond the end of the line buffer + // Throw away any characters beyond the end of the line buffer } else if (c >= 'a' && c <= 'z') { // Upcase lowercase line[char_counter++] = c-'a'+'A'; } else { diff --git a/settings.c b/settings.c index 5cc3b16..b44b5ae 100755 --- a/settings.c +++ b/settings.c @@ -33,13 +33,13 @@ settings_t settings; // Version 1 outdated settings record typedef struct { - double steps_per_mm[3]; + float steps_per_mm[3]; uint8_t microsteps; uint8_t pulse_microseconds; - double default_feed_rate; - double default_seek_rate; + float default_feed_rate; + float default_seek_rate; uint8_t invert_mask; - double mm_per_arc_segment; + float mm_per_arc_segment; } settings_v1_t; // Default settings (used when resetting eeprom-settings) @@ -89,20 +89,20 @@ void settings_dump() { // Parameter lines are on the form '$4=374.3' or '$' to dump current settings uint8_t settings_execute_line(char *line) { uint8_t char_counter = 1; - double parameter, value; + float parameter, value; if(line[0] != '$') { return(STATUS_UNSUPPORTED_STATEMENT); } if(line[char_counter] == 0) { settings_dump(); return(STATUS_OK); } - if(!read_double(line, &char_counter, ¶meter)) { + if(!read_float(line, &char_counter, ¶meter)) { return(STATUS_BAD_NUMBER_FORMAT); }; if(line[char_counter++] != '=') { return(STATUS_UNSUPPORTED_STATEMENT); } - if(!read_double(line, &char_counter, &value)) { + if(!read_float(line, &char_counter, &value)) { return(STATUS_BAD_NUMBER_FORMAT); } if(line[char_counter] != 0) { @@ -158,7 +158,7 @@ int read_settings() { } // A helper method to set settings from command line -void settings_store_setting(int parameter, double value) { +void settings_store_setting(int parameter, float value) { switch(parameter) { case 0: case 1: case 2: if (value <= 0.0) { diff --git a/settings.h b/settings.h index 290c6fb..33dc5b8 100755 --- a/settings.h +++ b/settings.h @@ -33,15 +33,15 @@ // Current global settings (persisted in EEPROM from byte 1 onwards) typedef struct { - double steps_per_mm[3]; + float steps_per_mm[3]; uint8_t microsteps; uint8_t pulse_microseconds; - double default_feed_rate; - double default_seek_rate; + float default_feed_rate; + float default_seek_rate; uint8_t invert_mask; - double mm_per_arc_segment; - double acceleration; - double junction_deviation; + float mm_per_arc_segment; + float acceleration; + float junction_deviation; } settings_t; extern settings_t settings; @@ -55,6 +55,6 @@ void settings_dump(); uint8_t settings_execute_line(char *line); // A helper method to set new settings from command line -void settings_store_setting(int parameter, double value); +void settings_store_setting(int parameter, float value); #endif diff --git a/stepper.c b/stepper.c index 912419b..f03f8fc 100755 --- a/stepper.c +++ b/stepper.c @@ -304,8 +304,10 @@ ISR(TIMER1_COMPA_vect) // This interrupt is set up by ISR_TIMER1_COMPAREA when it sets the motor port bits. It resets // the motor port after a short period (settings.pulse_microseconds) completing one step cycle. -// TODO: It is possible for the serial interrupts to delay this interrupt by a few microseconds, if -// they execute right before this interrupt. Not a big deal, but could use some TLC at some point. +// NOTE: Interrupt collisions between the serial and stepper interrupts can cause delays by +// a few microseconds, if they execute right before one another. Not a big deal, but can +// cause issues at high step rates if another high frequency asynchronous interrupt is +// added to Grbl. ISR(TIMER2_OVF_vect) { // Reset stepping pins (leave the direction pins) @@ -355,12 +357,11 @@ void st_init() // Configure Timer 2 TCCR2A = 0; // Normal operation TCCR2B = 0; // Disable timer until needed. - TIMSK2 |= (1<