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 */
}
Esempio n. 2
0
File: protocol.c Progetto: koo5/grbl
// 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 runtime 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 protocol_execute_line(char *line) 
{   
  // Grbl internal command and parameter lines are of the form '$4=374.3' or '$' for help  
  if(line[0] == '$') {
    
    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 '$' : // Prints Grbl settings
        if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); }
        else { report_grbl_settings(); }
        break;
      case '#' : // Print gcode parameters
        if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); }
        else { report_gcode_parameters(); }
        break;
      case 'G' : // Prints gcode parser state
        if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); }
        else { report_gcode_modes(); }
        break;
      case 'C' : // Set check g-code mode
        if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); }
        // 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); }
          sys.state = STATE_CHECK_MODE;
          report_feedback_message(MESSAGE_ENABLED);
        }
        break; 
      case 'X' : // Disable alarm lock
        if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); }
        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.
        }
        break;               
      case 'H' : // Perform homing cycle
        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 { return(STATUS_IDLE_ERROR); }
        } else { return(STATUS_SETTING_DISABLED); }
        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 runtime 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.
      case 'N' : // Startup lines. 
        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
          helper_var = true;  // Set helper_var to flag storing method. 
          // No break. Continues into default: to read remaining command characters.
        }
      default :  // Storing setting methods
        if(!read_float(line, &char_counter, &parameter)) { return(STATUS_BAD_NUMBER_FORMAT); }
        if(line[char_counter++] != '=') { return(STATUS_UNSUPPORTED_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) { return(STATUS_UNSUPPORTED_STATEMENT); }
          return(settings_store_global_setting(parameter, value));
        }
    }
    return(STATUS_OK); // If '$' command makes it to here, then everything's ok.

  } else {
    return(gc_execute_line(line));    // Everything else is gcode
  }
}
Esempio n. 3
0
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;  

  }
}
Esempio n. 4
0
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 */
}