int st_buffer_delay(uint32_t milliseconds, int16_t line_number) { struct Block *block; if (milliseconds==0) { st_stop(); return 0; } while (st_buffer_full()) { sleep_mode();} // makes sure there are two /* // slots left on buffer printPgmString(PSTR("in st_buffer_delay. Delay = ")); printInteger(milliseconds); printPgmString(PSTR("\r\n"));*/ // Setup block record block = &block_buffer[block_buffer_head]; block->backlash=0; block->line_number = line_number; block->maximum_steps = milliseconds; block->rate = 1000; block->mode = SM_HALT; // Move buffer head block_buffer_head = (block_buffer_head + 1) % BLOCK_BUFFER_SIZE; //next_buffer_head; // Ensure that blocks will be processed by enabling the Stepper Driver Interrupt ENABLE_STEPPER_DRIVER_INTERRUPT(); return 1; }
//************************************************************************************* int main(void) { beginSerial(BAUD_RATE); i2c_init(); // config_reset(); // This routine forces the eeprom config into its default state // if something really messes it up. Uncomment to use. config_init(); // Restore state from eeprom if it is there, else restore default. st_init(); // initialize the stepper subsystem mc_init(); // initialize motion control subsystem spindle_init(); // initialize spindle controller gc_init(); // initialize gcode-parser sp_init(); // initialize the serial protocol DDRD |= (1<<3)|(1<<4)|(1<<5); for(;;){ i2c_report_position(); _delay_ms(1); // Delay is required, otherwise // if mc_running and current_mode = SM_RUN then don't get buttons, else do if (!(mc_running==0 & (st_current_mode!=SM_RUN))){ i2c_get_buttons(); // i2c_get doesn't work. 1ms seems to be enough if (buttons[0]|buttons[1]|buttons[2]|buttons[3]){ mc_running=1; STEPPERS_ENABLE_PORT |= (1<<STEPPERS_ENABLE_BIT); ENABLE_STEPPER_DRIVER_INTERRUPT(); } } if (serialAvailable()) sp_process(); // process the serial protocol if (mc_in_arc()) mc_continue_arc(); // if busy drawing an arc, keep drawing } return 0; /* never reached */ }
void st_wake_up() { // TCNT1 = 0; ENABLE_STEPPER_DRIVER_INTERRUPT(); }
// Check endstops inline void update_endstops() { #ifdef Z_DUAL_ENDSTOPS uint16_t #else byte #endif current_endstop_bits = 0; #define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_## MINMAX ##_PIN #define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_## MINMAX ##_ENDSTOP_INVERTING #define _AXIS(AXIS) AXIS ##_AXIS #define _ENDSTOP_HIT(AXIS) endstop_hit_bits |= BIT(_ENDSTOP(AXIS, MIN)) #define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX // SET_ENDSTOP_BIT: set the current endstop bits for an endstop to its status #define SET_ENDSTOP_BIT(AXIS, MINMAX) SET_BIT(current_endstop_bits, _ENDSTOP(AXIS, MINMAX), (READ(_ENDSTOP_PIN(AXIS, MINMAX)) != _ENDSTOP_INVERTING(AXIS, MINMAX))) // COPY_BIT: copy the value of COPY_BIT to BIT in bits #define COPY_BIT(bits, COPY_BIT, BIT) SET_BIT(bits, BIT, TEST(bits, COPY_BIT)) // TEST_ENDSTOP: test the old and the current status of an endstop #define TEST_ENDSTOP(ENDSTOP) (TEST(current_endstop_bits, ENDSTOP) && TEST(old_endstop_bits, ENDSTOP)) #define UPDATE_ENDSTOP(AXIS,MINMAX) \ SET_ENDSTOP_BIT(AXIS, MINMAX); \ if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX)) && (current_block->steps[_AXIS(AXIS)] > 0)) { \ endstops_trigsteps[_AXIS(AXIS)] = count_position[_AXIS(AXIS)]; \ _ENDSTOP_HIT(AXIS); \ step_events_completed = current_block->step_event_count; \ } #ifdef COREXY // Head direction in -X axis for CoreXY bots. // If DeltaX == -DeltaY, the movement is only in Y axis if ((current_block->steps[A_AXIS] != current_block->steps[B_AXIS]) || (TEST(out_bits, A_AXIS) == TEST(out_bits, B_AXIS))) { if (TEST(out_bits, X_HEAD)) #elif defined(COREXZ) // Head direction in -X axis for CoreXZ bots. // If DeltaX == -DeltaZ, the movement is only in Z axis if ((current_block->steps[A_AXIS] != current_block->steps[C_AXIS]) || (TEST(out_bits, A_AXIS) == TEST(out_bits, C_AXIS))) { if (TEST(out_bits, X_HEAD)) #else if (TEST(out_bits, X_AXIS)) // stepping along -X axis (regular Cartesian bot) #endif { // -direction #ifdef DUAL_X_CARRIAGE // with 2 x-carriages, endstops are only checked in the homing direction for the active extruder if ((current_block->active_extruder == 0 && X_HOME_DIR == -1) || (current_block->active_extruder != 0 && X2_HOME_DIR == -1)) #endif { #if HAS_X_MIN UPDATE_ENDSTOP(X, MIN); #endif } } else { // +direction #ifdef DUAL_X_CARRIAGE // with 2 x-carriages, endstops are only checked in the homing direction for the active extruder if ((current_block->active_extruder == 0 && X_HOME_DIR == 1) || (current_block->active_extruder != 0 && X2_HOME_DIR == 1)) #endif { #if HAS_X_MAX UPDATE_ENDSTOP(X, MAX); #endif } } #if defined(COREXY) || defined(COREXZ) } #endif #ifdef COREXY // Head direction in -Y axis for CoreXY bots. // If DeltaX == DeltaY, the movement is only in X axis if ((current_block->steps[A_AXIS] != current_block->steps[B_AXIS]) || (TEST(out_bits, A_AXIS) != TEST(out_bits, B_AXIS))) { if (TEST(out_bits, Y_HEAD)) #else if (TEST(out_bits, Y_AXIS)) // -direction #endif { // -direction #if HAS_Y_MIN UPDATE_ENDSTOP(Y, MIN); #endif } else { // +direction #if HAS_Y_MAX UPDATE_ENDSTOP(Y, MAX); #endif } #if defined(COREXY) } #endif #ifdef COREXZ // Head direction in -Z axis for CoreXZ bots. // If DeltaX == DeltaZ, the movement is only in X axis if ((current_block->steps[A_AXIS] != current_block->steps[C_AXIS]) || (TEST(out_bits, A_AXIS) != TEST(out_bits, C_AXIS))) { if (TEST(out_bits, Z_HEAD)) #else if (TEST(out_bits, Z_AXIS)) #endif { // z -direction #if HAS_Z_MIN #ifdef Z_DUAL_ENDSTOPS SET_ENDSTOP_BIT(Z, MIN); #if HAS_Z2_MIN SET_ENDSTOP_BIT(Z2, MIN); #else COPY_BIT(current_endstop_bits, Z_MIN, Z2_MIN); #endif byte z_test = TEST_ENDSTOP(Z_MIN) << 0 + TEST_ENDSTOP(Z2_MIN) << 1; // bit 0 for Z, bit 1 for Z2 if (z_test && current_block->steps[Z_AXIS] > 0) { // z_test = Z_MIN || Z2_MIN endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; endstop_hit_bits |= BIT(Z_MIN); if (!performing_homing || (z_test == 0x3)) //if not performing home or if both endstops were trigged during homing... step_events_completed = current_block->step_event_count; } #else // !Z_DUAL_ENDSTOPS UPDATE_ENDSTOP(Z, MIN); #endif // !Z_DUAL_ENDSTOPS #endif // Z_MIN_PIN #ifdef Z_PROBE_ENDSTOP #ifdef HAKANS_FSR if (hakans_fsr_endstop_active) { #endif UPDATE_ENDSTOP(Z, PROBE); if (TEST_ENDSTOP(Z_PROBE)) { endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; endstop_hit_bits |= BIT(Z_PROBE); } #ifdef HAKANS_FSR } #endif #endif } else { // z +direction #if HAS_Z_MAX #ifdef Z_DUAL_ENDSTOPS SET_ENDSTOP_BIT(Z, MAX); #if HAS_Z2_MAX SET_ENDSTOP_BIT(Z2, MAX); #else COPY_BIT(current_endstop_bits, Z_MAX, Z2_MAX) #endif byte z_test = TEST_ENDSTOP(Z_MAX) << 0 + TEST_ENDSTOP(Z2_MAX) << 1; // bit 0 for Z, bit 1 for Z2 if (z_test && current_block->steps[Z_AXIS] > 0) { // t_test = Z_MAX || Z2_MAX endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; endstop_hit_bits |= BIT(Z_MIN); if (!performing_homing || (z_test == 0x3)) //if not performing home or if both endstops were trigged during homing... step_events_completed = current_block->step_event_count; } #else // !Z_DUAL_ENDSTOPS UPDATE_ENDSTOP(Z, MAX); #endif // !Z_DUAL_ENDSTOPS #endif // Z_MAX_PIN #ifdef Z_PROBE_ENDSTOP #ifdef HAKANS_FSR if (hakans_fsr_endstop_active) { #endif UPDATE_ENDSTOP(Z, PROBE); if (TEST_ENDSTOP(Z_PROBE)) { endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; endstop_hit_bits |= BIT(Z_PROBE); } #ifdef HAKANS_FSR } #endif #endif } #if defined(COREXZ) } #endif old_endstop_bits = current_endstop_bits; } // __________________________ // /| |\ _________________ ^ // / | | \ /| |\ | // / | | \ / | | \ s // / | | | | | \ p // / | | | | | \ e // +-----+------------------------+---+--+---------------+----+ e // | BLOCK 1 | BLOCK 2 | d // // time -----> // // The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates // first block->accelerate_until step_events_completed, then keeps going at constant speed until // step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. // The slope of acceleration is calculated using v = u + at where t is the accumulated timer values of the steps so far. void st_wake_up() { // TCNT1 = 0; ENABLE_STEPPER_DRIVER_INTERRUPT(); } FORCE_INLINE unsigned long calc_timer(unsigned long step_rate) { unsigned long timer; if (step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; #if defined(ENABLE_HIGH_SPEED_STEPPING) if(step_rate > (2 * DOUBLE_STEP_FREQUENCY)) { // If steprate > 2*DOUBLE_STEP_FREQUENCY >> step 4 times step_rate = (step_rate >> 2); step_loops = 4; }
void st_wake_up() { STEPPERS_ENABLE_PORT &= ~(1<<STEPPERS_ENABLE_BIT); ENABLE_STEPPER_DRIVER_INTERRUPT(); }
void st_wake_up() { ENABLE_STEPPER_DRIVER_INTERRUPT(); }
int st_buffer_block(int32_t steps_x, int32_t steps_y, int32_t steps_z, int32_t pos_x, int32_t pos_y, int32_t pos_z, uint32_t microseconds, int16_t line_number) { uint8_t direction_bits = 0; uint8_t changed_dir; struct Block *block; struct Block *comp_block=NULL; uint32_t maximum_steps; maximum_steps = max(labs(steps_x), max(labs(steps_y), labs(steps_z))); // Don't process empty blocks if (maximum_steps==0) {return 0;} // Determine direction bits if (steps_x < 0) { direction_bits |= (1<<X_DIRECTION_BIT); } if (steps_y < 0) { direction_bits |= (1<<Y_DIRECTION_BIT); } if (steps_z < 0) { direction_bits |= (1<<Z_DIRECTION_BIT); } while (st_buffer_full()) { sleep_mode();} // makes sure there are two // slots left on buffer // If direction has changed, then put a backlash instruction // on the queue: if (direction_bits!=old_direction_bits){ comp_block = &block_buffer[block_buffer_head]; comp_block->backlash = 1; comp_block->direction_bits = direction_bits; comp_block->line_number = line_number; comp_block->steps_x = 0; comp_block->steps_y = 0; comp_block->steps_z = 0; comp_block->pos_x = pos_x; comp_block->pos_y = pos_y; comp_block->pos_z = pos_z; changed_dir = direction_bits^old_direction_bits; old_direction_bits = direction_bits; if (changed_dir & (1<<X_DIRECTION_BIT)) comp_block->steps_x=settings.backlash_x_count; if (changed_dir & (1<<Y_DIRECTION_BIT)) comp_block->steps_y=settings.backlash_y_count; if (changed_dir & (1<<Z_DIRECTION_BIT)) comp_block->steps_z=settings.backlash_z_count; // Use same rate for backlash compensation as for the block itself: comp_block->rate = microseconds/maximum_steps; comp_block->mode = SM_RUN; comp_block->maximum_steps = max(comp_block->steps_x, max(comp_block->steps_y, comp_block->steps_z)); // If compensation is not empty, advance the end of the queue if (comp_block->maximum_steps > 0) { block_buffer_head = (block_buffer_head + 1) % BLOCK_BUFFER_SIZE; } } // Setup block record block = &block_buffer[block_buffer_head]; block->backlash=0; block->line_number = line_number; block->steps_x = labs(steps_x); block->steps_y = labs(steps_y); block->steps_z = labs(steps_z); block->pos_x = pos_x; block->pos_y = pos_y; block->pos_z = pos_z; block->maximum_steps = maximum_steps; block->rate = microseconds/block->maximum_steps; block->mode = SM_RUN; // Compute direction bits for this block block->direction_bits = direction_bits; // Move buffer head block_buffer_head = (block_buffer_head + 1) % BLOCK_BUFFER_SIZE; //next_buffer_head; // Ensure that blocks will be processed by enabling The Stepper Driver Interrupt ENABLE_STEPPER_DRIVER_INTERRUPT(); return 1; }