// Monitors probe pin state and records the system position when detected. Called by the // stepper ISR per ISR tick. // NOTE: This function must be extremely efficient as to not bog down the stepper ISR. void probe_state_monitor() { if (sys.probe_state == PROBE_ACTIVE) { if (probe_get_state()) { sys.probe_state = PROBE_OFF; memcpy(sys.probe_position, sys.position, sizeof(float)*N_AXIS); bit_true(sys.execute, EXEC_FEED_HOLD); } } }
// Monitors probe pin state and records the system position when detected. Called by the // stepper ISR per ISR tick. // NOTE: This function must be extremely efficient as to not bog down the stepper ISR. void probe_state_monitor() { if (sys_probe_state == PROBE_ACTIVE) { if (probe_get_state()) { sys_probe_state = PROBE_OFF; memcpy(sys.probe_position, sys.position, sizeof(sys.position)); bit_true(sys_rt_exec_state, EXEC_MOTION_CANCEL); } } }
// Monitors probe pin state and records the system position when detected. Called by the // stepper ISR per ISR tick. // NOTE: This function must be extremely efficient as to not bog down the stepper ISR. void probe_state_monitor() { #ifndef PUNCH_ACTIVATED if (sys_probe_state == PROBE_ACTIVE) { if (probe_get_state()) { sys_probe_state = PROBE_OFF; memcpy(sys.probe_position, sys.position, sizeof(float)*N_AXIS); bit_true(sys_rt_exec_state, EXEC_MOTION_CANCEL); } } #endif }
void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate, uint8_t is_probe_away, uint8_t is_no_error) #endif { // TODO: Need to update this cycle so it obeys a non-auto cycle start. if (sys.state == STATE_CHECK_MODE) { return; } // Finish all queued commands and empty planner buffer before starting probe cycle. protocol_buffer_synchronize(); // Initialize probing control variables sys.probe_succeeded = false; // Re-initialize probe history before beginning cycle. probe_configure_invert_mask(is_probe_away); // After syncing, check if probe is already triggered. If so, halt and issue alarm. // NOTE: This probe initialization error applies to all probing cycles. if ( probe_get_state() ) { // Check probe pin state. bit_true_atomic(sys_rt_exec_alarm, EXEC_ALARM_PROBE_FAIL); protocol_execute_realtime(); } if (sys.abort) { return; } // Return if system reset has been issued. // Setup and queue probing motion. Auto cycle-start should not start the cycle. #ifdef USE_LINE_NUMBERS mc_line(target, feed_rate, invert_feed_rate, line_number); #else mc_line(target, feed_rate, invert_feed_rate); #endif // Activate the probing state monitor in the stepper module. sys_probe_state = PROBE_ACTIVE; // Perform probing cycle. Wait here until probe is triggered or motion completes. bit_true_atomic(sys_rt_exec_state, EXEC_CYCLE_START); do { protocol_execute_realtime(); if (sys.abort) { return; } // Check for system abort } while (sys.state != STATE_IDLE); // Probing cycle complete! // Set state variables and error out, if the probe failed and cycle with error is enabled. if (sys_probe_state == PROBE_ACTIVE) { if (is_no_error) { memcpy(sys.probe_position, sys.position, sizeof(float)*N_AXIS); } else { bit_true_atomic(sys_rt_exec_alarm, EXEC_ALARM_PROBE_FAIL); } } else { sys.probe_succeeded = true; // Indicate to system the probing cycle completed successfully. } sys_probe_state = PROBE_OFF; // Ensure probe state monitor is disabled. protocol_execute_realtime(); // Check and execute run-time commands if (sys.abort) { return; } // Check for system abort // Reset the stepper and planner buffers to remove the remainder of the probe motion. st_reset(); // Reest step segment buffer. plan_reset(); // Reset planner buffer. Zero planner positions. Ensure probing motion is cleared. plan_sync_position(); // Sync planner position to current machine position. // TODO: Update the g-code parser code to not require this target calculation but uses a gc_sync_position() call. // NOTE: The target[] variable updated here will be sent back and synced with the g-code parser. system_convert_array_steps_to_mpos(target, sys.position); #ifdef MESSAGE_PROBE_COORDINATES // All done! Output the probe position as message. report_probe_parameters(); #endif }
// Perform tool length probe cycle. Requires probe switch. // NOTE: Upon probe failure, the program will be stopped and placed into ALARM state. uint8_t mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t parser_flags) { // TODO: Need to update this cycle so it obeys a non-auto cycle start. if (sys.state == STATE_CHECK_MODE) { return(GC_PROBE_CHECK_MODE); } // Finish all queued commands and empty planner buffer before starting probe cycle. protocol_buffer_synchronize(); if (sys.abort) { return(GC_PROBE_ABORT); } // Return if system reset has been issued. // Initialize probing control variables uint8_t is_probe_away = bit_istrue(parser_flags,GC_PARSER_PROBE_IS_AWAY); uint8_t is_no_error = bit_istrue(parser_flags,GC_PARSER_PROBE_IS_NO_ERROR); sys.probe_succeeded = false; // Re-initialize probe history before beginning cycle. probe_configure_invert_mask(is_probe_away); // After syncing, check if probe is already triggered. If so, halt and issue alarm. // NOTE: This probe initialization error applies to all probing cycles. if ( probe_get_state() ) { // Check probe pin state. system_set_exec_alarm(EXEC_ALARM_PROBE_FAIL_INITIAL); protocol_execute_realtime(); probe_configure_invert_mask(false); // Re-initialize invert mask before returning. return(GC_PROBE_FAIL_INIT); // Nothing else to do but bail. } // Setup and queue probing motion. Auto cycle-start should not start the cycle. mc_line(target, pl_data); // Activate the probing state monitor in the stepper module. sys_probe_state = PROBE_ACTIVE; // Perform probing cycle. Wait here until probe is triggered or motion completes. system_set_exec_state_flag(EXEC_CYCLE_START); do { protocol_execute_realtime(); if (sys.abort) { return(GC_PROBE_ABORT); } // Check for system abort } while (sys.state != STATE_IDLE); // Probing cycle complete! // Set state variables and error out, if the probe failed and cycle with error is enabled. if (sys_probe_state == PROBE_ACTIVE) { if (is_no_error) { memcpy(sys_probe_position, sys_position, sizeof(sys_position)); } else { system_set_exec_alarm(EXEC_ALARM_PROBE_FAIL_CONTACT); } } else { sys.probe_succeeded = true; // Indicate to system the probing cycle completed successfully. } sys_probe_state = PROBE_OFF; // Ensure probe state monitor is disabled. probe_configure_invert_mask(false); // Re-initialize invert mask. protocol_execute_realtime(); // Check and execute run-time commands // Reset the stepper and planner buffers to remove the remainder of the probe motion. st_reset(); // Reset step segment buffer. plan_reset(); // Reset planner buffer. Zero planner positions. Ensure probing motion is cleared. plan_sync_position(); // Sync planner position to current machine position. #ifdef MESSAGE_PROBE_COORDINATES // All done! Output the probe position as message. report_probe_parameters(); #endif if (sys.probe_succeeded) { return(GC_PROBE_FOUND); } // Successful probe cycle. else { return(GC_PROBE_FAIL_END); } // Failed to trigger probe within travel. With or without error. }
void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate) #endif { // TODO: Need to update this cycle so it obeys a non-auto cycle start. if (sys.state == STATE_CHECK_MODE) { return; } // Finish all queued commands and empty planner buffer before starting probe cycle. protocol_buffer_synchronize(); uint8_t auto_start_state = sys.auto_start; // Store run state // After syncing, check if probe is already triggered. If so, halt and issue alarm. if (probe_get_state()) { bit_true_atomic(sys.execute, EXEC_CRIT_EVENT); protocol_execute_runtime(); } if (sys.abort) { return; } // Return if system reset has been issued. // Setup and queue probing motion. Auto cycle-start should not start the cycle. #ifdef USE_LINE_NUMBERS mc_line(target, feed_rate, invert_feed_rate, line_number); #else mc_line(target, feed_rate, invert_feed_rate); #endif // Activate the probing monitor in the stepper module. sys.probe_state = PROBE_ACTIVE; // Perform probing cycle. Wait here until probe is triggered or motion completes. bit_true_atomic(sys.execute, EXEC_CYCLE_START); do { protocol_execute_runtime(); if (sys.abort) { return; } // Check for system abort } while ((sys.state != STATE_IDLE) && (sys.state != STATE_QUEUED)); // Probing motion complete. If the probe has not been triggered, error out. if (sys.probe_state == PROBE_ACTIVE) { bit_true_atomic(sys.execute, EXEC_CRIT_EVENT); } protocol_execute_runtime(); // Check and execute run-time commands if (sys.abort) { return; } // Check for system abort // Reset the stepper and planner buffers to remove the remainder of the probe motion. st_reset(); // Reest step segment buffer. plan_reset(); // Reset planner buffer. Zero planner positions. Ensure probing motion is cleared. plan_sync_position(); // Sync planner position to current machine position. // Pull-off triggered probe to the trigger location since we had to decelerate a little beyond // it to stop the machine in a controlled manner. uint8_t idx; for(idx=0; idx<N_AXIS; idx++){ // NOTE: The target[] variable updated here will be sent back and synced with the g-code parser. target[idx] = (float)sys.probe_position[idx]/settings.steps_per_deg[idx]; } #ifdef USE_LINE_NUMBERS mc_line(target, feed_rate, invert_feed_rate, line_number); #else mc_line(target, feed_rate, invert_feed_rate); #endif // Execute pull-off motion and wait until it completes. bit_true_atomic(sys.execute, EXEC_CYCLE_START); protocol_buffer_synchronize(); if (sys.abort) { return; } // Return if system reset has been issued. sys.auto_start = auto_start_state; // Restore run state before returning #ifdef MESSAGE_PROBE_COORDINATES // All done! Output the probe position as message. report_probe_parameters(); #endif }
// 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 idx; 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_MOTION_CANCEL: // Report run state. 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; case STATE_SAFETY_DOOR: printPgmString(PSTR("<Door")); break; } // If reporting a position, convert the current step count (current_position) to millimeters. if (bit_istrue(settings.status_report_mask,(BITFLAG_RT_STATUS_MACHINE_POSITION | BITFLAG_RT_STATUS_WORK_POSITION))) { system_convert_array_steps_to_mpos(print_position,current_position); } // Report machine position if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_MACHINE_POSITION)) { printPgmString(PSTR(",MPos:")); for (idx=0; idx< N_AXIS; idx++) { printFloat_CoordValue(print_position[idx]); if (idx < (N_AXIS-1)) { printPgmString(PSTR(",")); } } } // Report work position if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_WORK_POSITION)) { printPgmString(PSTR(",WPos:")); for (idx=0; idx< N_AXIS; idx++) { // Apply work coordinate offsets and tool length offset to current position. print_position[idx] -= gc_state.coord_system[idx]+gc_state.coord_offset[idx]; if (idx == TOOL_LENGTH_OFFSET_AXIS) { print_position[idx] -= gc_state.tool_length_offset; } printFloat_CoordValue(print_position[idx]); if (idx < (N_AXIS-1)) { printPgmString(PSTR(",")); } } } // Returns the number of active blocks are in the planner buffer. if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_PLANNER_BUFFER)) { printPgmString(PSTR(",Buf:")); print_uint8_base10(plan_get_block_buffer_count()); } // Report serial read buffer status if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_SERIAL_RX)) { printPgmString(PSTR(",RX:")); print_uint8_base10(serial_get_rx_buffer_count()); } #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 #ifdef REPORT_REALTIME_RATE // Report realtime rate printPgmString(PSTR(",F:")); printFloat_RateValue(st_get_realtime_rate()); #endif #ifdef REPORT_ALL_PIN_STATES if (bit_istrue(settings.status_report_mask, ( BITFLAG_RT_STATUS_LIMIT_PINS| BITFLAG_RT_STATUS_PROBE_PIN | BITFLAG_RT_STATUS_CONTROL_PINS ))) { printPgmString(PSTR(",Pin:")); if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_LIMIT_PINS)) { print_unsigned_int8(limits_get_state(),2,N_AXIS); } printPgmString(PSTR("|")); if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_PROBE_PIN)) { if (probe_get_state()) { printPgmString(PSTR("1")); } else { printPgmString(PSTR("0")); } } printPgmString(PSTR("|")); if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_CONTROL_PINS)) { print_unsigned_int8(system_control_get_state(),2,N_CONTROL_PIN); } } #else if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_LIMIT_PINS)) { printPgmString(PSTR(",Lim:")); print_unsigned_int8(limits_get_state(),2,N_AXIS); } #endif printPgmString(PSTR(">\r\n")); }