コード例 #1
0
// Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second
// unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in
// (1 minute)/feed_rate time.
// NOTE: This is the primary gateway to the grbl planner. All line motions, including arc line 
// segments, must pass through this routine before being passed to the planner. The seperation of
// mc_line and plan_buffer_line is done primarily to make backlash compensation integration simple
// and direct.
// TODO: Check for a better way to avoid having to push the arguments twice for non-backlash cases.
// However, this keeps the memory requirements lower since it doesn't have to call and hold two 
// plan_buffer_lines in memory. Grbl only has to retain the original line input variables during a
// backlash segment(s).
void mc_line(double x, double y, double z, double c, double feed_rate, uint8_t invert_feed_rate)
{
  // TODO: Backlash compensation may be installed here. Only need direction info to track when
  // to insert a backlash line motion(s) before the intended line motion. Requires its own
  // plan_check_full_buffer() and check for system abort loop. Also for position reporting 
  // backlash steps will need to be also tracked. Not sure what the best strategy is for this,
  // i.e. keep the planner independent and do the computations in the status reporting, or let
  // the planner handle the position corrections. The latter may get complicated.

  // If the buffer is full: good! That means we are well ahead of the robot. 
  // Remain in this loop until there is room in the buffer.
  do {
    protocol_execute_runtime(); // Check for any run-time commands
    if (sys.abort) { return; } // Bail, if system abort.
  } while ( plan_check_full_buffer() );  
  plan_buffer_line(x, y, z, c, feed_rate, invert_feed_rate);
  
  // Auto-cycle start immediately after planner finishes. Enabled/disabled by grbl settings. During 
  // a feed hold, auto-start is disabled momentarily until the cycle is resumed by the cycle-start 
  // runtime command.
  // NOTE: This is allows the user to decide to exclusively use the cycle start runtime command to
  // begin motion or let grbl auto-start it for them. This is useful when: manually cycle-starting
  // when the buffer is completely full and primed; auto-starting, if there was only one g-code 
  // command sent during manual operation; or if a system is prone to buffer starvation, auto-start
  // helps make sure it minimizes any dwelling/motion hiccups and keeps the cycle going. 
  if (sys.auto_start) { st_cycle_start(); }
}
コード例 #2
0
// Perform homing cycle to locate and set machine zero. Only '$H' executes this command.
// NOTE: There should be no motions in the buffer and Grbl must be in an idle state before
// executing the homing cycle. This prevents incorrect buffered plans after homing.
void mc_go_home()
{
  sys.state = STATE_HOMING; // Set system state variable
  LIMIT_PCMSK &= ~LIMIT_MASK; // Disable hard limits pin change register for cycle duration

  limits_go_home(); // Perform homing routine.

  protocol_execute_runtime(); // Check for reset and set system abort.
  if (sys.abort) { return; } // Did not complete. Alarm state set by mc_alarm.

  // The machine should now be homed and machine zero has been located. Upon completion,
  // reset system position and sync internal position vectors.
  clear_vector_float(sys.position); // Set machine zero
  sys_sync_current_position();
  sys.state = STATE_IDLE; // Set system state to IDLE to complete motion and indicate homed.

  // Pull-off axes (that have been homed) from limit switches before continuing motion.
  // This provides some initial clearance off the switches and should also help prevent them
  // from falsely tripping when hard limits are enabled.
/// 8c1
  int8_t x_dir, y_dir, z_dir, t_dir;
  x_dir = y_dir = z_dir = t_dir = 0;
  if (HOMING_LOCATE_CYCLE & (1<<X_AXIS)) {
    if (settings.homing_dir_mask & (1<<X_DIRECTION_BIT))
		x_dir = 1;
    else
    	x_dir = -1;
  }
  if (HOMING_LOCATE_CYCLE & (1<<Y_AXIS)) {
    if (settings.homing_dir_mask & (1<<Y_DIRECTION_BIT)) { y_dir = 1; }
    else { y_dir = -1; }
  }
  if (HOMING_LOCATE_CYCLE & (1<<Z_AXIS)) {
    if (settings.homing_dir_mask & (1<<Z_DIRECTION_BIT)) { z_dir = 1; }
    else { z_dir = -1; }
  }
/// 8c1
  if (HOMING_LOCATE_CYCLE & (1<<T_AXIS)) {
    if (settings.homing_dir_mask & (1<<T_DIRECTION_BIT)) { t_dir = 1; }
    else { t_dir = -1; }
  }

/// 8c1 : line
  mc_line(x_dir*settings.homing_pulloff, y_dir*settings.homing_pulloff,
          z_dir*settings.homing_pulloff, t_dir*settings.homing_pulloff, settings.homing_seek_rate, false, C_LINE);

  st_cycle_start(); // Move it. Nothing should be in the buffer except this motion.
  plan_synchronize(); // Make sure the motion completes.

  // The gcode parser position circumvented by the pull-off maneuver, so sync position vectors.
  sys_sync_current_position();

  // If hard limits feature enabled, re-enable hard limits pin change register after homing cycle.
  if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE))
	LIMIT_PCMSK |= LIMIT_MASK;
  // Finished!
}
コード例 #3
0
ファイル: planner.c プロジェクト: hexleyosx/grbl-simulator
// Returns the availability status of the block ring buffer. True, if full.
uint8_t plan_check_full_buffer()
{
  if (block_buffer_tail == next_buffer_head) { 
    // TODO: Move this back into motion control. Shouldn't be here, but it's efficient.
    if (sys.auto_start) { st_cycle_start(); } // Auto-cycle start when buffer is full.
    return(true); 
  }
  return(false);
}
コード例 #4
0
ファイル: protocol.c プロジェクト: heise/GRBLDRILL
// Executes run-time commands, when required. This is called from various check points in the main
// program, primarily where there may be a while loop waiting for a buffer to clear space or any
// point where the execution time from the last check point may be more than a fraction of a second.
// This is a way to execute runtime commands asynchronously (aka multitasking) with grbl's g-code
// parsing and planning functions. This function also serves as an interface for the interrupts to
// set the system runtime flags, where only the main program to handles them, removing the need to
// define more computationally-expensive volatile variables.
// NOTE: The sys.execute variable flags are set by the serial read subprogram, except where noted.
void protocol_execute_runtime()
{
// evaluate emergency stop -cm
  if (!(AUX_PIN & (1<<AUX_STOP_BIT)))
    {
      if (!(sys.execute & EXEC_RESET)) { // Force stop only first time.
        st_go_idle();
        spindle_stop();
        sys.execute |= EXEC_RESET; // Set as true
      }
    }


  if (sys.execute) { // Enter only if any bit flag is true
    uint8_t rt_exec = sys.execute; // Avoid calling volatile multiple times

    // System abort. Steppers have already been force stopped.
    if (rt_exec & EXEC_RESET) {
      sys.abort = true;
      return; // Nothing else to do but exit.
    }

    // Execute and serial print status
    if (rt_exec & EXEC_STATUS_REPORT) {
      protocol_status_report();
      bit_false(sys.execute,EXEC_STATUS_REPORT);
    }

    // Execute and serial print switches
    if (rt_exec & EXEC_SWITCH_REPORT) {
      protocol_switch_report();
      bit_false(sys.execute,EXEC_SWITCH_REPORT);
    }

    // Initiate stepper feed hold
    if (rt_exec & EXEC_FEED_HOLD) {
      st_feed_hold(); // Initiate feed hold.
      bit_false(sys.execute,EXEC_FEED_HOLD);
    }

    // Reinitializes the stepper module running flags and re-plans the buffer after a feed hold.
    // NOTE: EXEC_CYCLE_STOP is set by the stepper subsystem when a cycle or feed hold completes.
    if (rt_exec & EXEC_CYCLE_STOP) {
      st_cycle_reinitialize();
      bit_false(sys.execute,EXEC_CYCLE_STOP);
    }

    if (rt_exec & EXEC_CYCLE_START) {
      st_cycle_start(); // Issue cycle start command to stepper subsystem
      #ifdef CYCLE_AUTO_START
        sys.auto_start = true; // Re-enable auto start after feed hold.
      #endif
      bit_false(sys.execute,EXEC_CYCLE_START);
    }
  }
}
コード例 #5
0
// Perform homing cycle to locate and set machine zero. Only '$H' executes this command.
// NOTE: There should be no motions in the buffer and Grbl must be in an idle state before
// executing the homing cycle. This prevents incorrect buffered plans after homing.
void mc_go_home()
{
  sys.state = STATE_HOMING; // Set system state variable
  LIMIT_PCMSK &= ~LIMIT_MASK; // Disable hard limits pin change register for cycle duration
  
  limits_go_home(); // Perform homing routine.
  
  protocol_execute_runtime(); // Check for reset and set system abort.
  if (sys.abort) { return; } // Did not complete. Alarm state set by mc_alarm.

  // The machine should now be homed and machine limits have been located. By default, 
  // grbl defines machine space as all negative, as do most CNCs. Since limit switches
  // can be on either side of an axes, check and set machine zero appropriately.
  // At the same time, set up pull-off maneuver from axes limit switches that have been homed.
  // This provides some initial clearance off the switches and should also help prevent them 
  // from falsely tripping when hard limits are enabled.
  // TODO: Need to improve dir_mask[] to be more axes independent.
  float pulloff_target[N_AXIS];
  clear_vector_float(pulloff_target); // Zero pulloff target.
  clear_vector_long(sys.position); // Zero current position for now.
  uint8_t dir_mask[N_AXIS];
  dir_mask[X_AXIS] = (1<<X_DIRECTION_BIT);
  dir_mask[Y_AXIS] = (1<<Y_DIRECTION_BIT);
  dir_mask[Z_AXIS] = (1<<Z_DIRECTION_BIT);
  uint8_t i;
  for (i=0; i<N_AXIS; i++) {
    // Set up pull off targets and machine positions for limit switches homed in the negative
    // direction, rather than the traditional positive. Leave non-homed positions as zero and
    // do not move them.
    if (HOMING_LOCATE_CYCLE & bit(i)) {
      if (settings.homing_dir_mask & dir_mask[i]) {
        pulloff_target[i] = settings.homing_pulloff-settings.max_travel[i];
        sys.position[i] = -lround(settings.max_travel[i]*settings.steps_per_mm[i]);
      } else {
        pulloff_target[i] = -settings.homing_pulloff;
      }
    }
  }
  sys_sync_current_position();
  sys.state = STATE_IDLE; // Set system state to IDLE to complete motion and indicate homed.

  mc_line(pulloff_target, settings.homing_seek_rate, false);
  st_cycle_start(); // Move it. Nothing should be in the buffer except this motion. 
  plan_synchronize(); // Make sure the motion completes.
  
  // The gcode parser position circumvented by the pull-off maneuver, so sync position vectors.
  sys_sync_current_position();

  // If hard limits feature enabled, re-enable hard limits pin change register after homing cycle.
  if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)) { LIMIT_PCMSK |= LIMIT_MASK; }
  // Finished! 
}
コード例 #6
0
// Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second
// unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in
// (1 minute)/feed_rate time.
// NOTE: This is the primary gateway to the grbl planner. All line motions, including arc line
// segments, must pass through this routine before being passed to the planner. The seperation of
// mc_line and plan_buffer_line is done primarily to make backlash compensation integration simple
// and direct.
// TODO: Check for a better way to avoid having to push the arguments twice for non-backlash cases.
// However, this keeps the memory requirements lower since it doesn't have to call and hold two
// plan_buffer_lines in memory. Grbl only has to retain the original line input variables during a
// backlash segment(s).
void mc_line(float x, float y, float z, float feed_rate, uint8_t invert_feed_rate)
{
    // TODO: Perform soft limit check here. Just check if the target x,y,z values are outside the
    // work envelope. Should be straightforward and efficient. By placing it here, rather than in
    // the g-code parser, it directly picks up motions from everywhere in Grbl.

    // If in check gcode mode, prevent motion by blocking planner.
    if (sys.state == STATE_CHECK_MODE) {
        return;
    }

    // TODO: Backlash compensation may be installed here. Only need direction info to track when
    // to insert a backlash line motion(s) before the intended line motion. Requires its own
    // plan_check_full_buffer() and check for system abort loop. Also for position reporting
    // backlash steps will need to be also tracked. Not sure what the best strategy is for this,
    // i.e. keep the planner independent and do the computations in the status reporting, or let
    // the planner handle the position corrections. The latter may get complicated.

    // If the buffer is full: good! That means we are well ahead of the robot.
    // Remain in this loop until there is room in the buffer.
    do {
        protocol_execute_runtime(); // Check for any run-time commands
        if (sys.abort) {
            return;    // Bail, if system abort.
        }
    } while ( plan_check_full_buffer() );
    plan_buffer_line(x, y, z, feed_rate, invert_feed_rate);

    // If idle, indicate to the system there is now a planned block in the buffer ready to cycle
    // start. Otherwise ignore and continue on.
    if (!sys.state) {
        sys.state = STATE_QUEUED;
    }

    // Auto-cycle start immediately after planner finishes. Enabled/disabled by grbl settings. During
    // a feed hold, auto-start is disabled momentarily until the cycle is resumed by the cycle-start
    // runtime command.
    // NOTE: This is allows the user to decide to exclusively use the cycle start runtime command to
    // begin motion or let grbl auto-start it for them. This is useful when: manually cycle-starting
    // when the buffer is completely full and primed; auto-starting, if there was only one g-code
    // command sent during manual operation; or if a system is prone to buffer starvation, auto-start
    // helps make sure it minimizes any dwelling/motion hiccups and keeps the cycle going.
    if (sys.auto_start) {
        st_cycle_start();
    }
}
コード例 #7
0
ファイル: protocol.c プロジェクト: koo5/grbl
// Executes run-time commands, when required. This is called from various check points in the main
// program, primarily where there may be a while loop waiting for a buffer to clear space or any
// point where the execution time from the last check point may be more than a fraction of a second.
// This is a way to execute runtime commands asynchronously (aka multitasking) with grbl's g-code
// parsing and planning functions. This function also serves as an interface for the interrupts to 
// set the system runtime flags, where only the main program handles them, removing the need to
// define more computationally-expensive volatile variables. This also provides a controlled way to 
// execute certain tasks without having two or more instances of the same task, such as the planner
// recalculating the buffer upon a feedhold or override.
// NOTE: The sys.execute variable flags are set by any process, step or serial interrupts, pinouts,
// limit switches, or the main program.
void protocol_execute_runtime()
{
  if (sys.execute) { // Enter only if any bit flag is true
    uint8_t rt_exec = sys.execute; // Avoid calling volatile multiple times
    
    // System alarm. Everything has shutdown by something that has gone severely wrong. Report
    // the source of the error to the user. If critical, Grbl disables by entering an infinite
    // loop until system reset/abort.
    if (rt_exec & (EXEC_ALARM | EXEC_CRIT_EVENT)) {      
      sys.state = STATE_ALARM; // Set system alarm state

      // Critical event. Only hard limit qualifies. Update this as new critical events surface.
      if (rt_exec & EXEC_CRIT_EVENT) {
        report_alarm_message(ALARM_HARD_LIMIT); 
        report_feedback_message(MESSAGE_CRITICAL_EVENT);
        bit_false(sys.execute,EXEC_RESET); // Disable any existing reset
        do { 
          // Nothing. Block EVERYTHING until user issues reset or power cycles. Hard limits
          // typically occur while unattended or not paying attention. Gives the user time
          // to do what is needed before resetting, like killing the incoming stream.
        } while (bit_isfalse(sys.execute,EXEC_RESET));

      // Standard alarm event. Only abort during motion qualifies.
      } else {
        // Runtime abort command issued during a cycle, feed hold, or homing cycle. Message the
        // user that position may have been lost and set alarm state to enable the alarm lockout
        // to indicate the possible severity of the problem.
        report_alarm_message(ALARM_ABORT_CYCLE);
      }
      bit_false(sys.execute,(EXEC_ALARM | EXEC_CRIT_EVENT));
    } 
  
    // Execute system abort. 
    if (rt_exec & EXEC_RESET) {
      sys.abort = true;  // Only place this is set true.
      return; // Nothing else to do but exit.
    }
    
    // Execute and serial print status
    if (rt_exec & EXEC_STATUS_REPORT) { 
      report_realtime_status();
      bit_false(sys.execute,EXEC_STATUS_REPORT);
    }
    
    // Initiate stepper feed hold
    if (rt_exec & EXEC_FEED_HOLD) {
      st_feed_hold(); // Initiate feed hold.
      bit_false(sys.execute,EXEC_FEED_HOLD);
    }
    
    // Reinitializes the stepper module running state and, if a feed hold, re-plans the buffer.
    // NOTE: EXEC_CYCLE_STOP is set by the stepper subsystem when a cycle or feed hold completes.
    if (rt_exec & EXEC_CYCLE_STOP) {
      st_cycle_reinitialize();
      bit_false(sys.execute,EXEC_CYCLE_STOP);
    }
    
    if (rt_exec & EXEC_CYCLE_START) { 
      st_cycle_start(); // Issue cycle start command to stepper subsystem
      if (bit_istrue(settings.flags,BITFLAG_AUTO_START)) {
        sys.auto_start = true; // Re-enable auto start after feed hold.
      }
      bit_false(sys.execute,EXEC_CYCLE_START);
    }
  }
  
  // Overrides flag byte (sys.override) and execution should be installed here, since they 
  // are runtime and require a direct and controlled interface to the main stepper program.
}  
コード例 #8
0
// Auto-cycle start is a user setting that automatically begins the cycle when a user enters
// a valid motion command either manually or by a streaming tool. This is intended as a beginners
// feature to help new users to understand g-code. It can be disabled. Otherwise, the normal
// operation of cycle start is manually issuing a cycle start command whenever the user is
// ready and there is a valid motion command in the planner queue.
// NOTE: This function is called from the main loop and mc_line() only and executes when one of
// two conditions exist respectively: There are no more blocks sent (i.e. streaming is finished, 
// single commands), or the planner buffer is full and ready to go.
void mc_auto_cycle_start() { if (sys.auto_start) { st_cycle_start(); } }
コード例 #9
0
ファイル: main.c プロジェクト: RoelandK/GRBL_LM4F120H5QR
int main(void)
{
#ifdef PART_LM4F120H5QR // ARM code
  SysCtlClockSet( SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN ); //set system clock to 80 MHz
  FPUEnable(); //enable the Floating Point Unit
//  FPULazyStackingEnable(); // Enable stacking for interrupt handlers
#endif

  // Initialize system
  serial_init(); // Setup serial baud rate and interrupts
  settings_init(); // Load grbl settings from EEPROM
  st_init(); // Setup stepper pins and interrupt timers

#ifdef PART_LM4F120H5QR // ARM code
  IntMasterEnable();
#else // AVR code
  sei(); // Enable interrupts
#endif
  
  memset(&sys, 0, sizeof(sys));  // Clear all system variables
  sys.abort = true;   // Set abort to complete initialization
  sys.state = STATE_INIT;  // Set alarm state to indicate unknown initial position
  
  for(;;) {
  
    // Execute system reset upon a system abort, where the main program will return to this loop.
    // Once here, it is safe to re-initialize the system. At startup, the system will automatically
    // reset to finish the initialization process.
    if (sys.abort) {
      // Reset system.
      serial_reset_read_buffer(); // Clear serial read buffer
      plan_init(); // Clear block buffer and planner variables
      gc_init(); // Set g-code parser to default state
      protocol_init(); // Clear incoming line data and execute startup lines
      spindle_init();
      coolant_init();
      limits_init();
      st_reset(); // Clear stepper subsystem variables.

      // Sync cleared gcode and planner positions to current system position, which is only
      // cleared upon startup, not a reset/abort. 
      sys_sync_current_position();

      // Reset system variables.
      sys.abort = false;
      sys.execute = 0;
      if (bit_istrue(settings.flags,BITFLAG_AUTO_START)) { sys.auto_start = true; }
      
      // Check for power-up and set system alarm if homing is enabled to force homing cycle
      // by setting Grbl's alarm state. Alarm locks out all g-code commands, including the
      // startup scripts, but allows access to settings and internal commands. Only a homing
      // cycle '$H' or kill alarm locks '$X' will disable the alarm.
      // NOTE: The startup script will run after successful completion of the homing cycle, but
      // not after disabling the alarm locks. Prevents motion startup blocks from crashing into
      // things uncontrollably. Very bad.
      #ifdef HOMING_INIT_LOCK
        if (sys.state == STATE_INIT && bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { sys.state = STATE_ALARM; }
      #endif
      
      // Check for and report alarm state after a reset, error, or an initial power up.
      if (sys.state == STATE_ALARM) {
        report_feedback_message(MESSAGE_ALARM_LOCK); 
      } else {
        // All systems go. Set system to ready and execute startup script.
        sys.state = STATE_IDLE;
        protocol_execute_startup(); 
      }
    }
    
    protocol_execute_runtime();
    protocol_process(); // ... process the serial protocol
    
    // When the serial protocol returns, there are no more characters in the serial read buffer to
    // be processed and executed. This indicates that individual commands are being issued or 
    // streaming is finished. In either case, auto-cycle start, if enabled, any queued moves.
    if (sys.auto_start) { st_cycle_start(); }
    
  }
  // return 0;   /* never reached */
}
コード例 #10
-1
ファイル: protocol.c プロジェクト: HermannLihl/GRBLMILL
void protocol_execute_runtime()
{
  	uint8_t aux_bits;
  	
  	aux_bits = AUX_PIN ^ AUX_INVMASK; // apply invert mask
  	if (!(aux_bits & (1<<AUX_STOP_BIT)))
    	{
  			if (!(emerg_stop)) {
          st_go_idle();
          spindle_stop();
          sys.abort = true;
          emerg_stop = true;
        }
  	  }
    else {
      emerg_stop = false;
    }

  AUX_PORT ^= (1<<AUX_WDOG_BIT);	// Chargepump-Bit invertieren

  
  if (sys.execute) { // Enter only if any bit flag is true
    uint8_t rt_exec = sys.execute; // Avoid calling volatile multiple times    
 
    // System abort. Steppers have already been force stopped.
    if (rt_exec & EXEC_RESET) {
      sys.abort = true;
      return; // Nothing else to do but exit.
    }

    // Execute and serial print status
    if (rt_exec & EXEC_STATUS_REPORT) {
      protocol_status_report();
      bit_false(sys.execute,EXEC_STATUS_REPORT);
    }

    // Execute and serial print switches
    if (rt_exec & EXEC_SWITCH_REPORT) {
      protocol_switch_report();
      bit_false(sys.execute,EXEC_SWITCH_REPORT);
    }

    // Initiate stepper feed hold
    if (rt_exec & EXEC_FEED_HOLD) {
      st_feed_hold(); // Initiate feed hold.
      bit_false(sys.execute,EXEC_FEED_HOLD);
    }

    // Reinitializes the stepper module running flags and re-plans the buffer after a feed hold.
    // NOTE: EXEC_CYCLE_STOP is set by the stepper subsystem when a cycle or feed hold completes.
    if (rt_exec & EXEC_CYCLE_STOP) {
      st_cycle_reinitialize();
      bit_false(sys.execute,EXEC_CYCLE_STOP);
    }

    if (rt_exec & EXEC_CYCLE_START) {
      st_cycle_start(); // Issue cycle start command to stepper subsystem
      #ifdef CYCLE_AUTO_START
        sys.auto_start = true; // Re-enable auto start after feed hold.
      #endif
      bit_false(sys.execute,EXEC_CYCLE_START);
    }
  }
}