diff --git a/main.c b/main.c index b56bf6f..829ec5a 100644 --- a/main.c +++ b/main.c @@ -36,7 +36,7 @@ int main(void) { - sei(); + sei(); // Enable interrupts serial_init(BAUD_RATE); protocol_init(); @@ -47,8 +47,8 @@ int main(void) gc_init(); limits_init(); - for(;;){ - sleep_mode(); // Wait for it ... + while (1) { +// sleep_mode(); // Wait for it ... protocol_process(); // ... process the serial protocol } return 0; /* never reached */ diff --git a/motion_control.c b/motion_control.c index c7e5670..06b7868 100644 --- a/motion_control.c +++ b/motion_control.c @@ -48,9 +48,6 @@ void mc_dwell(double seconds) void mc_arc(double *position, double *target, double *offset, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, double feed_rate, uint8_t invert_feed_rate, double radius, uint8_t isclockwise) { -// int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled(); -// plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc - double center_axis0 = position[axis_0] + offset[axis_0]; double center_axis1 = position[axis_1] + offset[axis_1]; double linear_travel = target[axis_linear] - position[axis_linear]; @@ -141,8 +138,6 @@ void mc_arc(double *position, double *target, double *offset, uint8_t axis_0, ui } // Ensure last segment arrives at target location. plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], feed_rate, invert_feed_rate); - -// plan_set_acceleration_manager_enabled(acceleration_manager_was_enabled); } #endif diff --git a/nuts_bolts.c b/nuts_bolts.c index 0a8bf5c..8a6960c 100644 --- a/nuts_bolts.c +++ b/nuts_bolts.c @@ -1,3 +1,23 @@ +/* + nuts_bolts.c - Shared functions + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + #include "nuts_bolts.h" #include #include diff --git a/nuts_bolts.h b/nuts_bolts.h index 37f3aa6..54b3cb8 100644 --- a/nuts_bolts.h +++ b/nuts_bolts.h @@ -1,5 +1,5 @@ /* - motion_control.h - cartesian robot controller. + nuts_bolts.h - Header file for shared definitions, variables, and functions Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud diff --git a/planner.c b/planner.c index 6dea6b2..44913c8 100644 --- a/planner.c +++ b/planner.c @@ -46,12 +46,11 @@ static int32_t position[3]; // The current position of the tool in a static double previous_unit_vec[3]; // Unit vector of previous path line segment static double previous_nominal_speed; // Nominal speed of previous path line segment -static uint8_t acceleration_manager_enabled; // Acceleration management active? - // Returns the index of the next block in the ring buffer // NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication. -static int8_t next_block_index(int8_t block_index) { +static uint8_t next_block_index(uint8_t block_index) +{ block_index++; if (block_index == BLOCK_BUFFER_SIZE) { block_index = 0; } return(block_index); @@ -59,7 +58,8 @@ static int8_t next_block_index(int8_t block_index) { // Returns the index of the previous block in the ring buffer -static int8_t prev_block_index(int8_t block_index) { +static uint8_t prev_block_index(uint8_t block_index) +{ if (block_index == 0) { block_index = BLOCK_BUFFER_SIZE; } block_index--; return(block_index); @@ -68,7 +68,8 @@ static int8_t prev_block_index(int8_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 double estimate_acceleration_distance(double initial_rate, double target_rate, double acceleration) +{ return( (target_rate*target_rate-initial_rate*initial_rate)/(2*acceleration) ); } @@ -86,7 +87,8 @@ 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 double intersection_distance(double initial_rate, double final_rate, double acceleration, double distance) +{ return( (2*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/(4*acceleration) ); } @@ -96,13 +98,15 @@ 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 double max_allowable_speed(double acceleration, double target_velocity, double distance) +{ return( sqrt(target_velocity*target_velocity-2*acceleration*distance) ); } // The kernel called by planner_recalculate() when scanning the plan from last to first entry. -static void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) { +static void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) +{ if (!current) { return; } // Cannot operate on nothing. if (next) { @@ -128,8 +132,9 @@ static void planner_reverse_pass_kernel(block_t *previous, block_t *current, blo // planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This // implements the reverse pass. -static void planner_reverse_pass() { - auto int8_t block_index = block_buffer_head; +static void planner_reverse_pass() +{ + uint8_t block_index = block_buffer_head; block_t *block[3] = {NULL, NULL, NULL}; while(block_index != block_buffer_tail) { block_index = prev_block_index( block_index ); @@ -143,7 +148,8 @@ static void planner_reverse_pass() { // The kernel called by planner_recalculate() when scanning the plan from first to last entry. -static void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) { +static void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) +{ if(!previous) { return; } // Begin planning after buffer_tail // If the previous block is an acceleration block, but it is not long enough to complete the @@ -167,8 +173,9 @@ static void planner_forward_pass_kernel(block_t *previous, block_t *current, blo // planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This // implements the forward pass. -static void planner_forward_pass() { - int8_t block_index = block_buffer_tail; +static void planner_forward_pass() +{ + uint8_t block_index = block_buffer_tail; block_t *block[3] = {NULL, NULL, NULL}; while(block_index != block_buffer_head) { @@ -194,8 +201,8 @@ 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, double entry_factor, double exit_factor) +{ block->initial_rate = ceil(block->nominal_rate*entry_factor); // (step/min) block->final_rate = ceil(block->nominal_rate*exit_factor); // (step/min) int32_t acceleration_per_minute = block->rate_delta*ACCELERATION_TICKS_PER_SECOND*60.0; // (step/min^2) @@ -235,8 +242,9 @@ static void calculate_trapezoid_for_block(block_t *block, double entry_factor, d // planner_recalculate() after updating the blocks. Any recalulate flagged junction will // compute the two adjacent trapezoids to the junction, since the junction speed corresponds // to exit speed and entry speed of one another. -static void planner_recalculate_trapezoids() { - int8_t block_index = block_buffer_tail; +static void planner_recalculate_trapezoids() +{ + uint8_t block_index = block_buffer_tail; block_t *current; block_t *next = NULL; @@ -281,49 +289,41 @@ static void planner_recalculate_trapezoids() { // All planner computations are performed with doubles (float on Arduinos) to minimize numerical round- // off errors. Only when planned values are converted to stepper rate parameters, these are integers. -static void planner_recalculate() { +static void planner_recalculate() +{ planner_reverse_pass(); planner_forward_pass(); planner_recalculate_trapezoids(); } -void plan_init() { +void plan_init() +{ block_buffer_head = 0; block_buffer_tail = 0; - plan_set_acceleration_manager_enabled(true); clear_vector(position); clear_vector_double(previous_unit_vec); previous_nominal_speed = 0.0; } -void plan_set_acceleration_manager_enabled(uint8_t enabled) { - if ((!!acceleration_manager_enabled) != (!!enabled)) { - st_synchronize(); - acceleration_manager_enabled = !!enabled; - } -} - -int plan_is_acceleration_manager_enabled() { - return(acceleration_manager_enabled); -} - -void plan_discard_current_block() { +void plan_discard_current_block() +{ if (block_buffer_head != block_buffer_tail) { block_buffer_tail = next_block_index( block_buffer_tail ); } } -block_t *plan_get_current_block() { +block_t *plan_get_current_block() +{ if (block_buffer_head == block_buffer_tail) { return(NULL); } return(&block_buffer[block_buffer_tail]); } // 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 +// millimeters. 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(double x, double y, double z, double feed_rate, uint8_t invert_feed_rate) +{ // Calculate target position in absolute steps int32_t target[3]; target[X_AXIS] = lround(x*settings.steps_per_mm[X_AXIS]); @@ -331,7 +331,7 @@ void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t in target[Z_AXIS] = lround(z*settings.steps_per_mm[Z_AXIS]); // Calculate the buffer head after we push this byte - int next_buffer_head = next_block_index( block_buffer_head ); + uint8_t next_buffer_head = next_block_index( block_buffer_head ); // If the buffer is full: good! That means we are well ahead of the robot. // Rest here until there is room in the buffer. while(block_buffer_tail == next_buffer_head) { sleep_mode(); } @@ -384,84 +384,72 @@ void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t in block->rate_delta = ceil( block->step_event_count*inverse_millimeters * settings.acceleration / (60 * ACCELERATION_TICKS_PER_SECOND )); // (step/min/acceleration_tick) - // Perform planner-enabled calculations - if (acceleration_manager_enabled) { - - // Compute path unit vector - double unit_vec[3]; + // Compute path unit vector + double unit_vec[3]; - unit_vec[X_AXIS] = delta_mm[X_AXIS]*inverse_millimeters; - unit_vec[Y_AXIS] = delta_mm[Y_AXIS]*inverse_millimeters; - unit_vec[Z_AXIS] = delta_mm[Z_AXIS]*inverse_millimeters; - - // Compute maximum allowable entry speed at junction by centripetal acceleration approximation. - // Let a circle be tangent to both previous and current path line segments, where the junction - // deviation is defined as the distance from the junction to the closest edge of the circle, - // colinear with the circle center. The circular segment joining the two paths represents the - // path of centripetal acceleration. Solve for max velocity based on max acceleration about the - // radius of the circle, defined indirectly by junction deviation. This may be also viewed as - // 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 + unit_vec[X_AXIS] = delta_mm[X_AXIS]*inverse_millimeters; + unit_vec[Y_AXIS] = delta_mm[Y_AXIS]*inverse_millimeters; + unit_vec[Z_AXIS] = delta_mm[Z_AXIS]*inverse_millimeters; - // 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) && (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 = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS] - - previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS] - - previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ; - - // Skip and use default max junction speed for 0 degree acute junction. - if (cos_theta < 0.95) { - vmax_junction = min(previous_nominal_speed,block->nominal_speed); - // 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. - vmax_junction = min(vmax_junction, - sqrt(settings.acceleration * settings.junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) ); - } + // Compute maximum allowable entry speed at junction by centripetal acceleration approximation. + // Let a circle be tangent to both previous and current path line segments, where the junction + // deviation is defined as the distance from the junction to the closest edge of the circle, + // colinear with the circle center. The circular segment joining the two paths represents the + // path of centripetal acceleration. Solve for max velocity based on max acceleration about the + // radius of the circle, defined indirectly by junction deviation. This may be also viewed as + // 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 + + // 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) && (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 = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS] + - previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS] + - previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ; + + // Skip and use default max junction speed for 0 degree acute junction. + if (cos_theta < 0.95) { + vmax_junction = min(previous_nominal_speed,block->nominal_speed); + // 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. + vmax_junction = min(vmax_junction, + sqrt(settings.acceleration * settings.junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) ); } } - 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); - block->entry_speed = min(vmax_junction, v_allowable); - - // Initialize planner efficiency flags - // Set flag if block will always reach maximum junction speed regardless of entry/exit speeds. - // If a block can de/ac-celerate from nominal speed to zero within the length of the block, then - // the current block and next block junction speeds are guaranteed to always be at their maximum - // junction speeds in deceleration and acceleration, respectively. This is due to how the current - // block nominal speed limits both the current and next maximum junction speeds. Hence, in both - // the reverse and forward planners, the corresponding block junction speed will always be at the - // the maximum junction speed and may always be ignored for any speed reduction checks. - if (block->nominal_speed <= v_allowable) { block->nominal_length_flag = true; } - else { block->nominal_length_flag = false; } - block->recalculate_flag = true; // Always calculate trapezoid for new block + } + block->max_entry_speed = vmax_junction; - // Update previous path unit_vector and nominal speed - memcpy(previous_unit_vec, unit_vec, sizeof(unit_vec)); // previous_unit_vec[] = unit_vec[] - previous_nominal_speed = block->nominal_speed; + // 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); + block->entry_speed = min(vmax_junction, v_allowable); - } else { - // Acceleration planner disabled. Set minimum that is required. - block->initial_rate = block->nominal_rate; - block->final_rate = block->nominal_rate; - block->accelerate_until = 0; - block->decelerate_after = block->step_event_count; - block->rate_delta = 0; - } + // Initialize planner efficiency flags + // Set flag if block will always reach maximum junction speed regardless of entry/exit speeds. + // If a block can de/ac-celerate from nominal speed to zero within the length of the block, then + // the current block and next block junction speeds are guaranteed to always be at their maximum + // junction speeds in deceleration and acceleration, respectively. This is due to how the current + // block nominal speed limits both the current and next maximum junction speeds. Hence, in both + // the reverse and forward planners, the corresponding block junction speed will always be at the + // the maximum junction speed and may always be ignored for any speed reduction checks. + if (block->nominal_speed <= v_allowable) { block->nominal_length_flag = true; } + else { block->nominal_length_flag = false; } + block->recalculate_flag = true; // Always calculate trapezoid for new block + + // Update previous path unit_vector and nominal speed + memcpy(previous_unit_vec, unit_vec, sizeof(unit_vec)); // previous_unit_vec[] = unit_vec[] + previous_nominal_speed = block->nominal_speed; // Move buffer head block_buffer_head = next_buffer_head; // Update position memcpy(position, target, sizeof(target)); // position[] = target[] - if (acceleration_manager_enabled) { planner_recalculate(); } + planner_recalculate(); st_cycle_start(); } diff --git a/planner.h b/planner.h index f91b7c2..f8f59e8 100644 --- a/planner.h +++ b/planner.h @@ -27,12 +27,12 @@ // This struct is used when buffering the setup for each linear movement "nominal" values are as specified in // the source g-code and may never actually be reached if acceleration management is active. typedef struct { + // Fields used by the bresenham algorithm for tracing the line - uint32_t steps_x, steps_y, steps_z; // Step count along each axis uint8_t direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) + uint32_t steps_x, steps_y, steps_z; // Step count along each axis int32_t step_event_count; // The number of step events required to complete this block - uint32_t nominal_rate; // The nominal step rate for this block in step_events/minute - + // 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 junction in mm/min @@ -42,12 +42,13 @@ typedef struct { uint8_t nominal_length_flag; // Planner flag for nominal speed always reached // Settings for the trapezoid generator - uint32_t initial_rate; // The jerk-adjusted step rate at start of block - uint32_t final_rate; // The minimal rate at exit + uint32_t initial_rate; // The step rate at start of block + uint32_t final_rate; // The step rate at end of block int32_t rate_delta; // The steps/minute to add or subtract when changing speed (must be positive) uint32_t accelerate_until; // The index of the step event on which to stop acceleration uint32_t decelerate_after; // The index of the step event on which to start decelerating - + uint32_t nominal_rate; // The nominal step rate for this block in step_events/minute + } block_t; // Initialize the motion plan subsystem @@ -65,12 +66,6 @@ void plan_discard_current_block(); // Gets the current block. Returns NULL if buffer empty block_t *plan_get_current_block(); -// Enables or disables acceleration-management for upcoming blocks -void plan_set_acceleration_manager_enabled(uint8_t enabled); - -// Is acceleration-management currently enabled? -int plan_is_acceleration_manager_enabled(); - // Reset the position vector void plan_set_current_position(double x, double y, double z); diff --git a/protocol.c b/protocol.c index 4835c90..4010253 100644 --- a/protocol.c +++ b/protocol.c @@ -31,10 +31,12 @@ #include #define LINE_BUFFER_SIZE 50 -static char line[LINE_BUFFER_SIZE]; -static uint8_t char_counter; +static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated. +static uint8_t char_counter; // Last character counter in line variable. +static uint8_t iscomment; // Comment/block delete flag for processor to ignore comment characters. -static void status_message(int status_code) { +static void status_message(int status_code) +{ if (status_code == 0) { printPgmString(PSTR("ok\r\n")); } else { @@ -57,12 +59,15 @@ static void status_message(int status_code) { void protocol_init() { + char_counter = 0; // Reset line input + iscomment = false; printPgmString(PSTR("\r\nGrbl " GRBL_VERSION)); printPgmString(PSTR("\r\n")); } // Executes one line of input according to protocol -uint8_t protocol_execute_line(char *line) { +uint8_t protocol_execute_line(char *line) +{ if(line[0] == '$') { return(settings_execute_line(line)); // Delegate lines starting with '$' to the settings module } else { @@ -70,15 +75,16 @@ uint8_t protocol_execute_line(char *line) { } } + +// Process one line of incoming serial data. Remove unneeded characters and capitalize. void protocol_process() { char c; - uint8_t iscomment = false; while((c = serial_read()) != SERIAL_NO_DATA) { - if ((c == '\n') || (c == '\r')) { // End of block reached + if ((c == '\n') || (c == '\r')) { // End of line reached if (char_counter > 0) {// Line is complete. Then execute! - line[char_counter] = 0; // terminate string + line[char_counter] = 0; // Terminate string status_message(protocol_execute_line(line)); } else { // Empty or comment line. Skip block. diff --git a/protocol.h b/protocol.h index 3ad6597..4490a4b 100644 --- a/protocol.h +++ b/protocol.h @@ -3,6 +3,7 @@ Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud + Copyright (c) 2011 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/serial.c b/serial.c index 7310e3f..04483bb 100644 --- a/serial.c +++ b/serial.c @@ -44,25 +44,25 @@ volatile uint8_t tx_buffer_tail = 0; static void set_baud_rate(long baud) { uint16_t UBRR0_value = ((F_CPU / 16 + baud / 2) / baud - 1); - UBRR0H = UBRR0_value >> 8; - UBRR0L = UBRR0_value; + UBRR0H = UBRR0_value >> 8; + UBRR0L = UBRR0_value; } void serial_init(long baud) { set_baud_rate(baud); - /* baud doubler off - Only needed on Uno XXX */ + /* baud doubler off - Only needed on Uno XXX */ UCSR0A &= ~(1 << U2X0); - // enable rx and tx + // enable rx and tx UCSR0B |= 1<> 3); // Bit shift divide by 8. - - busy = true; - sei(); // Re enable interrupts (normally disabled while inside an interrupt handler) - // ((We re-enable interrupts in order for SIG_OVERFLOW2 to be able to be triggered - // at exactly the right time even if we occasionally spend a lot of time inside this handler.)) + TCNT2 = -(((settings.pulse_microseconds-2)*TICKS_PER_MICROSECOND) >> 3); // If there is no current block, attempt to pop one from the buffer if (current_block == NULL) { - // Anything in the buffer? + // Anything in the buffer? If so, initialize next motion. current_block = plan_get_current_block(); if (current_block != NULL) { trapezoid_generator_reset(); @@ -256,37 +252,39 @@ SIGNAL(TIMER1_COMPA_vect) // This interrupt is set up by SIG_OUTPUT_COMPARE1A when it sets the motor port bits. It resets // the motor port after a short period (settings.pulse_microseconds) completing one step cycle. -SIGNAL(TIMER2_OVF_vect) +ISR(TIMER2_OVF_vect) { - // reset stepping pins (leave the direction pins) + // Reset stepping pins (leave the direction pins) STEPPING_PORT = (STEPPING_PORT & ~STEP_MASK) | (settings.invert_mask & STEP_MASK); } // Initialize and start the stepper motor subsystem void st_init() { - // Configure directions of interface pins - STEPPING_DDR |= STEPPING_MASK; + // Configure directions of interface pins + STEPPING_DDR |= STEPPING_MASK; STEPPING_PORT = (STEPPING_PORT & ~STEPPING_MASK) | settings.invert_mask; STEPPERS_DISABLE_DDR |= 1<> 3; - prescaler = 1; // prescaler: 8 - actual_cycles = ceiling * 8L; + ceiling = cycles >> 3; + prescaler = 1; // prescaler: 8 + actual_cycles = ceiling * 8L; } else if (cycles <= 0x3fffffL) { - ceiling = cycles >> 6; - prescaler = 2; // prescaler: 64 - actual_cycles = ceiling * 64L; + ceiling = cycles >> 6; + prescaler = 2; // prescaler: 64 + actual_cycles = ceiling * 64L; } else if (cycles <= 0xffffffL) { - ceiling = (cycles >> 8); - prescaler = 3; // prescaler: 256 - actual_cycles = ceiling * 256L; + ceiling = (cycles >> 8); + prescaler = 3; // prescaler: 256 + actual_cycles = ceiling * 256L; } else if (cycles <= 0x3ffffffL) { - ceiling = (cycles >> 10); - prescaler = 4; // prescaler: 1024 - actual_cycles = ceiling * 1024L; + ceiling = (cycles >> 10); + prescaler = 4; // prescaler: 1024 + actual_cycles = ceiling * 1024L; } else { // Okay, that was slower than we actually go. Just set the slowest speed - ceiling = 0xffff; - prescaler = 4; - actual_cycles = 0xffff * 1024; + ceiling = 0xffff; + prescaler = 4; + actual_cycles = 0xffff * 1024; } // Set prescaler TCCR1B = (TCCR1B & ~(0x07<