Updated variable spindle and new probing. Minor bug fixes.
- Minor bug fix for variable spindle PWM output. Values smaller than the minimum RPM for the spindle would overflow the PWM value. Thanks Rob! - Created an optional minimum spindle PWM low-mark value as a compile-time option. This is for special circumstances when the PWM has to be at a certain level to be read by the spindle controller. - Refactored the new probing commands (G38.3, G38.4, G38.5) code to work better with the rest of Grbl’s systems. - Refactored mc_probe() and mc_arc() to accept the mode of the command, i.e. clockwise vs counter, toward vs away, etc. This is to make these functions independent of gcode state variables. - Removed the pull off motion in the probing cycle. This is not an official operation and was added for user simplicity, but wrongly did so. So bye bye. - Created a configure probe invert mask function to handle the different probe pin setting and probing cycle modes with a single mask. - Minor bug fix with reporting motion modes via $G. G38.2 wasn’t showing up. It now does, along with the other new probing commands. - Refactored some of the new pin configurations for the future of Grbl. -
This commit is contained in:
parent
15071385f7
commit
7e67395463
8
config.h
8
config.h
@ -156,7 +156,7 @@
|
||||
// The hardware PWM output on pin D11 is required for variable spindle output voltages.
|
||||
// #define VARIABLE_SPINDLE // Default disabled. Uncomment to enable.
|
||||
|
||||
// Use by the variable spindle output only. These parameters set the maximum and minimum spindle speed
|
||||
// Used by the variable spindle output only. These parameters set the maximum and minimum spindle speed
|
||||
// "S" g-code values to correspond to the maximum and minimum pin voltages. There are 256 discrete and
|
||||
// equally divided voltage bins between the maximum and minimum spindle speeds. So for a 5V pin, 1000
|
||||
// max rpm, and 250 min rpm, the spindle output voltage would be set for the following "S" commands:
|
||||
@ -164,6 +164,12 @@
|
||||
#define SPINDLE_MAX_RPM 1000.0 // Max spindle RPM. This value is equal to 100% duty cycle on the PWM.
|
||||
#define SPINDLE_MIN_RPM 0.0 // Min spindle RPM. This value is equal to (1/256) duty cycle on the PWM.
|
||||
|
||||
// Used by variable spindle output only. This forces the PWM output to a minimum duty cycle when enabled.
|
||||
// When disabled, the PWM pin will still read 0V. Most users will not need this option, but it may be
|
||||
// useful in certain scenarios. This setting does not update the minimum spindle RPM calculations. Any
|
||||
// spindle RPM output lower than this value will be set to this value.
|
||||
// #define MINIMUM_SPINDLE_PWM 5 // Default disabled. Uncomment to enable. Integer (0-255)
|
||||
|
||||
// Minimum planner junction speed. Sets the default minimum junction speed the planner plans to at
|
||||
// every buffer block junction, except for starting from rest and end of the buffer, which are always
|
||||
// zero. This value controls how fast the machine moves through junctions with no regard for acceleration
|
||||
|
10
cpu_map.h
10
cpu_map.h
@ -206,11 +206,11 @@
|
||||
// a later date if flash and memory space allows.
|
||||
#define COOLANT_FLOOD_DDR DDRC
|
||||
#define COOLANT_FLOOD_PORT PORTC
|
||||
#define COOLANT_FLOOD_BIT 4 // Uno Analog Pin 3
|
||||
#define COOLANT_FLOOD_BIT 1 // Uno Analog Pin 1
|
||||
#ifdef ENABLE_M7 // Mist coolant disabled by default. See config.h to enable/disable.
|
||||
#define COOLANT_MIST_DDR DDRC
|
||||
#define COOLANT_MIST_PORT PORTC
|
||||
#define COOLANT_MIST_BIT 5 // Uno Analog Pin 4
|
||||
#define COOLANT_MIST_BIT 2 // Uno Analog Pin 2
|
||||
#endif
|
||||
|
||||
// Define user-control pinouts (cycle start, reset, feed hold) input pins.
|
||||
@ -218,9 +218,9 @@
|
||||
#define PINOUT_DDR DDRC
|
||||
#define PINOUT_PIN PINC
|
||||
#define PINOUT_PORT PORTC
|
||||
#define PIN_RESET 1 // Uno Analog Pin 1
|
||||
#define PIN_FEED_HOLD 2 // Uno Analog Pin 2
|
||||
#define PIN_CYCLE_START 3 // Uno Analog Pin 3
|
||||
#define PIN_RESET 3 // Uno Analog Pin 3
|
||||
#define PIN_FEED_HOLD 4 // Uno Analog Pin 4
|
||||
#define PIN_CYCLE_START 5 // Uno Analog Pin 5
|
||||
#define PINOUT_INT PCIE1 // Pin change interrupt enable pin
|
||||
#define PINOUT_INT_vect PCINT1_vect
|
||||
#define PINOUT_PCMSK PCMSK1 // Pin change interrupt register
|
||||
|
81
gcode.c
81
gcode.c
@ -123,8 +123,7 @@ uint8_t gc_execute_line(char *line)
|
||||
char letter;
|
||||
float value;
|
||||
uint8_t int_value = 0;
|
||||
uint16_t mantissa = 0; // NOTE: For mantissa values > 255, variable type must be changed to uint16_t.
|
||||
uint8_t probe_mode = 0;
|
||||
uint16_t mantissa = 0;
|
||||
|
||||
while (line[char_counter] != 0) { // Loop until no more g-code words in line.
|
||||
|
||||
@ -210,22 +209,10 @@ uint8_t gc_execute_line(char *line)
|
||||
case 3: gc_block.modal.motion = MOTION_MODE_CCW_ARC; break; // G3
|
||||
case 38:
|
||||
switch(mantissa) {
|
||||
case 20: // G38.2
|
||||
gc_block.modal.motion = MOTION_MODE_PROBE;
|
||||
break;
|
||||
case 30: // G38.3
|
||||
gc_block.modal.motion = MOTION_MODE_PROBE;
|
||||
probe_mode = PROBE_NO_ERROR;
|
||||
break;
|
||||
case 40: // G38.4
|
||||
gc_block.modal.motion = MOTION_MODE_PROBE;
|
||||
probe_mode = PROBE_AWAY;
|
||||
break;
|
||||
case 50: // G38.5
|
||||
gc_block.modal.motion = MOTION_MODE_PROBE;
|
||||
probe_mode = PROBE_AWAY | PROBE_NO_ERROR;
|
||||
break;
|
||||
|
||||
case 20: gc_block.modal.motion = MOTION_MODE_PROBE_TOWARD; break; // G38.2
|
||||
case 30: gc_block.modal.motion = MOTION_MODE_PROBE_TOWARD_NO_ERROR; break; // G38.3
|
||||
case 40: gc_block.modal.motion = MOTION_MODE_PROBE_AWAY; break; // G38.4
|
||||
case 50: gc_block.modal.motion = MOTION_MODE_PROBE_AWAY_NO_ERROR; break; // G38.5
|
||||
default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G38.x command]
|
||||
}
|
||||
mantissa = 0; // Set to zero to indicate valid non-integer G command.
|
||||
@ -811,7 +798,8 @@ uint8_t gc_execute_line(char *line)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MOTION_MODE_PROBE:
|
||||
case MOTION_MODE_PROBE_TOWARD: case MOTION_MODE_PROBE_TOWARD_NO_ERROR:
|
||||
case MOTION_MODE_PROBE_AWAY: case MOTION_MODE_PROBE_AWAY_NO_ERROR:
|
||||
// [G38 Errors]: Target is same current. No axis words. Cutter compensation is enabled. Feed rate
|
||||
// is undefined. Probe is triggered. NOTE: Probe check moved to probe cycle. Instead of returning
|
||||
// an error, it issues an alarm to prevent further motion to the probe. It's also done there to
|
||||
@ -838,6 +826,9 @@ uint8_t gc_execute_line(char *line)
|
||||
need to update the state and execute the block according to the order-of-execution.
|
||||
*/
|
||||
|
||||
// [0. Non-specific/common error-checks and miscellaneous setup]:
|
||||
gc_state.line_number = gc_block.values.n;
|
||||
|
||||
// [1. Comments feedback ]: NOT SUPPORTED
|
||||
|
||||
// [2. Set feed rate mode ]:
|
||||
@ -923,13 +914,13 @@ uint8_t gc_execute_line(char *line)
|
||||
// and absolute and incremental modes.
|
||||
if (axis_command) {
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
mc_line(gc_block.values.xyz, -1.0, false, gc_block.values.n);
|
||||
mc_line(gc_block.values.xyz, -1.0, false, gc_state.line_number);
|
||||
#else
|
||||
mc_line(gc_block.values.xyz, -1.0, false);
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
mc_line(parameter_data, -1.0, false, gc_block.values.n);
|
||||
mc_line(parameter_data, -1.0, false, gc_state.line_number);
|
||||
#else
|
||||
mc_line(parameter_data, -1.0, false);
|
||||
#endif
|
||||
@ -959,41 +950,71 @@ uint8_t gc_execute_line(char *line)
|
||||
switch (gc_state.modal.motion) {
|
||||
case MOTION_MODE_SEEK:
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
mc_line(gc_block.values.xyz, -1.0, false, gc_block.values.n);
|
||||
mc_line(gc_block.values.xyz, -1.0, false, gc_state.line_number);
|
||||
#else
|
||||
mc_line(gc_block.values.xyz, -1.0, false);
|
||||
#endif
|
||||
break;
|
||||
case MOTION_MODE_LINEAR:
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
mc_line(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, gc_block.values.n);
|
||||
mc_line(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, gc_state.line_number);
|
||||
#else
|
||||
mc_line(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate);
|
||||
#endif
|
||||
break;
|
||||
case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC:
|
||||
case MOTION_MODE_CW_ARC:
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
mc_arc(gc_state.position, gc_block.values.xyz, gc_block.values.ijk, gc_block.values.r,
|
||||
gc_state.feed_rate, gc_state.modal.feed_rate, axis_0, axis_1, axis_linear, gc_block.values.n);
|
||||
gc_state.feed_rate, gc_state.modal.feed_rate, axis_0, axis_1, axis_linear, true, gc_state.line_number);
|
||||
#else
|
||||
mc_arc(gc_state.position, gc_block.values.xyz, gc_block.values.ijk, gc_block.values.r,
|
||||
gc_state.feed_rate, gc_state.modal.feed_rate, axis_0, axis_1, axis_linear);
|
||||
gc_state.feed_rate, gc_state.modal.feed_rate, axis_0, axis_1, axis_linear, true);
|
||||
#endif
|
||||
break;
|
||||
case MOTION_MODE_PROBE:
|
||||
case MOTION_MODE_CCW_ARC:
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
mc_arc(gc_state.position, gc_block.values.xyz, gc_block.values.ijk, gc_block.values.r,
|
||||
gc_state.feed_rate, gc_state.modal.feed_rate, axis_0, axis_1, axis_linear, false, gc_state.line_number);
|
||||
#else
|
||||
mc_arc(gc_state.position, gc_block.values.xyz, gc_block.values.ijk, gc_block.values.r,
|
||||
gc_state.feed_rate, gc_state.modal.feed_rate, axis_0, axis_1, axis_linear, false);
|
||||
#endif
|
||||
break;
|
||||
case MOTION_MODE_PROBE_TOWARD:
|
||||
// NOTE: gc_block.values.xyz is returned from mc_probe_cycle with the updated position value. So
|
||||
// upon a successful probing cycle, the machine position and the returned value should be the same.
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, probe_mode, gc_block.values.n);
|
||||
mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, false, false, gc_state.line_number);
|
||||
#else
|
||||
mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, probe_mode);
|
||||
mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, false, false);
|
||||
#endif
|
||||
break;
|
||||
case MOTION_MODE_PROBE_TOWARD_NO_ERROR:
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, false, true, gc_state.line_number);
|
||||
#else
|
||||
mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, false, true);
|
||||
#endif
|
||||
break;
|
||||
case MOTION_MODE_PROBE_AWAY:
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, true, false, gc_state.line_number);
|
||||
#else
|
||||
mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, true, false);
|
||||
#endif
|
||||
break;
|
||||
case MOTION_MODE_PROBE_AWAY_NO_ERROR:
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, true, true, gc_state.line_number);
|
||||
#else
|
||||
mc_probe_cycle(gc_block.values.xyz, gc_state.feed_rate, gc_state.modal.feed_rate, true, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
// As far as the parser is concerned, the position is now == target. In reality the
|
||||
// motion control system might still be processing the action and the real tool position
|
||||
// in any intermediate location.
|
||||
memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); // gc.position[] = target[];
|
||||
memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); // gc_state.position[] = gc_block.values.xyz[]
|
||||
}
|
||||
}
|
||||
|
||||
|
9
gcode.h
9
gcode.h
@ -71,8 +71,11 @@
|
||||
#define MOTION_MODE_LINEAR 1 // G1
|
||||
#define MOTION_MODE_CW_ARC 2 // G2
|
||||
#define MOTION_MODE_CCW_ARC 3 // G3
|
||||
#define MOTION_MODE_PROBE 4 // G38.2, G38.3, G38.4, G38.5
|
||||
#define MOTION_MODE_NONE 5 // G80
|
||||
#define MOTION_MODE_PROBE_TOWARD 4 // G38.2
|
||||
#define MOTION_MODE_PROBE_TOWARD_NO_ERROR 5 // G38.3
|
||||
#define MOTION_MODE_PROBE_AWAY 6 // G38.4
|
||||
#define MOTION_MODE_PROBE_AWAY_NO_ERROR 7 // G38.5
|
||||
#define MOTION_MODE_NONE 8 // G80
|
||||
|
||||
// Modal Group G2: Plane select
|
||||
#define PLANE_SELECT_XY 0 // G17 (Default: Must be zero)
|
||||
@ -164,7 +167,7 @@ typedef struct {
|
||||
float spindle_speed; // RPM
|
||||
float feed_rate; // Millimeters/min
|
||||
uint8_t tool; // Tracks tool number. NOT USED.
|
||||
// int32_t line_number; // Last line number sent
|
||||
int32_t line_number; // Last line number sent
|
||||
|
||||
float position[N_AXIS]; // Where the interpreter considers the tool to be at this point in the code
|
||||
|
||||
|
@ -95,7 +95,7 @@
|
||||
|
||||
|
||||
// Execute an arc in offset mode format. position == current xyz, target == target xyz,
|
||||
// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is
|
||||
// offset == offset from current xyz, axis_X defines circle plane in tool space, axis_linear is
|
||||
// the direction of helical travel, radius == circle radius, isclockwise boolean. Used
|
||||
// for vector transformation direction.
|
||||
// The arc is approximated by generating a huge number of tiny, linear segments. The chordal tolerance
|
||||
@ -103,10 +103,10 @@
|
||||
// distance from segment to the circle when the end points both lie on the circle.
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
void mc_arc(float *position, float *target, float *offset, float radius, float feed_rate,
|
||||
uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, int32_t line_number)
|
||||
uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc, int32_t line_number)
|
||||
#else
|
||||
void mc_arc(float *position, float *target, float *offset, float radius, float feed_rate,
|
||||
uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear)
|
||||
uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc)
|
||||
#endif
|
||||
{
|
||||
float center_axis0 = position[axis_0] + offset[axis_0];
|
||||
@ -118,7 +118,7 @@
|
||||
|
||||
// CCW angle between position and target from circle center. Only one atan2() trig computation required.
|
||||
float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1);
|
||||
if (gc_state.modal.motion == MOTION_MODE_CW_ARC) { // Correct atan2 output per direction
|
||||
if (is_clockwise_arc) { // Correct atan2 output per direction
|
||||
if (angular_travel >= 0) { angular_travel -= 2*M_PI; }
|
||||
} else {
|
||||
if (angular_travel <= 0) { angular_travel += 2*M_PI; }
|
||||
@ -287,9 +287,11 @@ void mc_homing_cycle()
|
||||
// Perform tool length probe cycle. Requires probe switch.
|
||||
// NOTE: Upon probe failure, the program will be stopped and placed into ALARM state.
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate, uint8_t mode, int32_t line_number)
|
||||
void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate, uint8_t is_probe_away,
|
||||
uint8_t is_no_error, int32_t line_number)
|
||||
#else
|
||||
void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate, uint8_t mode)
|
||||
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.
|
||||
@ -298,10 +300,14 @@ void mc_homing_cycle()
|
||||
// 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
|
||||
uint8_t perform_pull_off = 1;
|
||||
|
||||
// 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.
|
||||
if (probe_get_state(mode) && probe_errors_enabled(mode)) {
|
||||
// NOTE: This probe initialization error applies to all probing cycles.
|
||||
if ( probe_get_state() ) { // Check probe pin state.
|
||||
bit_true_atomic(sys.execute, EXEC_CRIT_EVENT);
|
||||
protocol_execute_runtime();
|
||||
}
|
||||
@ -314,8 +320,8 @@ void mc_homing_cycle()
|
||||
mc_line(target, feed_rate, invert_feed_rate);
|
||||
#endif
|
||||
|
||||
// Activate the probing monitor in the stepper module.
|
||||
sys.probe_state = PROBE_ACTIVE | mode;
|
||||
// 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.execute, EXEC_CYCLE_START);
|
||||
@ -324,16 +330,16 @@ void mc_homing_cycle()
|
||||
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) {
|
||||
// Probing cycle complete!
|
||||
|
||||
if (probe_errors_enabled(mode)) {
|
||||
bit_true_atomic(sys.execute, EXEC_CRIT_EVENT);
|
||||
} else {
|
||||
perform_pull_off = 0;
|
||||
probe_finalize(0);
|
||||
}
|
||||
// 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.execute, EXEC_CRIT_EVENT); }
|
||||
} 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_runtime(); // Check and execute run-time commands
|
||||
if (sys.abort) { return; } // Check for system abort
|
||||
|
||||
@ -342,24 +348,11 @@ void mc_homing_cycle()
|
||||
plan_reset(); // Reset planner buffer. Zero planner positions. Ensure probing motion is cleared.
|
||||
plan_sync_position(); // Sync planner position to current machine position.
|
||||
|
||||
if (perform_pull_off) {
|
||||
// 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_mm[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.
|
||||
// TODO: Update the g-code parser code to not require this target calculation but uses a gc_sync_position() call.
|
||||
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.position[idx]/settings.steps_per_mm[idx];
|
||||
}
|
||||
|
||||
sys.auto_start = auto_start_state; // Restore run state before returning
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#ifndef motion_control_h
|
||||
#define motion_control_h
|
||||
#include "gcode.h"
|
||||
|
||||
#define HOMING_CYCLE_LINE_NUMBER -1
|
||||
|
||||
@ -40,14 +41,14 @@ void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate);
|
||||
|
||||
// Execute an arc in offset mode format. position == current xyz, target == target xyz,
|
||||
// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is
|
||||
// the direction of helical travel, radius == circle radius, isclockwise boolean. Used
|
||||
// the direction of helical travel, radius == circle radius, is_clockwise_arc boolean. Used
|
||||
// for vector transformation direction.
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
void mc_arc(float *position, float *target, float *offset, float radius, float feed_rate,
|
||||
uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, int32_t line_number);
|
||||
uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc, int32_t line_number);
|
||||
#else
|
||||
void mc_arc(float *position, float *target, float *offset, float radius, float feed_rate,
|
||||
uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear);
|
||||
uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc);
|
||||
#endif
|
||||
|
||||
// Dwell for a specific number of seconds
|
||||
@ -58,9 +59,11 @@ void mc_homing_cycle();
|
||||
|
||||
// Perform tool length probe cycle. Requires probe switch.
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate, uint8_t motion, int32_t line_number);
|
||||
void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate, uint8_t is_probe_away,
|
||||
uint8_t is_no_error, int32_t line_number);
|
||||
#else
|
||||
void mc_probe_cycle(float *target, float feed_rate, uint8_t invert_feed_rate, uint8_t motion);
|
||||
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
|
||||
|
||||
// Performs system reset. If in motion state, kills all motion and sets system alarm.
|
||||
|
39
probe.c
39
probe.c
@ -22,7 +22,7 @@
|
||||
#include "settings.h"
|
||||
#include "probe.h"
|
||||
|
||||
// Inverts the probe pin state depending on user settings.
|
||||
// Inverts the probe pin state depending on user settings and probing cycle mode.
|
||||
uint8_t probe_invert_mask;
|
||||
|
||||
|
||||
@ -32,39 +32,38 @@ 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;
|
||||
}
|
||||
// probe_configure_invert_mask(false); // Initialize invert mask. Not required. Updated when in-use.
|
||||
}
|
||||
|
||||
|
||||
// Called by probe_init() and the mc_probe() routines. Sets up the probe pin invert mask to
|
||||
// appropriately set the pin logic according to setting for normal-high/normal-low operation
|
||||
// and the probing cycle modes for toward-workpiece/away-from-workpiece.
|
||||
void probe_configure_invert_mask(uint8_t is_probe_away)
|
||||
{
|
||||
probe_invert_mask = 0; // Initialize as zero.
|
||||
if (bit_isfalse(settings.flags,BITFLAG_INVERT_PROBE_PIN)) { probe_invert_mask ^= PROBE_MASK; }
|
||||
if (is_probe_away) { probe_invert_mask ^= PROBE_MASK; }
|
||||
}
|
||||
|
||||
|
||||
// Returns the probe pin state. Triggered = true. Called by gcode parser and probe state monitor.
|
||||
uint8_t probe_get_state(uint8_t mode) {
|
||||
mode = ((mode >> PROBE_AWAY_BIT) & 1) << PROBE_BIT;
|
||||
return mode ^ ((PROBE_PIN & PROBE_MASK) ^ probe_invert_mask);
|
||||
}
|
||||
uint8_t probe_get_state() { return((PROBE_PIN & PROBE_MASK) ^ probe_invert_mask); }
|
||||
|
||||
uint8_t probe_errors_enabled(uint8_t mode) {
|
||||
return !(mode & PROBE_NO_ERROR);
|
||||
}
|
||||
|
||||
void probe_finalize(uint8_t probe_succeeded) {
|
||||
sys.probe_state = PROBE_OFF;
|
||||
sys.probe_succeeded = probe_succeeded;
|
||||
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_OFF) {
|
||||
if (probe_get_state(sys.probe_state)) {
|
||||
probe_finalize(1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
20
probe.h
20
probe.h
@ -22,25 +22,19 @@
|
||||
#define probe_h
|
||||
|
||||
// Values that define the probing state machine.
|
||||
#define PROBE_OFF 0 // No probing. (Must be zero.)
|
||||
#define PROBE_OFF 0 // Probing disabled or not in use. (Must be zero.)
|
||||
#define PROBE_ACTIVE 1 // Actively watching the input pin.
|
||||
|
||||
// Probe direction and error modes
|
||||
#define PROBE_AWAY 2 // G38.4, G38.5
|
||||
#define PROBE_NO_ERROR 4 // G38.3, G38.5
|
||||
|
||||
#define PROBE_AWAY_BIT 1
|
||||
#define PROBE_NO_ERROR_BIT 2
|
||||
|
||||
// Probe pin initialization routine.
|
||||
void probe_init();
|
||||
|
||||
// Returns probe pin state.
|
||||
uint8_t probe_get_state(uint8_t mode);
|
||||
// Called by probe_init() and the mc_probe() routines. Sets up the probe pin invert mask to
|
||||
// appropriately set the pin logic according to setting for normal-high/normal-low operation
|
||||
// and the probing cycle modes for toward-workpiece/away-from-workpiece.
|
||||
void probe_configure_invert_mask(uint8_t is_probe_away);
|
||||
|
||||
uint8_t probe_errors_enabled(uint8_t mode);
|
||||
|
||||
void probe_finalize(uint8_t probe_succeeded);
|
||||
// Returns probe pin state. Triggered = true. Called by gcode parser and probe state monitor.
|
||||
uint8_t probe_get_state();
|
||||
|
||||
// Monitors probe pin state and records the system position when detected. Called by the
|
||||
// stepper ISR per ISR tick.
|
||||
|
16
report.c
16
report.c
@ -281,12 +281,18 @@ void report_ngc_parameters()
|
||||
// Print current gcode parser mode state
|
||||
void report_gcode_modes()
|
||||
{
|
||||
printPgmString(PSTR("["));
|
||||
|
||||
switch (gc_state.modal.motion) {
|
||||
case MOTION_MODE_SEEK : printPgmString(PSTR("[G0")); break;
|
||||
case MOTION_MODE_LINEAR : printPgmString(PSTR("[G1")); break;
|
||||
case MOTION_MODE_CW_ARC : printPgmString(PSTR("[G2")); break;
|
||||
case MOTION_MODE_CCW_ARC : printPgmString(PSTR("[G3")); break;
|
||||
case MOTION_MODE_NONE : printPgmString(PSTR("[G80")); break;
|
||||
case MOTION_MODE_SEEK : printPgmString(PSTR("G0")); break;
|
||||
case MOTION_MODE_LINEAR : printPgmString(PSTR("G1")); break;
|
||||
case MOTION_MODE_CW_ARC : printPgmString(PSTR("G2")); break;
|
||||
case MOTION_MODE_CCW_ARC : printPgmString(PSTR("G3")); break;
|
||||
case MOTION_MODE_PROBE_TOWARD : printPgmString(PSTR("G38.2")); break;
|
||||
case MOTION_MODE_PROBE_TOWARD_NO_ERROR : printPgmString(PSTR("G38.3")); break;
|
||||
case MOTION_MODE_PROBE_AWAY : printPgmString(PSTR("G38.4")); break;
|
||||
case MOTION_MODE_PROBE_AWAY_NO_ERROR : printPgmString(PSTR("G38.5")); break;
|
||||
case MOTION_MODE_NONE : printPgmString(PSTR("G80")); break;
|
||||
}
|
||||
|
||||
printPgmString(PSTR(" G"));
|
||||
|
@ -86,10 +86,16 @@ void spindle_run(uint8_t direction, float rpm)
|
||||
#define SPINDLE_RPM_RANGE (SPINDLE_MAX_RPM-SPINDLE_MIN_RPM)
|
||||
TCCRA_REGISTER = (1<<COMB_BIT) | (1<<WAVE1_REGISTER) | (1<<WAVE0_REGISTER);
|
||||
TCCRB_REGISTER = (TCCRB_REGISTER & 0b11111000) | 0x02; // set to 1/8 Prescaler
|
||||
rpm -= SPINDLE_MIN_RPM;
|
||||
if ( rpm > SPINDLE_RPM_RANGE ) { rpm = SPINDLE_RPM_RANGE; } // Prevent uint8 overflow
|
||||
if ( rpm < SPINDLE_MIN_RPM ) { rpm = 0; }
|
||||
else {
|
||||
rpm -= SPINDLE_MIN_RPM;
|
||||
if ( rpm > SPINDLE_RPM_RANGE ) { rpm = SPINDLE_RPM_RANGE; } // Prevent uint8 overflow
|
||||
}
|
||||
uint8_t current_pwm = floor( rpm*(255.0/SPINDLE_RPM_RANGE) + 0.5);
|
||||
OCR_REGISTER = current_pwm;
|
||||
#ifdef MINIMUM_SPINDLE_PWM
|
||||
if (current_pwm < MINIMUM_SPINDLE_PWM) { current_pwm = MINIMUM_SPINDLE_PWM; }
|
||||
#endif
|
||||
OCR_REGISTER = current_pwm; // Set PWM pin output
|
||||
|
||||
#ifndef CPU_MAP_ATMEGA328P // On the Uno, spindle enable and PWM are shared.
|
||||
SPINDLE_ENABLE_PORT |= (1<<SPINDLE_ENABLE_BIT);
|
||||
|
6
system.h
6
system.h
@ -73,13 +73,15 @@ typedef struct {
|
||||
uint8_t abort; // System abort flag. Forces exit back to main loop for reset.
|
||||
uint8_t state; // Tracks the current state of Grbl.
|
||||
volatile uint8_t execute; // Global system runtime executor bitflag variable. See EXEC bitmasks.
|
||||
uint8_t homing_axis_lock;
|
||||
|
||||
int32_t position[N_AXIS]; // Real-time machine (aka home) position vector in steps.
|
||||
// NOTE: This may need to be a volatile variable, if problems arise.
|
||||
uint8_t auto_start; // Planner auto-start flag. Toggled off during feed hold. Defaulted by settings.
|
||||
|
||||
uint8_t homing_axis_lock; // Locks axes when limits engage. Used as an axis motion mask in the stepper ISR.
|
||||
volatile uint8_t probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR.
|
||||
int32_t probe_position[N_AXIS]; // Last probe position in machine coordinates and steps.
|
||||
uint8_t probe_succeeded;
|
||||
uint8_t probe_succeeded; // Tracks if last probing cycle was successful.
|
||||
} system_t;
|
||||
extern system_t sys;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user