Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
//*************************************************************************************
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 */
}
Ejemplo n.º 3
0
void st_wake_up() {
  //  TCNT1 = 0;
  ENABLE_STEPPER_DRIVER_INTERRUPT();
}
Ejemplo n.º 4
0
// 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;
    }
Ejemplo n.º 5
0
void st_wake_up() {
  STEPPERS_ENABLE_PORT &= ~(1<<STEPPERS_ENABLE_BIT);
  ENABLE_STEPPER_DRIVER_INTERRUPT();  
}
Ejemplo n.º 6
0
void st_wake_up() {
  ENABLE_STEPPER_DRIVER_INTERRUPT();  
}
Ejemplo n.º 7
0
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;
}