示例#1
0
// Pin change interrupt for pin-out commands, i.e. cycle start, feed hold, and reset. Sets
// only the realtime command execute variable to have the main program execute these when 
// its ready. This works exactly like the character-based realtime commands when picked off
// directly from the incoming serial data stream.
//ISR(CONTROL_INT_vect)
void control_pin_check()
{
	static  uint8_t oldpin = 0;
	uint8_t pin =0;

	pin = system_control_get_state();

	if(pin != oldpin)
	{
		oldpin = pin;
		if (pin) {
			if (bit_istrue(pin,CONTROL_PIN_INDEX_RESET)) {
				mc_reset();
			} else if (bit_istrue(pin,CONTROL_PIN_INDEX_CYCLE_START)) {
				bit_true(sys_rt_exec_state, EXEC_CYCLE_START);
#ifndef ENABLE_SAFETY_DOOR_INPUT_PIN
			} else if (bit_istrue(pin,CONTROL_PIN_INDEX_FEED_HOLD)) {
				bit_true(sys_rt_exec_state, EXEC_FEED_HOLD);
#else
			} else if (bit_istrue(pin,CONTROL_PIN_INDEX_SAFETY_DOOR)) {
				bit_true(sys_rt_exec_state, EXEC_SAFETY_DOOR);
#endif
			}
		}
	}
}
示例#2
0
// Grbl global settings print out.
// NOTE: The numbering scheme here must correlate to storing in settings.c
void report_grbl_settings() {
  printPgmString((const char *)("$0=")); printFloat(settings.steps_per_mm[X_AXIS]);
  printPgmString((const char *)(" (x, step/mm)\r\n$1=")); printFloat(settings.steps_per_mm[Y_AXIS]);
  printPgmString((const char *)(" (y, step/mm)\r\n$2=")); printFloat(settings.steps_per_mm[Z_AXIS]);
  printPgmString((const char *)(" (z, step/mm)\r\n$3=")); printInteger(settings.pulse_microseconds);
  printPgmString((const char *)(" (step pulse, usec)\r\n$4=")); printFloat(settings.default_feed_rate);
  printPgmString((const char *)(" (default feed, mm/min)\r\n$5=")); printFloat(settings.default_seek_rate);
  printPgmString((const char *)(" (default seek, mm/min)\r\n$6=")); printInteger(settings.invert_mask); 
  printPgmString((const char *)(" (step port invert mask, int:")); print_uint8_base2(settings.invert_mask);  
  printPgmString((const char *)(")\r\n$7=")); printInteger(settings.stepper_idle_lock_time);
  printPgmString((const char *)(" (step idle delay, msec)\r\n$8=")); printFloat(settings.acceleration/(60*60)); // Convert from mm/min^2 for human readability
  printPgmString((const char *)(" (acceleration, mm/sec^2)\r\n$9=")); printFloat(settings.junction_deviation);
  printPgmString((const char *)(" (junction deviation, mm)\r\n$10=")); printFloat(settings.mm_per_arc_segment);
  printPgmString((const char *)(" (arc, mm/segment)\r\n$11=")); printInteger(settings.n_arc_correction);
  printPgmString((const char *)(" (n-arc correction, int)\r\n$12=")); printInteger(settings.decimal_places);
  printPgmString((const char *)(" (n-decimals, int)\r\n$13=")); printInteger(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES));
  printPgmString((const char *)(" (report inches, bool)\r\n$14=")); printInteger(bit_istrue(settings.flags,BITFLAG_AUTO_START));
  printPgmString((const char *)(" (auto start, bool)\r\n$15=")); printInteger(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE));
  printPgmString((const char *)(" (invert step enable, bool)\r\n$16=")); printInteger(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));
  printPgmString((const char *)(" (hard limits, bool)\r\n$17=")); printInteger(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
  printPgmString((const char *)(" (homing cycle, bool)\r\n$18=")); printInteger(settings.homing_dir_mask);
  printPgmString((const char *)(" (homing dir invert mask, int:")); print_uint8_base2(settings.homing_dir_mask);  
  printPgmString((const char *)(")\r\n$19=")); printFloat(settings.homing_feed_rate);
  printPgmString((const char *)(" (homing feed, mm/min)\r\n$20=")); printFloat(settings.homing_seek_rate);
  printPgmString((const char *)(" (homing seek, mm/min)\r\n$21=")); printInteger(settings.homing_debounce_delay);
  printPgmString((const char *)(" (homing debounce, msec)\r\n$22=")); printFloat(settings.homing_pulloff);
  printPgmString((const char *)(" (homing pull-off, mm)\r\n")); 
}
示例#3
0
文件: main.c 项目: 100takis/grbl
int main(void)
{
  // Initialize system upon power-up.
  serial_init();   // Setup serial baud rate and interrupts
  settings_init(); // Load grbl settings from EEPROM
  stepper_init();  // Configure stepper pins and interrupt timers
  system_init();   // Configure pinout pins and pin-change interrupt
  
  memset(&sys, 0, sizeof(sys));  // Clear all system variables
  sys.abort = true;   // Set abort to complete initialization
  sei(); // Enable interrupts

  // 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 (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { sys.state = STATE_ALARM; }
  #endif
  
  // Grbl initialization loop upon power-up or a system abort. For the latter, all processes
  // will return to this loop to be cleanly re-initialized.
  for(;;) {

    // TODO: Separate configure task that require interrupts to be disabled, especially upon
    // a system abort and ensuring any active interrupts are cleanly reset.
  
    // Reset Grbl primary systems.
    serial_reset_read_buffer(); // Clear serial read buffer
    gc_init(); // Set g-code parser to default state
    spindle_init();
    coolant_init();
    limits_init(); 
    probe_init();
    plan_reset(); // Clear block buffer and planner variables
    st_reset(); // Clear stepper subsystem variables.

    // Sync cleared gcode and planner positions to current system position.
    plan_sync_position();
    gc_sync_position();

    // Reset system variables.
    sys.abort = false;
    sys.execute = 0;
    if (bit_istrue(settings.flags,BITFLAG_AUTO_START)) { sys.auto_start = true; }
    else { sys.auto_start = false; }
          
    // Start Grbl main loop. Processes program inputs and executes them.
    protocol_main_loop();
    
  }
  return 0;   /* Never reached */
}
示例#4
0
文件: report.c 项目: rustyoz/grbl
 // Prints real-time data. This function grabs a real-time snapshot of the stepper subprogram 
 // and the actual location of the CNC machine. Users may change the following function to their
 // specific needs, but the desired real-time data report must be as short as possible. This is
 // requires as it minimizes the computational overhead and allows grbl to keep running smoothly, 
 // especially during g-code programs with fast, short line segments and high frequency reports (5-20Hz).
void report_realtime_status()
{
  // **Under construction** Bare-bones status report. Provides real-time machine position relative to 
  // the system power on location (0,0,0) and work coordinate position (G54 and G92 applied). Eventually
  // to be added are distance to go on block, processed block id, and feed rate. Also a settings bitmask
  // for a user to select the desired real-time data.
  uint8_t i;
  int32_t current_position[N_AXIS]; // Copy current state of the system position variable
  memcpy(current_position,sys.position,sizeof(sys.position));
  float print_position[N_AXIS];
 
  // Report current machine state
  switch (sys.state) {
    case STATE_IDLE: printPgmString(PSTR("<Idle")); break;
    case STATE_QUEUED: printPgmString(PSTR("<Queue")); break;
    case STATE_CYCLE: printPgmString(PSTR("<Run")); break;
    case STATE_HOLD: printPgmString(PSTR("<Hold")); break;
    case STATE_HOMING: printPgmString(PSTR("<Home")); break;
    case STATE_ALARM: printPgmString(PSTR("<Alarm")); break;
    case STATE_CHECK_MODE: printPgmString(PSTR("<Check")); break;
  }
 
  // Report machine position
  printPgmString(PSTR(",MPos:")); 
  for (i=0; i< N_AXIS; i++) {
    print_position[i] = current_position[i]/settings.steps_per_mm[i];
    if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { print_position[i] *= INCH_PER_MM; }
    printFloat(print_position[i]);
    printPgmString(PSTR(","));
  }
  
  // Report work position
  printPgmString(PSTR("WPos:")); 
  for (i=0; i< N_AXIS; i++) {
    if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) {
      print_position[i] -= (gc.coord_system[i]+gc.coord_offset[i])*INCH_PER_MM;
    } else {
      print_position[i] -= gc.coord_system[i]+gc.coord_offset[i];
    }
    printFloat(print_position[i]);
    if (i < (N_AXIS-1)) { printPgmString(PSTR(",")); }
  }
    
  #ifdef USE_LINE_NUMBERS
  // Report current line number
  printPgmString(PSTR(",Ln:")); 
  int32_t ln=0;
  plan_block_t * pb = plan_get_current_block();
  if(pb != NULL) {
    ln = pb->line_number;
  } 
  printInteger(ln);
  #endif
    
  printPgmString(PSTR(">\r\n"));
}
示例#5
0
文件: report.c 项目: Blue-Design/grbl
// Grbl global settings print out.
// NOTE: The numbering scheme here must correlate to storing in settings.c
void report_grbl_settings() {
  // Print Grbl settings.
  printPgmString(PSTR("$0=")); print_uint8_base10(settings.pulse_microseconds);
  printPgmString(PSTR(" (step pulse, usec)\r\n$1=")); print_uint8_base10(settings.stepper_idle_lock_time);
  printPgmString(PSTR(" (step idle delay, msec)\r\n$2=")); print_uint8_base10(settings.step_invert_mask); 
  printPgmString(PSTR(" (step port invert mask:")); print_uint8_base2(settings.step_invert_mask);  
  printPgmString(PSTR(")\r\n$3=")); print_uint8_base10(settings.dir_invert_mask); 
  printPgmString(PSTR(" (dir port invert mask:")); print_uint8_base2(settings.dir_invert_mask);  
  printPgmString(PSTR(")\r\n$4=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE));
  printPgmString(PSTR(" (step enable invert, bool)\r\n$5=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS));
  printPgmString(PSTR(" (limit pins invert, bool)\r\n$6=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_PROBE_PIN));
  printPgmString(PSTR(" (probe pin invert, bool)\r\n$10=")); print_uint8_base10(settings.status_report_mask);
  printPgmString(PSTR(" (status report mask:")); print_uint8_base2(settings.status_report_mask);
  printPgmString(PSTR(")\r\n$11=")); printFloat_SettingValue(settings.junction_deviation);
  printPgmString(PSTR(" (junction deviation, mm)\r\n$12=")); printFloat_SettingValue(settings.arc_tolerance);
  printPgmString(PSTR(" (arc tolerance, mm)\r\n$13=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES));
  printPgmString(PSTR(" (report inches, bool)\r\n$14=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_AUTO_START));
  printPgmString(PSTR(" (auto start, bool)\r\n$20=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE));
  printPgmString(PSTR(" (soft limits, bool)\r\n$21=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));
  printPgmString(PSTR(" (hard limits, bool)\r\n$22=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
  printPgmString(PSTR(" (homing cycle, bool)\r\n$23=")); print_uint8_base10(settings.homing_dir_mask);
  printPgmString(PSTR(" (homing dir invert mask:")); print_uint8_base2(settings.homing_dir_mask);  
  printPgmString(PSTR(")\r\n$24=")); printFloat_SettingValue(settings.homing_feed_rate);
  printPgmString(PSTR(" (homing feed, mm/min)\r\n$25=")); printFloat_SettingValue(settings.homing_seek_rate);
  printPgmString(PSTR(" (homing seek, mm/min)\r\n$26=")); print_uint8_base10(settings.homing_debounce_delay);
  printPgmString(PSTR(" (homing debounce, msec)\r\n$27=")); printFloat_SettingValue(settings.homing_pulloff);
  printPgmString(PSTR(" (homing pull-off, mm)\r\n"));

  // Print axis settings
  uint8_t idx, set_idx;
  uint8_t val = AXIS_SETTINGS_START_VAL;
  for (set_idx=0; set_idx<AXIS_N_SETTINGS; set_idx++) {
    for (idx=0; idx<N_AXIS; idx++) {
      printPgmString(PSTR("$"));
      print_uint8_base10(val+idx);
      printPgmString(PSTR("="));
      switch (set_idx) {
        case 0: printFloat_SettingValue(settings.steps_per_mm[idx]); break;
        case 1: printFloat_SettingValue(settings.max_rate[idx]); break;
        case 2: printFloat_SettingValue(settings.acceleration[idx]/(60*60)); break;
        case 3: printFloat_SettingValue(-settings.max_travel[idx]); break;
      }
      printPgmString(PSTR(" ("));
      switch (idx) {
        case X_AXIS: printPgmString(PSTR("x")); break;
        case Y_AXIS: printPgmString(PSTR("y")); break;
        case Z_AXIS: printPgmString(PSTR("z")); break;
      }
      switch (set_idx) {
        case 0: printPgmString(PSTR(", step/mm")); break;
        case 1: printPgmString(PSTR(" max rate, mm/min")); break;
        case 2: printPgmString(PSTR(" accel, mm/sec^2")); break;
        case 3: printPgmString(PSTR(" max travel, mm")); break;
      }      
      printPgmString(PSTR(")\r\n"));
    }
    val += AXIS_SETTINGS_INCREMENT;
  }  
}
// 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 place non-planner-type functions from being
// in the planner and to let backlash compensation or canned cycle integration simple and direct.
void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate)
{
  // If enabled, check for soft limit violations. Placed here all line motions are picked up
  // from everywhere in Grbl.
  if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) { limits_soft_check(target); }    
      
  // If in check gcode mode, prevent motion by blocking planner. Soft limits still work.
  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.
  // TODO: Backlash comp positioning values may need to be kept at a system level, i.e. tracking 
  // true position after a feed hold in the middle of a backlash move. The difficulty is in making 
  // sure that the stepper subsystem and planner are working in sync, and the status report 
  // position also takes this into account.

  // 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.
    if ( plan_check_full_buffer() ) { mc_auto_cycle_start(); } // Auto-cycle start when buffer is full.
    else { break; }
  } while (1);

  plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], 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; }
}
示例#7
0
文件: limits.c 项目: IRNAS/grbl_stm32
void limits_init() 
{
//  LIMIT_DDR &= ~(LIMIT_MASK); // Set as input pins
//
//  #ifdef DISABLE_LIMIT_PIN_PULL_UP
//    LIMIT_PORT &= ~(LIMIT_MASK); // Normal low operation. Requires external pull-down.
//  #else
//    LIMIT_PORT |= (LIMIT_MASK);  // Enable internal pull-up resistors. Normal high operation.
//  #endif
//
//  if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)) {
//    LIMIT_PCMSK |= LIMIT_MASK; // Enable specific pins of the Pin Change Interrupt
//    PCICR |= (1 << LIMIT_INT); // Enable Pin Change Interrupt
//  } else {
//    limits_disable();
//  }
//
//  #ifdef ENABLE_SOFTWARE_DEBOUNCE
//    MCUSR &= ~(1<<WDRF);
//    WDTCSR |= (1<<WDCE) | (1<<WDE);
//    WDTCSR = (1<<WDP0); // Set time-out at ~32msec.
//  #endif

	set_as_input(LIMX);
	set_as_input(LIMY);
	set_as_input(LIMZ);

	if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)) {
		limits_enable();
	} else {
		limits_disable();
	}

}
// Stepper shutdown
void st_go_idle(uint8_t delay_and_disable_steppers) 
{
  bool pin_state;
  
  // Disable Stepper Driver Interrupt. Allow Stepper Port Reset Interrupt to finish, if active.
  //TODO
  //TIMSK1 &= ~(1<<OCIE1A); // Disable Timer1 interrupt
  //TCCR1B = (TCCR1B & ~((1<<CS12) | (1<<CS11))) | (1<<CS10); // Reset clock to no prescaling.
  TMR1ON_bit = 0;
  busy = false;
  
  // Set stepper driver idle state, disabled or enabled, depending on settings and circumstances.
  pin_state = false; // Keep enabled.
  //if (((settings.stepper_idle_lock_time != 0xff) || bit_istrue(sys.execute,EXEC_ALARM)) && sys.state != STATE_HOMING) {
  if (delay_and_disable_steppers) {
    // Force stepper dwell to lock axes for a defined amount of time to ensure the axes come to a complete
    // stop and not drift from residual inertial forces at the end of the last movement.
    //TODO delay_ms(settings.stepper_idle_lock_time);
    pin_state = true; // Override. Disable steppers.
  }
  if (bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)) { pin_state = !pin_state; } // Apply pin invert.
  if (pin_state) { STEPPERS_DISABLE_PORT |= (1<<STEPPERS_DISABLE_BIT); }
  else { STEPPERS_DISABLE_PORT &= ~(1<<STEPPERS_DISABLE_BIT); }

}
示例#9
0
文件: print.c 项目: proto3/grbl
void printFloat_RateValue(float n) {
  if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) {
    printFloat(n*INCH_PER_MM,N_DECIMAL_RATEVALUE_INCH);
  } else {
    printFloat(n,N_DECIMAL_RATEVALUE_MM);
  }
}
示例#10
0
 // Prints real-time data. This function grabs a real-time snapshot of the stepper subprogram 
 // and the actual location of the CNC machine. Users may change the following function to their
 // specific needs, but the desired real-time data report must be as short as possible. This is
 // requires as it minimizes the computational overhead and allows grbl to keep running smoothly, 
 // especially during g-code programs with fast, short line segments and high frequency reports (5-20Hz).
void report_realtime_status()
{
  // **Under construction** Bare-bones status report. Provides real-time machine position relative to 
  // the system power on location (0,0,0) and work coordinate position (G54 and G92 applied). Eventually
  // to be added are distance to go on block, processed block id, and feed rate. Also a settings bitmask
  // for a user to select the desired real-time data.
  uint8_t i;
  int32_t current_position[3]; // Copy current state of the system position variable
  float print_position[3];

   memcpy(current_position,sys.position,sizeof(sys.position));
  // Report current machine state
  switch (sys.state) {
    case STATE_IDLE: printPgmString((const char *)("<Idle")); break;
//    case STATE_INIT: printPgmString((const char *)("[Init")); break; // Never observed
    case STATE_QUEUED: printPgmString((const char *)("<Queue")); break;
    case STATE_CYCLE: printPgmString((const char *)("<Run")); break;
    case STATE_HOLD: printPgmString((const char *)("<Hold")); break;
    case STATE_HOMING: printPgmString((const char *)("<Home")); break;
    case STATE_ALARM: printPgmString((const char *)("<Alarm")); break;
    case STATE_CHECK_MODE: printPgmString((const char *)("<Check")); break;
  }
 
  // Report machine position
  printPgmString((const char *)(",MPos:")); 
  for (i=0; i<= 2; i++) {
    print_position[i] = current_position[i]/settings.steps_per_mm[i];
    if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { print_position[i] *= INCH_PER_MM; }
    printFloat(print_position[i]);
    printPgmString((const char *)(","));
  }
  
  // Report work position
  printPgmString((const char *)("WPos:")); 
  for (i=0; i<= 2; i++) {
    if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) {
      print_position[i] -= (gc.coord_system[i]+gc.coord_offset[i])*INCH_PER_MM;
    } else {
      print_position[i] -= gc.coord_system[i]+gc.coord_offset[i];
    }
    printFloat(print_position[i]);
    if (i < 2) { printPgmString((const char *)(",")); }
  }
    
  printPgmString((const char *)(">\r\n"));
}
示例#11
0
// Returns control pin state as a uint8 bitfield. Each bit indicates the input pin state, where 
// triggered is 1 and not triggered is 0. Invert mask is applied. Bitfield organization is
// defined by the CONTROL_PIN_INDEX in the header file.
uint8_t system_control_get_state()
{
//  uint8_t control_state = 0;
//  uint8_t pin = (CONTROL_PIN & CONTROL_MASK);
//  #ifndef INVERT_ALL_CONTROL_PINS
//    pin ^= CONTROL_INVERT_MASK;
//  #endif
//  if (pin) {
//    #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
//      if (bit_istrue(pin,(1<<SAFETY_DOOR_BIT))) { control_state |= CONTROL_PIN_INDEX_SAFETY_DOOR; }
//    #endif
//    if (bit_istrue(pin,(1<<RESET_BIT))) { control_state |= CONTROL_PIN_INDEX_RESET; }
//    if (bit_istrue(pin,(1<<FEED_HOLD_BIT))) { control_state |= CONTROL_PIN_INDEX_FEED_HOLD; }
//    if (bit_istrue(pin,(1<<CYCLE_START_BIT))) { control_state |= CONTROL_PIN_INDEX_CYCLE_START; }
//  }
//  return(control_state);
	uint8_t control_state = 0;
	uint8_t pin           = 0;

#ifdef 	SAFETY_DOOR_PIN
  	  if (GPIO_ReadInputDataBit(SAFETY_DOOR_PIN)) { pin |= (1<<SAFETY_DOOR_BIT); }
#endif
#ifdef RESET_PIN
  	  if (GPIO_ReadInputDataBit(RESET_PIN))       { pin |= (1<<RESET_BIT);       }
#endif
#ifdef FEED_HOLD_PIN
  	  if (GPIO_ReadInputDataBit(FEED_HOLD_PIN))  { pin |= (1<<FEED_HOLD_BIT);   }
#endif
#ifdef CYCLE_START_PIN
  	  if (GPIO_ReadInputDataBit(CYCLE_START_PIN)){ pin |= (1<<CYCLE_START_BIT); }
#endif
	  #ifndef INVERT_ALL_CONTROL_PINS
	    pin ^= CONTROL_INVERT_MASK;
	  #endif
	  if (pin) {
	    #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
	      if (bit_istrue(pin,(1<<SAFETY_DOOR_BIT))) { control_state |= CONTROL_PIN_INDEX_SAFETY_DOOR; }
	    #endif
	    if (bit_istrue(pin,(1<<RESET_BIT))) { control_state |= CONTROL_PIN_INDEX_RESET; }
	    if (bit_istrue(pin,(1<<FEED_HOLD_BIT))) { control_state |= CONTROL_PIN_INDEX_FEED_HOLD; }
	    if (bit_istrue(pin,(1<<CYCLE_START_BIT))) { control_state |= CONTROL_PIN_INDEX_CYCLE_START; }
	  }

	  return(control_state);

}
// 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!
}
示例#13
0
uint8_t get_punch_sensor_value(uint8_t bit)
{
    volatile uint8_t v = PUNCH_SENSOR_PIN & (PUNCH_SENSOR_DOWN_MASK | PUNCH_SENSOR_UP_MASK);
    uint8_t value = bit_istrue(v, bit( bit));

    uint8_t inverted = 0;
    if (bit == PUNCH_SENSOR_DOWN_BIT) {
        inverted = BITFLAG_PUNCH_SENSOR_DOWN;
    } else if (bit == PUNCH_SENSOR_UP_BIT) {
        inverted = BITFLAG_PUNCH_SENSOR_UP;
    }

    if (bit_istrue(settings.punch_sensor_invert_mask , inverted) != 0)
    {
        if (value)
            return 1;
        return 0;
    }
    return value == 0;
}
示例#14
0
文件: probe.c 项目: Claude59/horus-fw
// Probe pin initialization routine.
void probe_init() 
{
  PROBE_DDR &= ~(PROBE_MASK); // Configure as input pins
  if (bit_istrue(settings.flags,BITFLAG_INVERT_PROBE_PIN)) { 
    PROBE_PORT &= ~(PROBE_MASK); // Normal low operation. Requires external pull-down.
    probe_invert_mask = 0;
  } else {
    PROBE_PORT |= PROBE_MASK;    // Enable internal pull-up resistors. Normal high operation.
    probe_invert_mask = PROBE_MASK; 
  }
}
示例#15
0
	// Returns if safety door is ajar(T) or closed(F), based on pin state.
	uint8_t system_check_safety_door_ajar()
	{
	  #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
	    #ifdef INVERT_CONTROL_PIN
	      return(bit_istrue(CONTROL_PIN,bit(SAFETY_DOOR_BIT)));
	    #else
	      return(bit_isfalse(CONTROL_PIN,bit(SAFETY_DOOR_BIT)));
	    #endif
	  #else
	    return(false); // Input pin not enabled, so just return that it's closed.
	  #endif
	}
示例#16
0
      void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate)
    #endif

#endif
{
  // If enabled, check for soft limit violations. Placed here all line motions are picked up
  // from everywhere in Grbl.
  if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) { limits_soft_check(target); }

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

  // NOTE: Backlash compensation may be installed here. It will need direction info to track when
  // to insert a backlash line motion(s) before the intended line motion and will require its own
  // plan_check_full_buffer() and check for system abort loop. Also for position reporting
  // backlash steps will need to be also tracked, which will need to be kept at a system level.
  // There are likely some other things that will need to be tracked as well. However, we feel
  // that backlash compensation should NOT be handled by Grbl itself, because there are a myriad
  // of ways to implement it and can be effective or ineffective for different CNC machines. This
  // would be better handled by the interface as a post-processor task, where the original g-code
  // is translated and inserts backlash motions that best suits the machine.
  // NOTE: Perhaps as a middle-ground, all that needs to be sent is a flag or special command that
  // indicates to Grbl what is a backlash compensation motion, so that Grbl executes the move but
  // doesn't update the machine position values. Since the position values used by the g-code
  // parser and planner are separate from the system machine positions, this is doable.

  // 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.
    if ( plan_check_full_buffer() ) { protocol_auto_cycle_start(); } // Auto-cycle start when buffer is full.
    else { break; }
  } while (1);

  #ifdef USE_LINE_NUMBERS
    plan_buffer_line(target, feed_rate, invert_feed_rate, line_number);
  #else
    #ifdef VARIABLE_SPINDLE
      // NNW
      plan_buffer_line(target, feed_rate, invert_feed_rate,rpm);
    #else
      plan_buffer_line(target, feed_rate, invert_feed_rate);
    #endif

  #endif

  // 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; }

}
示例#17
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! 
}
示例#18
0
void limits_init()
{
  LIMIT_DDR &= ~(LIMIT_MASK); // Set as input pins

  if (bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) {
    LIMIT_PORT &= ~(LIMIT_MASK); // Normal low operation. Requires external pull-down.
  } else {
    LIMIT_PORT |= (LIMIT_MASK);  // Enable internal pull-up resistors. Normal high operation.
  }

  if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)) {
    LIMIT_PCMSK |= LIMIT_MASK; // Enable specific pins of the Pin Change Interrupt
    PCICR |= (1 << LIMIT_INT); // Enable Pin Change Interrupt
  } else {
    limits_disable();
  }

  #ifdef ENABLE_SOFTWARE_DEBOUNCE
  MCUSR &= ~(1<<WDRF);
  WDTCSR |= (1<<WDCE) | (1<<WDE);
  WDTCSR = (1<<WDP0); // Set time-out at ~32msec.
  #endif
}
示例#19
0
文件: report.c 项目: rustyoz/grbl
// Prints Grbl NGC parameters (coordinate offsets, probing)
void report_ngc_parameters()
{
  float coord_data[N_AXIS];
  uint8_t coord_select, i;
  for (coord_select = 0; coord_select <= SETTING_INDEX_NCOORD; coord_select++) { 
    if (!(settings_read_coord_data(coord_select,coord_data))) { 
      report_status_message(STATUS_SETTING_READ_FAIL); 
      return;
    } 
    printPgmString(PSTR("[G"));
    switch (coord_select) {
      case 0: printPgmString(PSTR("54:")); break;
      case 1: printPgmString(PSTR("55:")); break;
      case 2: printPgmString(PSTR("56:")); break;
      case 3: printPgmString(PSTR("57:")); break;
      case 4: printPgmString(PSTR("58:")); break;
      case 5: printPgmString(PSTR("59:")); break;
      case 6: printPgmString(PSTR("28:")); break;
      case 7: printPgmString(PSTR("30:")); break;
      // case 8: printPgmString(PSTR("92:")); break; // G92.2, G92.3 not supported. Hence not stored.  
    }           
    for (i=0; i<N_AXIS; i++) {
      if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { printFloat(coord_data[i]*INCH_PER_MM); }
      else { printFloat(coord_data[i]); }
      if (i < (N_AXIS-1)) { printPgmString(PSTR(",")); }
      else { printPgmString(PSTR("]\r\n")); }
    } 
  }
  printPgmString(PSTR("[G92:")); // Print G92,G92.1 which are not persistent in memory
  for (i=0; i<N_AXIS; i++) {
    if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { printFloat(gc.coord_offset[i]*INCH_PER_MM); }
    else { printFloat(gc.coord_offset[i]); }
    if (i < (N_AXIS-1)) { printPgmString(PSTR(",")); }
    else { printPgmString(PSTR("]\r\n")); }
  } 
  report_probe_parameters(); // Print probe parameters. Not persistent in memory.
}
示例#20
0
文件: report.c 项目: rustyoz/grbl
// Prints current probe parameters. Upon a probe command, these parameters are updated upon a
// successful probe or upon a failed probe with the G38.3 without errors command (if supported). 
// These values are retained until Grbl is power-cycled, whereby they will be re-zeroed.
void report_probe_parameters()
{
  uint8_t i;
  float print_position[N_AXIS];
 
  // Report in terms of machine position.
  printPgmString(PSTR("[Probe:")); 
  for (i=0; i< N_AXIS; i++) {
    print_position[i] = sys.probe_position[i]/settings.steps_per_mm[i];
    if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { print_position[i] *= INCH_PER_MM; }
    printFloat(print_position[i]);
    if (i < (N_AXIS-1)) { printPgmString(PSTR(",")); }
  }  
  printPgmString(PSTR("]\r\n"));
}
示例#21
0
void set_punch_bit(uint8_t bit, uint8_t value)
{
    uint8_t inverted = 0;
    if (bit == PUNCH_DOWN_ENABLE_BIT) {
        inverted = BITFLAG_PUNCH_ACTUATOR_DOWN;
    } else if (bit == PUNCH_UP_ENABLE_BIT) {
        inverted = BITFLAG_PUNCH_ACTUATOR_UP;
    }

    value = value ^ bit_istrue(settings.punch_actuator_invert_mask, inverted);

    if(value) {
        PUNCH_PORT |= (1 << bit);
    } else {
        PUNCH_PORT &= ~(1<< bit);
    }
}
示例#22
0
// This should likely go away and be handled by setting the pause flag and then
// pausing in the execSystemRealtime function
// Need to check if all returns from this subsequently look to sys.stop
void pause(){
    /*

    The pause command pauses the machine in place without flushing the lines stored in the machine's
    buffer.

    When paused the machine enters a while() loop and doesn't exit until the '~' cycle resume command
    is issued from Ground Control.

    */

    bit_true(sys.pause, PAUSE_FLAG_USER_PAUSE);
    Serial.println(F("Maslow Paused"));

    while(bit_istrue(sys.pause, PAUSE_FLAG_USER_PAUSE)) {

        // Run realtime commands
        execSystemRealtime();
        if (sys.stop){return;}
    }
}
示例#23
0
void Grbl::init()
{
  // Initialize system upon power-up.
  m_serial->begin(GRBL_BAUD_RATE);   // Setup serial baud rate and interrupts
  m_settings.init(); // Load grbl settings from EEPROM
  m_stepper.init();  // Configure stepper pins and interrupt timers
  m_system.init();   // Configure pinout pins and pin-change interrupt
  
  memset(&m_system.sys, 0, sizeof(m_system.sys));  // Clear all system variables
  m_system.sys.abort = true;   // Set abort to complete initialization
  
  // 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 (bit_istrue(m_settings.settings.flags,BITFLAG_HOMING_ENABLE)) { m_system.sys.state = STATE_ALARM; }
  #endif
}
示例#24
0
文件: limits.c 项目: MisterTobi/grbl
// Performs a soft limit check. Called from mc_line() only. Assumes the machine has been homed,
// the workspace volume is in all negative space, and the system is in normal operation.
void limits_soft_check(float *target)
{
  uint8_t idx;
  uint8_t soft_limit_error = false;
  for (idx=0; idx<N_AXIS; idx++) {
   
    #ifdef HOMING_FORCE_SET_ORIGIN
      // When homing forced set origin is enabled, soft limits checks need to account for directionality.
      // NOTE: max_travel is stored as negative
      if (bit_istrue(settings.homing_dir_mask,bit(idx))) {
        if (target[idx] < 0 || target[idx] > -settings.max_travel[idx]) { soft_limit_error = true; }
      } else {
        if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) { soft_limit_error = true; }
      }
    #else  
      // NOTE: max_travel is stored as negative
      if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) { soft_limit_error = true; }
    #endif
    
    if (soft_limit_error) {
      // Force feed hold if cycle is active. All buffered blocks are guaranteed to be within 
      // workspace volume so just come to a controlled stop so position is not lost. When complete
      // enter alarm mode.
      if (sys.state == STATE_CYCLE) {
        system_set_exec_state_flag(EXEC_FEED_HOLD);
        do {
          protocol_execute_realtime();
          if (sys.abort) { return; }
        } while ( sys.state != STATE_IDLE );
      }
    
      mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown.
      system_set_exec_alarm_flag((EXEC_ALARM_SOFT_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate soft limit critical event
      protocol_execute_realtime(); // Execute to enter critical event loop and system abort
      return;
    }
  }
}
示例#25
0
void Grbl::reset()
{
  // Reset Grbl primary systems.
  m_serial->flushRx(); // Clear serial read buffer
  m_serial->flushTx();
  m_gc.init(); // Set g-code parser to default state
  m_spindle.init();
  m_coolant.init();
  m_limits.init();
  m_probe.init();
  m_plan.reset(); // Clear block buffer and planner variables
  m_stepper.reset(); // Clear stepper subsystem variables.
  
  // Sync cleared gcode and planner positions to current system position.
  m_plan.sync_position();
  m_gc.sync_position();
  
  // Reset system variables.
  m_system.sys.abort = false;
  m_system.sys.execute = 0;
  if (bit_istrue(m_settings.settings.flags,BITFLAG_AUTO_START)) { m_system.sys.auto_start = true; }
  else { m_system.sys.auto_start = false; }
}
示例#26
0
文件: report.c 项目: rustyoz/grbl
// Grbl global settings print out.
// NOTE: The numbering scheme here must correlate to storing in settings.c
void report_grbl_settings() {
  printPgmString(PSTR("$0=")); printFloat(settings.steps_per_mm[X_AXIS]);
  printPgmString(PSTR(" (x, step/mm)\r\n$1=")); printFloat(settings.steps_per_mm[Y_AXIS]);
  printPgmString(PSTR(" (y, step/mm)\r\n$2=")); printFloat(settings.steps_per_mm[Z_AXIS]);
  printPgmString(PSTR(" (z, step/mm)\r\n$3=")); printFloat(settings.max_rate[X_AXIS]);
  printPgmString(PSTR(" (x max rate, mm/min)\r\n$4=")); printFloat(settings.max_rate[Y_AXIS]);
  printPgmString(PSTR(" (y max rate, mm/min)\r\n$5=")); printFloat(settings.max_rate[Z_AXIS]);
  printPgmString(PSTR(" (z max rate, mm/min)\r\n$6=")); printFloat(settings.acceleration[X_AXIS]/(60*60)); // Convert from mm/min^2 for human readability
  printPgmString(PSTR(" (x accel, mm/sec^2)\r\n$7=")); printFloat(settings.acceleration[Y_AXIS]/(60*60)); // Convert from mm/min^2 for human readability
  printPgmString(PSTR(" (y accel, mm/sec^2)\r\n$8=")); printFloat(settings.acceleration[Z_AXIS]/(60*60)); // Convert from mm/min^2 for human readability
  printPgmString(PSTR(" (z accel, mm/sec^2)\r\n$9=")); printFloat(-settings.max_travel[X_AXIS]); // Grbl internally store this as negative.
  printPgmString(PSTR(" (x max travel, mm)\r\n$10=")); printFloat(-settings.max_travel[Y_AXIS]); // Grbl internally store this as negative.
  printPgmString(PSTR(" (y max travel, mm)\r\n$11=")); printFloat(-settings.max_travel[Z_AXIS]); // Grbl internally store this as negative.
  printPgmString(PSTR(" (z max travel, mm)\r\n$12=")); printInteger(settings.pulse_microseconds);
  printPgmString(PSTR(" (step pulse, usec)\r\n$13=")); printFloat(settings.default_feed_rate);
  printPgmString(PSTR(" (default feed, mm/min)\r\n$14=")); printInteger(settings.step_invert_mask); 
  printPgmString(PSTR(" (step port invert mask:")); print_uint8_base2(settings.step_invert_mask);  
  printPgmString(PSTR(")\r\n$15=")); printInteger(settings.dir_invert_mask); 
  printPgmString(PSTR(" (dir port invert mask:")); print_uint8_base2(settings.dir_invert_mask);  
  printPgmString(PSTR(")\r\n$16=")); printInteger(settings.stepper_idle_lock_time);
  printPgmString(PSTR(" (step idle delay, msec)\r\n$17=")); printFloat(settings.junction_deviation);
  printPgmString(PSTR(" (junction deviation, mm)\r\n$18=")); printFloat(settings.arc_tolerance);
  printPgmString(PSTR(" (arc tolerance, mm)\r\n$19=")); printInteger(settings.decimal_places);
  printPgmString(PSTR(" (n-decimals, int)\r\n$20=")); printInteger(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES));
  printPgmString(PSTR(" (report inches, bool)\r\n$21=")); printInteger(bit_istrue(settings.flags,BITFLAG_AUTO_START));
  printPgmString(PSTR(" (auto start, bool)\r\n$22=")); printInteger(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE));
  printPgmString(PSTR(" (invert step enable, bool)\r\n$23=")); printInteger(bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS));
  printPgmString(PSTR(" (invert limit pins, bool)\r\n$24=")); printInteger(bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE));
  printPgmString(PSTR(" (soft limits, bool)\r\n$25=")); printInteger(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));
  printPgmString(PSTR(" (hard limits, bool)\r\n$26=")); printInteger(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
  printPgmString(PSTR(" (homing cycle, bool)\r\n$27=")); printInteger(settings.homing_dir_mask);
  printPgmString(PSTR(" (homing dir invert mask:")); print_uint8_base2(settings.homing_dir_mask);  
  printPgmString(PSTR(")\r\n$28=")); printFloat(settings.homing_feed_rate);
  printPgmString(PSTR(" (homing feed, mm/min)\r\n$29=")); printFloat(settings.homing_seek_rate);
  printPgmString(PSTR(" (homing seek, mm/min)\r\n$30=")); printInteger(settings.homing_debounce_delay);
  printPgmString(PSTR(" (homing debounce, msec)\r\n$31=")); printFloat(settings.homing_pulloff);
  printPgmString(PSTR(" (homing pull-off, mm)\r\n")); 
}
int startGrbl(void)
{
  // 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
  sei(); // Enable interrupts
  
  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
    
//  Wire.begin();

    
    
  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.
      
        syspos(&encdr_x,&encdr_y,&encdr_z);
        ofst_x=encdr_x;
        ofst_y=encdr_y;
        ofst_z=encdr_z;
        
      // 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();

 //   syspos(&encdr_x,&encdr_y);
      
    protocol_process(); // ... process the serial protocol
    
    
      
  }
  return 0;   /* never reached */
}
示例#28
0
// Directs and executes one line of formatted input from protocol_process. While mostly
// incoming streaming g-code blocks, this also executes Grbl internal commands, such as 
// settings, initiating the homing cycle, and toggling switch states. This differs from
// the realtime command module by being susceptible to when Grbl is ready to execute the 
// next line during a cycle, so for switches like block delete, the switch only effects
// the lines that are processed afterward, not necessarily real-time during a cycle, 
// since there are motions already stored in the buffer. However, this 'lag' should not
// be an issue, since these commands are not typically used during a cycle.
uint8_t system_execute_line(char *line) 
{   
  uint8_t char_counter = 1; 
  uint8_t helper_var = 0; // Helper variable
  float parameter, value;
  switch( line[char_counter] ) {
    case 0 : report_grbl_help(); break;
    case '$': case 'G': case 'C': case 'X':
      if ( line[(char_counter+1)] != 0 ) { return(STATUS_INVALID_STATEMENT); }
      switch( line[char_counter] ) {
        case '$' : // Prints Grbl settings
          if ( sys.state & (STATE_CYCLE | STATE_HOLD) ) { return(STATUS_IDLE_ERROR); } // Block during cycle. Takes too long to print.
          else { report_grbl_settings(); }
          break;
        case 'G' : // Prints gcode parser state
          // TODO: Move this to realtime commands for GUIs to request this data during suspend-state.
          report_gcode_modes();
          break;   
        case 'C' : // Set check g-code mode [IDLE/CHECK]
          // Perform reset when toggling off. Check g-code mode should only work if Grbl
          // is idle and ready, regardless of alarm locks. This is mainly to keep things
          // simple and consistent.
          if ( sys.state == STATE_CHECK_MODE ) { 
            mc_reset(); 
            report_feedback_message(MESSAGE_DISABLED);
          } else {
            if (sys.state) { return(STATUS_IDLE_ERROR); } // Requires no alarm mode.
            sys.state = STATE_CHECK_MODE;
            report_feedback_message(MESSAGE_ENABLED);
          }
          break; 
        case 'X' : // Disable alarm lock [ALARM]
          if (sys.state == STATE_ALARM) { 
            report_feedback_message(MESSAGE_ALARM_UNLOCK);
            sys.state = STATE_IDLE;
            // Don't run startup script. Prevents stored moves in startup from causing accidents.
          #ifndef DEFAULTS_TRINAMIC
          if (system_check_safety_door_ajar()) { // Check safety door switch before returning.
              bit_true(sys_rt_exec_state, EXEC_SAFETY_DOOR);
              protocol_execute_realtime(); // Enter safety door mode.
            }
	  #endif
          } // Otherwise, no effect.
          break;                   
    //  case 'J' : break;  // Jogging methods
          // TODO: Here jogging can be placed for execution as a seperate subprogram. It does not need to be 
          // susceptible to other realtime commands except for e-stop. The jogging function is intended to
          // be a basic toggle on/off with controlled acceleration and deceleration to prevent skipped 
          // steps. The user would supply the desired feedrate, axis to move, and direction. Toggle on would
          // start motion and toggle off would initiate a deceleration to stop. One could 'feather' the
          // motion by repeatedly toggling to slow the motion to the desired location. Location data would 
          // need to be updated real-time and supplied to the user through status queries.
          //   More controlled exact motions can be taken care of by inputting G0 or G1 commands, which are 
          // handled by the planner. It would be possible for the jog subprogram to insert blocks into the
          // block buffer without having the planner plan them. It would need to manage de/ac-celerations 
          // on its own carefully. This approach could be effective and possibly size/memory efficient.  
//       }
//       break;
      }
      break;
    default : 
      // Block any system command that requires the state as IDLE/ALARM. (i.e. EEPROM, homing)
      if ( !(sys.state == STATE_IDLE || sys.state == STATE_ALARM) ) { return(STATUS_IDLE_ERROR); }
      switch( line[char_counter] ) {
        case '#' : // Print Grbl NGC parameters
          if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); }
          else { report_ngc_parameters(); }
          break;          
        case 'H' : // Perform homing cycle [IDLE/ALARM]
          if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { 
            sys.state = STATE_HOMING; // Set system state variable
            // Only perform homing if Grbl is idle or lost.
            
            // TODO: Likely not required.
	#ifndef DEFAULTS_TRINAMIC
            if (system_check_safety_door_ajar()) { // Check safety door switch before homing.
              bit_true(sys_rt_exec_state, EXEC_SAFETY_DOOR);
              protocol_execute_realtime(); // Enter safety door mode.
            }
        #endif
            
            mc_homing_cycle(); 
            if (!sys.abort) {  // Execute startup scripts after successful homing.
              sys.state = STATE_IDLE; // Set to IDLE when complete.
              st_go_idle(); // Set steppers to the settings idle state before returning.
              system_execute_startup(line); 
            }
          } else { return(STATUS_SETTING_DISABLED); }
          break;
        case 'I' : // Print or store build info. [IDLE/ALARM]
          if ( line[++char_counter] == 0 ) { 
            settings_read_build_info(line);
            report_build_info(line);
          } else { // Store startup line [IDLE/ALARM]
            if(line[char_counter++] != '=') { return(STATUS_INVALID_STATEMENT); }
            helper_var = char_counter; // Set helper variable as counter to start of user info line.
            do {
              line[char_counter-helper_var] = line[char_counter];
            } while (line[char_counter++] != 0);
            settings_store_build_info(line);
          }
          break; 
        case 'R' : // Restore defaults [IDLE/ALARM]
          if (line[++char_counter] != 'S') { return(STATUS_INVALID_STATEMENT); }
          if (line[++char_counter] != 'T') { return(STATUS_INVALID_STATEMENT); }
          if (line[++char_counter] != '=') { return(STATUS_INVALID_STATEMENT); }
          if (line[char_counter+2] != 0) { return(STATUS_INVALID_STATEMENT); }                        
          switch (line[++char_counter]) {
            case '$': settings_restore(SETTINGS_RESTORE_DEFAULTS); break;
            case '#': settings_restore(SETTINGS_RESTORE_PARAMETERS); break;
            case '*': settings_restore(SETTINGS_RESTORE_ALL); break;
            default: return(STATUS_INVALID_STATEMENT);
          }
          report_feedback_message(MESSAGE_RESTORE_DEFAULTS);
          mc_reset(); // Force reset to ensure settings are initialized correctly.
          break;
        case 'N' : // Startup lines. [IDLE/ALARM]
          if ( line[++char_counter] == 0 ) { // Print startup lines
            for (helper_var=0; helper_var < N_STARTUP_LINE; helper_var++) {
              if (!(settings_read_startup_line(helper_var, line))) {
                report_status_message(STATUS_SETTING_READ_FAIL);
              } else {
                report_startup_line(helper_var,line);
              }
            }
            break;
          } else { // Store startup line [IDLE Only] Prevents motion during ALARM.
            if (sys.state != STATE_IDLE) { return(STATUS_IDLE_ERROR); } // Store only when idle.
            helper_var = true;  // Set helper_var to flag storing method. 
            // No break. Continues into default: to read remaining command characters.
          }
        default :  // Storing setting methods [IDLE/ALARM]
          if(!read_float(line, &char_counter, &parameter)) { return(STATUS_BAD_NUMBER_FORMAT); }
          if(line[char_counter++] != '=') { return(STATUS_INVALID_STATEMENT); }
          if (helper_var) { // Store startup line
            // Prepare sending gcode block to gcode parser by shifting all characters
            helper_var = char_counter; // Set helper variable as counter to start of gcode block
            do {
              line[char_counter-helper_var] = line[char_counter];
            } while (line[char_counter++] != 0);
            // Execute gcode block to ensure block is valid.
            helper_var = gc_execute_line(line); // Set helper_var to returned status code.
            if (helper_var) { return(helper_var); }
            else { 
              helper_var = trunc(parameter); // Set helper_var to int value of parameter
              settings_store_startup_line(helper_var,line);
            }
          } else { // Store global setting.
            if(!read_float(line, &char_counter, &value)) { return(STATUS_BAD_NUMBER_FORMAT); }
            if((line[char_counter] != 0) || (parameter > 255)) { return(STATUS_INVALID_STATEMENT); }
            return(settings_store_global_setting((uint8_t)parameter, value));
          }
      }    
  }
  return(STATUS_OK); // If '$' command makes it to here, then everything's ok.
}
示例#29
0
文件: main.c 项目: MrSurly/grbl
int main(void)
{
  // Initialize system upon power-up.
  serial_init();   // Setup serial baud rate and interrupts
  settings_init(); // Load Grbl settings from EEPROM
  stepper_init();  // Configure stepper pins and interrupt timers
  system_init();   // Configure pinout pins and pin-change interrupt

  memset(sys_position,0,sizeof(sys_position)); // Clear machine position.
  sei(); // Enable interrupts

  // Initialize system state.
  #ifdef FORCE_INITIALIZATION_ALARM
    // Force Grbl into an ALARM state upon a power-cycle or hard reset.
    sys.state = STATE_ALARM;
  #else
    sys.state = STATE_IDLE;
  #endif
  
  // 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 (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { sys.state = STATE_ALARM; }
  #endif

  // Grbl initialization loop upon power-up or a system abort. For the latter, all processes
  // will return to this loop to be cleanly re-initialized.
  for(;;) {

    // Reset system variables.
    uint8_t prior_state = sys.state;
    memset(&sys, 0, sizeof(system_t)); // Clear system struct variable.
    sys.state = prior_state;
    sys.f_override = DEFAULT_FEED_OVERRIDE;  // Set to 100%
    sys.r_override = DEFAULT_RAPID_OVERRIDE; // Set to 100%
    sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE; // Set to 100%
		memset(sys_probe_position,0,sizeof(sys_probe_position)); // Clear probe position.
    sys_probe_state = 0;
    sys_rt_exec_state = 0;
    sys_rt_exec_alarm = 0;
    sys_rt_exec_motion_override = 0;
    sys_rt_exec_accessory_override = 0;

    // Reset Grbl primary systems.
    serial_reset_read_buffer(); // Clear serial read buffer
    gc_init(); // Set g-code parser to default state
    spindle_init();
    coolant_init();
    limits_init();
    probe_init();
    plan_reset(); // Clear block buffer and planner variables
    st_reset(); // Clear stepper subsystem variables.

    // Sync cleared gcode and planner positions to current system position.
    plan_sync_position();
    gc_sync_position();

    // Print welcome message. Indicates an initialization has occured at power-up or with a reset.
    report_init_message();

    // Start Grbl main loop. Processes program inputs and executes them.
    protocol_main_loop();

  }
  return 0;   /* Never reached */
}
示例#30
0
文件: jogging.c 项目: sknipa/GRBL-JOG
void jogging() 
// Tests jog port pins and moves steppers
{
  uint8_t jog_bits, jog_bits_old, out_bits0, jog_exit, last_sys_state;
  uint8_t i, limit_state, spindle_bits;
  
  uint32_t dest_step_rate, step_rate, step_delay; // Step delay after pulse 

  switch (sys.state) {
    case STATE_CYCLE: case STATE_HOMING: case STATE_INIT:
      LED_PORT |= (1<<LED_ERROR_BIT);     
      return;
    case STATE_ALARM: case STATE_QUEUED: 
      LED_PORT &= ~(1<<LED_ERROR_BIT);  break;
    default: 
      LED_PORT |= (1<<LED_ERROR_BIT);                 
  }
  last_sys_state = sys.state;
  
  spindle_bits = (~PINOUT_PIN) & (1<<PIN_SPIN_TOGGLE); // active low          
  if (spindle_bits) {
    if (spindle_status) {
//      gc.spindle_direction = 0; 
      spindle_run(0);
    }
    else {
//      gc.spindle_direction = 1;   // also update gcode spindle status
      spindle_run(1);
    } 
    spindle_btn_release();  
    delay_ms(20);
  }

  jog_bits = (~JOGSW_PIN) & JOGSW_MASK; // active low
  if (!jog_bits) { return; }  // nothing pressed
  
  // At least one jog/joystick switch is active 
  if (jog_bits & (1<<JOG_ZERO)) {     // Zero-Button gedrückt
    jog_btn_release();
    sys.state = last_sys_state;
    if (bit_isfalse(PINOUT_PIN,bit(PIN_RESET))) { // RESET und zusätzlich ZERO gedrückt: Homing  
      if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { 
        // Only perform homing if Grbl is idle or lost.
        if ( sys.state==STATE_IDLE || sys.state==STATE_ALARM ) { 
          mc_go_home(); 
          if (!sys.abort) { protocol_execute_startup(); } // Execute startup scripts after successful homing.
        }
      }
    } else { // Zero current work position

      sys_sync_current_position();

//      gc.coord_system[i]    Current work coordinate system (G54+). Stores offset from absolute machine
//                            position in mm. Loaded from EEPROM when called.
//      gc.coord_offset[i]    Retains the G92 coordinate offset (work coordinates) relative to
//                            machine zero in mm. Non-persistent. Cleared upon reset and boot.  

      for (i=0; i<=2; i++) { // Axes indices are consistent, so loop may be used.
        gc.coord_offset[i] = gc.position[i] - gc.coord_system[i];
      } 

// Z-Achse um bestimmten Betrag zurückziehen                  
      mc_line(gc.position[X_AXIS], gc.position[Y_AXIS], gc.position[Z_AXIS] 
        + (settings.z_zero_pulloff * settings.z_scale), settings.default_seek_rate, false);
        
      plan_synchronize(); // Make sure the motion completes
      
      gc.position[Z_AXIS] = gc.position[Z_AXIS] - (settings.z_zero_gauge * settings.z_scale);
      gc.coord_offset[Z_AXIS] = gc.position[Z_AXIS] - gc.coord_system[Z_AXIS];
      
// The gcode parser position circumvented by the pull-off maneuver, so sync position vectors.
// Sets the planner position vector to current steps. Called by the system abort routine.
// Sets g-code parser position in mm. Input in steps. Called by the system abort and hard
      sys_sync_current_position(); // Syncs all internal position vectors to the current system position.

    }
    return;
  } 
  
  ADCSRA = ADCSRA_init | (1<<ADIF); //0x93, clear ADIF

  uint8_t reverse_flag = 0;
  uint8_t out_bits = 0; 
  uint8_t jog_select = 0; 
  out_bits0 = (0) ^ (settings.invert_mask); 
  
  ADCSRA = ADCSRA_init | (1<<ADIF); //0x93, clear ADIF
  ADCSRA = ADCSRA_init | (1<<ADSC); //0xC3; start conversion  
  
  sys.state = STATE_JOG;
  
  // check for reverse switches 
  if (jog_bits & (1<<JOGREV_X_BIT)) { // X reverse switch on
    out_bits0 ^= (1<<X_DIRECTION_BIT);
    out_bits = out_bits0 ^ (1<<X_STEP_BIT); 
    reverse_flag = 1;
  }                                                            
  if (jog_bits & (1<<JOGREV_Y_BIT)) { // Y reverse switch on
    out_bits0 ^= (1<<Y_DIRECTION_BIT);
    out_bits = out_bits0 ^ (1<<Y_STEP_BIT);
    reverse_flag = 1;
    jog_select = 1;
  }                                                            
  if (jog_bits & (1<<JOGREV_Z_BIT)) { // Z reverse switch on
    out_bits0 ^= (1<<Z_DIRECTION_BIT);
    out_bits = out_bits0 ^ (1<<Z_STEP_BIT);
    reverse_flag = 1;
    jog_select = 2;
  } 
  
  // check for forward switches 
  if (jog_bits & (1<<JOGFWD_X_BIT)) { // X forward switch on
    out_bits = out_bits0 ^ (1<<X_STEP_BIT);
  }                                                            
  if (jog_bits & (1<<JOGFWD_Y_BIT)) { // Y forward switch on
    out_bits = out_bits0 ^ (1<<Y_STEP_BIT);
    jog_select = 1;
  }                                                            
  if (jog_bits & (1<<JOGFWD_Z_BIT)) { // Z forward switch on
    out_bits = out_bits0 ^ (1<<Z_STEP_BIT);
    jog_select = 2;
  } 

  dest_step_rate = ADCH;    // set initial dest_step_rate according to analog input
  dest_step_rate = (dest_step_rate * JOG_SPEED_FAC) + JOG_MIN_SPEED;  
  step_rate = JOG_MIN_SPEED;   // set initial step rate
  jog_exit = 0; 
  while (!(ADCSRA && (1<<ADIF))) {} // warte bis ADIF-Bit gesetzt 
  ADCSRA = ADCSRA_init; // exit conversion
  
  st_wake_up();
  
 
  // prepare direction with small delay, direction settle time
  STEPPING_PORT = (STEPPING_PORT & ~STEPPING_MASK) | (out_bits0 & STEPPING_MASK);
  delay_us(10);
  jog_bits_old = jog_bits;
  i = 0;  // now index for sending position data 
  
  for(;;) { // repeat until button/joystick released  
//    report_realtime_status(); // benötigt viel Zeit!
    
    ADCSRA = ADCSRA_init | (1<<ADIF); //0x93, clear ADIF

    // Get limit pin state
    #ifdef LIMIT_SWITCHES_ACTIVE_HIGH
      // When in an active-high switch configuration
      limit_state = LIMIT_PIN;
    #else
      limit_state = LIMIT_PIN ^ LIMIT_MASK;
    #endif
    if ((limit_state & LIMIT_MASK) && reverse_flag) { jog_exit = 1; } // immediate stop
 
    jog_bits = (~JOGSW_PIN) & JOGSW_MASK; // active low
    if (jog_bits == jog_bits_old) { // nothing changed
      if (step_rate < (dest_step_rate - 5)) { // Hysterese für A/D-Wandlung
        step_rate += JOG_RAMP; // accellerate
      }                                    
      if (step_rate > (dest_step_rate + 5)) { // Hysterese für A/D-Wandlung
        step_rate -= JOG_RAMP; // brake
      }                                    
    }
    else {
      if (step_rate > (JOG_MIN_SPEED*2)) {  // switch change happened, fast brake to complete stop
        step_rate = ((step_rate * 99) / 100) - 10;
      }
      else { jog_exit = 1; } // finished to stop and exit
    }
    
   
    // stop and exit if done
    if (jog_exit || (sys.execute & EXEC_RESET)) { 
      st_go_idle(); 
      sys.state = last_sys_state;
      sys_sync_current_position();
      return; 
    }
    
    // update position registers
    if (reverse_flag) {
      sys.position[jog_select]--;
    } 
    else {
      sys.position[jog_select]++; 
    }
    ADCSRA = ADCSRA_init | (1<<ADSC); //0xC3; start ADC conversion
    // Both direction and step pins appropriately inverted and set. Perform one step
    STEPPING_PORT = (STEPPING_PORT & ~STEPPING_MASK) | (out_bits & STEPPING_MASK);
    delay_us(settings.pulse_microseconds);
    STEPPING_PORT = (STEPPING_PORT & ~STEPPING_MASK) | (out_bits0 & STEPPING_MASK);
    step_delay = (1000000/step_rate) - settings.pulse_microseconds - 100; // 100 = fester Wert für Schleifenzeit
  
    if (sys.execute & EXEC_STATUS_REPORT) { // status report requested, print short msg only
      printPgmString(PSTR("Jog\r\n"));
      sys.execute = 0;
    }
    delay_us(step_delay);
    
#ifdef JOG_SPI_PRESENT
    send_spi_position(i); // bei jedem Durchlauf nur eine Achse übertragen
    i++;
    if (i>2) {i=0;}
#endif 
      
    while (!(ADCSRA && (1<<ADIF))) {} // warte ggf. bis ADIF-Bit gesetzt  
    ADCSRA = ADCSRA_init;     // exit conversion
    dest_step_rate = ADCH;    // set next dest_step_rate according to analog input
    dest_step_rate = (dest_step_rate * JOG_SPEED_FAC) + JOG_MIN_SPEED;  

  }
}