Commit a1f1371f authored by Guillaume Picquet's avatar Guillaume Picquet

Update to grbl 1.1h

parent efb67fe1
......@@ -8,3 +8,4 @@
"7","Homing fail","Homing fail. Safety door was opened during homing cycle."
"8","Homing fail","Homing fail. Pull off travel failed to clear limit switch. Try increasing pull-off setting or check wiring."
"9","Homing fail","Homing fail. Could not find limit switch within search distances. Try increasing max travel, decreasing pull-off distance, or check wiring."
"10","Homing fail","Homing fail. Second dual axis limit switch failed to trigger within configured search distance after first. Try increasing trigger fail distance or check wiring."
......@@ -19,4 +19,5 @@ $,Restore EEPROM `$` settings command,Disabled
I,Build info write user string command,Disabled
E,Force sync upon EEPROM write,Disabled
W,Force sync upon work coordinate offset change,Disabled
L,Homing initialization auto-lock,Disabled
\ No newline at end of file
L,Homing initialization auto-lock,Disabled
2,Dual axis motors,Enabled
\ No newline at end of file
----------------
Date: 2018-11-12
Author: Sonny Jeon
Subject: Update grbl.h
----------------
Date: 2018-11-12
Author: Sonny Jeon
Subject: Update system.c
Correct control pin state checking within pin change interrupt. Improper if-else statements could lead to missed signal.
----------------
Date: 2018-11-12
Author: Sonny Jeon
Subject: Update gcode.c
If statement bug fix related to jog motion modal group error checking.
----------------
Date: 2018-06-14
Author: Sonny Jeon
Subject: Spindle/coolant rare bug fixes. Free more flash.
[new] Altered the way default settings are stored and restored. Saved about 300 bytes(!) of flashed size. Should free up enough for certain configurations of CoreXY machines.
[fix] When the optional M7 mist coolant IO was enabled, coolant overrides was not disabling correctly.
[fix] Coolant override states was not restored correctly after a parking motion in certain situations. It would restore programmed state, rather than current overridden state.
[fix] Now allow coolant overrides to operate during jogging motion.
[fix] Invert control pin mask typo.
[new] Added a new build info feedback mechanism for enabling the safety door input pin.
----------------
Date: 2018-06-09
Author: Jon
......@@ -564,17 +601,17 @@ Date: 2016-10-22
Author: Will Winder
Subject: Minor VARIABLE_SPINDLE feature toggle refactoring (#16)
* Modify code CSV format.
- Wrap value in quotes to avoid issue with embedded commas. This occurs
in one of the alarm codes.
- Change header row format to allow same parsing code as data rows.
* VARIABLE_SPINDLE feature flag experiment.
- Use a macro for 'spindle_set_speed' and 'spindle_sync' to reduce the
number of required VARIABLE_SPINDLE checks.
* Modify code CSV format.
- Wrap value in quotes to avoid issue with embedded commas. This occurs
in one of the alarm codes.
- Change header row format to allow same parsing code as data rows.
* VARIABLE_SPINDLE feature flag experiment.
- Use a macro for 'spindle_set_speed' and 'spindle_sync' to reduce the
number of required VARIABLE_SPINDLE checks.
----------------
......@@ -678,9 +715,9 @@ Date: 2016-10-17
Author: Will Winder
Subject: Modify code CSV format. (#10)
- Wrap value in quotes to avoid issue with embedded commas. This occurs
in one of the alarm codes.
- Wrap value in quotes to avoid issue with embedded commas. This occurs
in one of the alarm codes.
- Change header row format to allow same parsing code as data rows.
----------------
......
......@@ -201,7 +201,7 @@
// will be applied to all of them. This is useful when a user has a mixed set of limit pins with both
// normally-open(NO) and normally-closed(NC) switches installed on their machine.
// NOTE: PLEASE DO NOT USE THIS, unless you have a situation that needs it.
// #define INVERT_LIMIT_PIN_MASK ((1<<X_LIMIT_BIT)|(1<<Y_LIMIT_BIT)) // Default disabled. Uncomment to enable.
#define INVERT_LIMIT_PIN_MASK ((1<<X_LIMIT_BIT)|(1<<Y_LIMIT_BIT)|(1<<Z_LIMIT_BIT)) // Default disabled. Uncomment to enable.
// Inverts the spindle enable pin from low-disabled/high-enabled to low-enabled/high-disabled. Useful
// for some pre-built electronic boards.
......@@ -586,9 +586,11 @@
// to ensure the laser doesn't inadvertently remain powered while at a stop and cause a fire.
#define DISABLE_LASER_DURING_HOLD // Default enabled. Comment to disable.
// Enables a piecewise linear model of the spindle PWM/speed output. Requires a solution by the
// 'fit_nonlinear_spindle.py' script in the /doc/script folder of the repo. See file comments
// on how to gather spindle data and run the script to generate a solution.
// This feature alters the spindle PWM/speed to a nonlinear output with a simple piecewise linear
// curve. Useful for spindles that don't produce the right RPM from Grbl's standard spindle PWM
// linear model. Requires a solution by the 'fit_nonlinear_spindle.py' script in the /doc/script
// folder of the repo. See file comments on how to gather spindle data and run the script to
// generate a solution.
// #define ENABLE_PIECEWISE_LINEAR_SPINDLE // Default disabled. Uncomment to enable.
// N_PIECES, RPM_MAX, RPM_MIN, RPM_POINTxx, and RPM_LINE_XX constants are all set and given by
......@@ -610,6 +612,68 @@
#define RPM_LINE_A4 1.203413e-01 // Used N_PIECES = 4. A and B constants of line 4.
#define RPM_LINE_B4 1.151360e+03
/* ---------------------------------------------------------------------------------------
This optional dual axis feature is primarily for the homing cycle to locate two sides of
a dual-motor gantry independently, i.e. self-squaring. This requires an additional limit
switch for the cloned motor. To self square, both limit switches on the cloned axis must
be physically positioned to trigger when the gantry is square. Highly recommend keeping
the motors always enabled to ensure the gantry stays square with the $1=255 setting.
For Grbl on the Arduino Uno, the cloned axis limit switch must to be shared with and
wired with z-axis limit pin due to the lack of available pins. The homing cycle must home
the z-axis and cloned axis in different cycles, which is already the default config.
The dual axis feature works by cloning an axis step output onto another pair of step
and direction pins. The step pulse and direction of the cloned motor can be set
independently of the main axis motor. However to save precious flash and memory, this
dual axis feature must share the same settings (step/mm, max speed, acceleration) as the
parent motor. This is NOT a feature for an independent fourth axis. Only a motor clone.
WARNING: Make sure to test the directions of your dual axis motors! They must be setup
to move the same direction BEFORE running your first homing cycle or any long motion!
Motors moving in opposite directions can cause serious damage to your machine! Use this
dual axis feature at your own risk.
*/
// NOTE: This feature requires approximately 400 bytes of flash. Certain configurations can
// run out of flash to fit on an Arduino 328p/Uno. Only X and Y axes are supported. Variable
// spindle/laser mode IS supported, but only for one config option. Core XY, spindle direction
// pin, and M7 mist coolant are disabled/not supported.
// #define ENABLE_DUAL_AXIS // Default disabled. Uncomment to enable.
// Select the one axis to mirror another motor. Only X and Y axis is supported at this time.
#define DUAL_AXIS_SELECT X_AXIS // Must be either X_AXIS or Y_AXIS
// To prevent the homing cycle from racking the dual axis, when one limit triggers before the
// other due to switch failure or noise, the homing cycle will automatically abort if the second
// motor's limit switch does not trigger within the three distance parameters defined below.
// Axis length percent will automatically compute a fail distance as a percentage of the max
// travel of the other non-dual axis, i.e. if dual axis select is X_AXIS at 5.0%, then the fail
// distance will be computed as 5.0% of y-axis max travel. Fail distance max and min are the
// limits of how far or little a valid fail distance is.
#define DUAL_AXIS_HOMING_FAIL_AXIS_LENGTH_PERCENT 5.0 // Float (percent)
#define DUAL_AXIS_HOMING_FAIL_DISTANCE_MAX 25.0 // Float (mm)
#define DUAL_AXIS_HOMING_FAIL_DISTANCE_MIN 2.5 // Float (mm)
// Dual axis pin configuration currently supports two shields. Uncomment the shield you want,
// and comment out the other one(s).
// NOTE: Protoneer CNC Shield v3.51 has A.STP and A.DIR wired to pins A4 and A3 respectively.
// The variable spindle (i.e. laser mode) build option works and may be enabled or disabled.
// Coolant pin A3 is moved to D13, replacing spindle direction.
#define DUAL_AXIS_CONFIG_PROTONEER_V3_51 // Uncomment to select. Comment other configs.
// NOTE: Arduino CNC Shield Clone (Originally Protoneer v3.0) has A.STP and A.DIR wired to
// D12 and D13, respectively. With the limit pins and stepper enable pin on this same port,
// the spindle enable pin had to be moved and spindle direction pin deleted. The spindle
// enable pin now resides on A3, replacing coolant enable. Coolant enable is bumped over to
// pin A4. Spindle enable is used far more and this pin setup helps facilitate users to
// integrate this feature without arguably too much work.
// Variable spindle (i.e. laser mode) does NOT work with this shield as configured. While
// variable spindle technically can work with this shield, it requires too many changes for
// most user setups to accomodate. It would best be implemented by sharing all limit switches
// on pins D9/D10 (as [X1,Z]/[X2,Y] or [X,Y2]/[Y1,Z]), home each axis independently, and
// updating lots of code to ensure everything is running correctly.
// #define DUAL_AXIS_CONFIG_CNC_SHIELD_CLONE // Uncomment to select. Comment other configs.
/* ---------------------------------------------------------------------------------------
OEM Single File Configuration Option
......
This diff is collapsed.
......@@ -369,6 +369,84 @@
#define DEFAULT_HOMING_PULLOFF 1.0 // mm
#endif
#ifdef DEFAULTS_BOBSCNC_E3
// Grbl settings for Bob's CNC E3 Machine
// https://www.bobscnc.com/products/e3-cnc-engraving-kit
#define DEFAULT_X_STEPS_PER_MM 80.0
#define DEFAULT_Y_STEPS_PER_MM 80.0
#define DEFAULT_Z_STEPS_PER_MM 2267.717
#define DEFAULT_X_MAX_RATE 10000.0 // mm/min
#define DEFAULT_Y_MAX_RATE 10000.0 // mm/min
#define DEFAULT_Z_MAX_RATE 500.0 // mm/min
#define DEFAULT_X_ACCELERATION (500.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Y_ACCELERATION (500.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Z_ACCELERATION (300.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_X_MAX_TRAVEL 450.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Y_MAX_TRAVEL 390.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Z_MAX_TRAVEL 85.0 // mm NOTE: Must be a positive value.
#define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm
#define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm
#define DEFAULT_STEP_PULSE_MICROSECONDS 5
#define DEFAULT_STEPPING_INVERT_MASK 0
#define DEFAULT_DIRECTION_INVERT_MASK 0
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
#define DEFAULT_STATUS_REPORT_MASK 1 // MPos enabled
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
#define DEFAULT_REPORT_INCHES 1 // true
#define DEFAULT_INVERT_ST_ENABLE 0 // false
#define DEFAULT_INVERT_LIMIT_PINS 1 // true
#define DEFAULT_SOFT_LIMIT_ENABLE 1 // true
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_INVERT_PROBE_PIN 0 // false
#define DEFAULT_LASER_MODE 0 // false
#define DEFAULT_HOMING_ENABLE 1 // true
#define DEFAULT_HOMING_DIR_MASK 3 // move xy -dir, z dir
#define DEFAULT_HOMING_FEED_RATE 500.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 4000.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 5.0 // mm
#endif
#ifdef DEFAULTS_BOBSCNC_E4
// Grbl settings for Bob's CNC E4 Machine
// https://www.bobscnc.com/products/e4-cnc-router
#define DEFAULT_X_STEPS_PER_MM 80.0
#define DEFAULT_Y_STEPS_PER_MM 80.0
#define DEFAULT_Z_STEPS_PER_MM 2267.717
#define DEFAULT_X_MAX_RATE 10000.0 // mm/min
#define DEFAULT_Y_MAX_RATE 10000.0 // mm/min
#define DEFAULT_Z_MAX_RATE 500.0 // mm/min
#define DEFAULT_X_ACCELERATION (500.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Y_ACCELERATION (500.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Z_ACCELERATION (300.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2
#define DEFAULT_X_MAX_TRAVEL 610.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Y_MAX_TRAVEL 610.0 // mm NOTE: Must be a positive value.
#define DEFAULT_Z_MAX_TRAVEL 85.0 // mm NOTE: Must be a positive value.
#define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm
#define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm
#define DEFAULT_STEP_PULSE_MICROSECONDS 5
#define DEFAULT_STEPPING_INVERT_MASK 0
#define DEFAULT_DIRECTION_INVERT_MASK 0
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
#define DEFAULT_STATUS_REPORT_MASK 1 // MPos enabled
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
#define DEFAULT_REPORT_INCHES 1 // true
#define DEFAULT_INVERT_ST_ENABLE 0 // false
#define DEFAULT_INVERT_LIMIT_PINS 1 // true
#define DEFAULT_SOFT_LIMIT_ENABLE 1 // true
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_INVERT_PROBE_PIN 0 // false
#define DEFAULT_LASER_MODE 0 // false
#define DEFAULT_HOMING_ENABLE 1 // true
#define DEFAULT_HOMING_DIR_MASK 3 // move xy -dir, z dir
#define DEFAULT_HOMING_FEED_RATE 500.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 4000.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 5.0 // mm
#endif
#ifdef DEFAULTS_ZEN_TOOLWORKS_7x7
// Description: Zen Toolworks 7x7 mill with three Shinano SST43D2121 65oz-in NEMA 17 stepper motors.
// Leadscrew is different from some ZTW kits, where most are 1.25mm/rev rather than 8.0mm/rev here.
......@@ -439,11 +517,11 @@
#define DEFAULT_REPORT_INCHES 0 // false
#define DEFAULT_INVERT_ST_ENABLE 0 // false
#define DEFAULT_INVERT_LIMIT_PINS 0 // false
#define DEFAULT_SOFT_LIMIT_ENABLE 0 // false
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_SOFT_LIMIT_ENABLE 1 // true
#define DEFAULT_HARD_LIMIT_ENABLE 1 // true
#define DEFAULT_INVERT_PROBE_PIN 0 // false
#define DEFAULT_LASER_MODE 0 // false
#define DEFAULT_HOMING_ENABLE 0 // false
#define DEFAULT_HOMING_ENABLE 1 // true
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir
#define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 500.0 // mm/min
......
......@@ -22,8 +22,8 @@
#define grbl_h
// Grbl versioning system
#define GRBL_VERSION "1.1g"
#define GRBL_VERSION_BUILD "20181112"
#define GRBL_VERSION "1.1h"
#define GRBL_VERSION_BUILD "20190825"
// Define standard libraries used by Grbl.
#include <avr/io.h>
......@@ -111,6 +111,30 @@
#error "Override refresh must be greater than zero."
#endif
#if defined(ENABLE_DUAL_AXIS)
#if !((DUAL_AXIS_SELECT == X_AXIS) || (DUAL_AXIS_SELECT == Y_AXIS))
#error "Dual axis currently supports X or Y axes only."
#endif
#if defined(DUAL_AXIS_CONFIG_CNC_SHIELD_CLONE) && defined(VARIABLE_SPINDLE)
#error "VARIABLE_SPINDLE not supported with DUAL_AXIS_CNC_SHIELD_CLONE."
#endif
#if defined(DUAL_AXIS_CONFIG_CNC_SHIELD_CLONE) && defined(DUAL_AXIS_CONFIG_PROTONEER_V3_51)
#error "More than one dual axis configuration found. Select one."
#endif
#if !defined(DUAL_AXIS_CONFIG_CNC_SHIELD_CLONE) && !defined(DUAL_AXIS_CONFIG_PROTONEER_V3_51)
#error "No supported dual axis configuration found. Select one."
#endif
#if defined(COREXY)
#error "CORE XY not supported with dual axis feature."
#endif
#if defined(USE_SPINDLE_DIR_AS_ENABLE_PIN)
#error "USE_SPINDLE_DIR_AS_ENABLE_PIN not supported with dual axis feature."
#endif
#if defined(ENABLE_M7)
#error "ENABLE_M7 not supported with dual axis feature."
#endif
#endif
// ---------------------------------------------------------------------------------------
#endif
......@@ -30,6 +30,14 @@
#define HOMING_AXIS_LOCATE_SCALAR 5.0 // Must be > 1 to ensure limit switch is cleared.
#endif
#ifdef ENABLE_DUAL_AXIS
// Flags for dual axis async limit trigger check.
#define DUAL_AXIS_CHECK_DISABLE 0 // Must be zero
#define DUAL_AXIS_CHECK_ENABLE bit(0)
#define DUAL_AXIS_CHECK_TRIGGER_1 bit(1)
#define DUAL_AXIS_CHECK_TRIGGER_2 bit(2)
#endif
void limits_init()
{
LIMIT_DDR &= ~(LIMIT_MASK); // Set as input pins
......@@ -79,6 +87,9 @@ uint8_t limits_get_state()
for (idx=0; idx<N_AXIS; idx++) {
if (pin & get_limit_pin_mask(idx)) { limit_state |= (1 << idx); }
}
#ifdef ENABLE_DUAL_AXIS
if (pin & (1<<DUAL_LIMIT_BIT)) { limit_state |= (1 << N_AXIS); }
#endif
}
return(limit_state);
}
......@@ -159,6 +170,20 @@ void limits_go_home(uint8_t cycle_mask)
// Initialize variables used for homing computations.
uint8_t n_cycle = (2*N_HOMING_LOCATE_CYCLE+1);
uint8_t step_pin[N_AXIS];
#ifdef ENABLE_DUAL_AXIS
uint8_t step_pin_dual;
uint8_t dual_axis_async_check;
int32_t dual_trigger_position;
#if (DUAL_AXIS_SELECT == X_AXIS)
float fail_distance = (-DUAL_AXIS_HOMING_FAIL_AXIS_LENGTH_PERCENT/100.0)*settings.max_travel[Y_AXIS];
#else
float fail_distance = (-DUAL_AXIS_HOMING_FAIL_AXIS_LENGTH_PERCENT/100.0)*settings.max_travel[X_AXIS];
#endif
fail_distance = min(fail_distance, DUAL_AXIS_HOMING_FAIL_DISTANCE_MAX);
fail_distance = max(fail_distance, DUAL_AXIS_HOMING_FAIL_DISTANCE_MIN);
int32_t dual_fail_distance = trunc(fail_distance*settings.steps_per_mm[DUAL_AXIS_SELECT]);
// int32_t dual_fail_distance = trunc((DUAL_AXIS_HOMING_TRIGGER_FAIL_DISTANCE)*settings.steps_per_mm[DUAL_AXIS_SELECT]);
#endif
float target[N_AXIS];
float max_travel = 0.0;
uint8_t idx;
......@@ -175,6 +200,9 @@ void limits_go_home(uint8_t cycle_mask)
max_travel = max(max_travel,(-HOMING_AXIS_SEARCH_SCALAR)*settings.max_travel[idx]);
}
}
#ifdef ENABLE_DUAL_AXIS
step_pin_dual = (1<<DUAL_STEP_BIT);
#endif
// Set search mode with approach at seek rate to quickly engage the specified cycle_mask limit switches.
bool approach = true;
......@@ -187,6 +215,11 @@ void limits_go_home(uint8_t cycle_mask)
// Initialize and declare variables needed for homing routine.
axislock = 0;
#ifdef ENABLE_DUAL_AXIS
sys.homing_axis_lock_dual = 0;
dual_trigger_position = 0;
dual_axis_async_check = DUAL_AXIS_CHECK_DISABLE;
#endif
n_active_axis = 0;
for (idx=0; idx<N_AXIS; idx++) {
// Set target location for active axes and setup computation for homing rate.
......@@ -217,6 +250,9 @@ void limits_go_home(uint8_t cycle_mask)
}
// Apply axislock to the step port pins active in this cycle.
axislock |= step_pin[idx];
#ifdef ENABLE_DUAL_AXIS
if (idx == DUAL_AXIS_SELECT) { sys.homing_axis_lock_dual = step_pin_dual; }
#endif
}
}
......@@ -242,11 +278,41 @@ void limits_go_home(uint8_t cycle_mask)
else { axislock &= ~(step_pin[A_MOTOR]|step_pin[B_MOTOR]); }
#else
axislock &= ~(step_pin[idx]);
#ifdef ENABLE_DUAL_AXIS
if (idx == DUAL_AXIS_SELECT) { dual_axis_async_check |= DUAL_AXIS_CHECK_TRIGGER_1; }
#endif
#endif
}
}
}
sys.homing_axis_lock = axislock;
#ifdef ENABLE_DUAL_AXIS
if (sys.homing_axis_lock_dual) { // NOTE: Only true when homing dual axis.
if (limit_state & (1 << N_AXIS)) {
sys.homing_axis_lock_dual = 0;
dual_axis_async_check |= DUAL_AXIS_CHECK_TRIGGER_2;
}
}
// When first dual axis limit triggers, record position and begin checking distance until other limit triggers. Bail upon failure.
if (dual_axis_async_check) {
if (dual_axis_async_check & DUAL_AXIS_CHECK_ENABLE) {
if (( dual_axis_async_check & (DUAL_AXIS_CHECK_TRIGGER_1 | DUAL_AXIS_CHECK_TRIGGER_2)) == (DUAL_AXIS_CHECK_TRIGGER_1 | DUAL_AXIS_CHECK_TRIGGER_2)) {
dual_axis_async_check = DUAL_AXIS_CHECK_DISABLE;
} else {
if (abs(dual_trigger_position - sys_position[DUAL_AXIS_SELECT]) > dual_fail_distance) {
system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_DUAL_APPROACH);
mc_reset();
protocol_execute_realtime();
return;
}
}
} else {
dual_axis_async_check |= DUAL_AXIS_CHECK_ENABLE;
dual_trigger_position = sys_position[DUAL_AXIS_SELECT];
}
}
#endif
}
st_prep_buffer(); // Check and prep segment buffer. NOTE: Should take no longer than 200us.
......@@ -273,7 +339,11 @@ void limits_go_home(uint8_t cycle_mask)
}
}
} while (STEP_MASK & axislock);
#ifdef ENABLE_DUAL_AXIS
} while ((STEP_MASK & axislock) || (sys.homing_axis_lock_dual));
#else
} while (STEP_MASK & axislock);
#endif
st_reset(); // Immediately force kill steppers and reset step segment buffer.
delay_ms(settings.homing_debounce_delay); // Delay to allow transient dynamics to dissipate.
......
......@@ -456,7 +456,7 @@ uint8_t plan_buffer_line(float *target, plan_line_data_t *pl_data)
float nominal_speed = plan_compute_profile_nominal_speed(block);
plan_compute_profile_parameters(block, nominal_speed, pl.previous_nominal_speed);
pl.previous_nominal_speed = nominal_speed;
// Update previous path unit_vector and planner position.
memcpy(pl.previous_unit_vec, unit_vec, sizeof(unit_vec)); // pl.previous_unit_vec[] = unit_vec[]
memcpy(pl.position, target_steps, sizeof(target_steps)); // pl.position[] = target_steps[]
......
......@@ -436,6 +436,9 @@ void report_build_info(char *line)
#ifndef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE // NOTE: Shown when disabled.
serial_write('W');
#endif
#ifdef ENABLE_DUAL_AXIS
serial_write('2');
#endif
// NOTE: Compiled values, like override increments/max/min values, may be added at some point later.
serial_write(',');
print_uint8_base10(BLOCK_BUFFER_SIZE-1);
......@@ -569,9 +572,21 @@ void report_realtime_status()
printPgmString(PSTR("|Pn:"));
if (prb_pin_state) { serial_write('P'); }
if (lim_pin_state) {
if (bit_istrue(lim_pin_state,bit(X_AXIS))) { serial_write('X'); }
if (bit_istrue(lim_pin_state,bit(Y_AXIS))) { serial_write('Y'); }
if (bit_istrue(lim_pin_state,bit(Z_AXIS))) { serial_write('Z'); }
#ifdef ENABLE_DUAL_AXIS
#if (DUAL_AXIS_SELECT == X_AXIS)
if (bit_istrue(lim_pin_state,(bit(X_AXIS)|bit(N_AXIS)))) { serial_write('X'); }
if (bit_istrue(lim_pin_state,bit(Y_AXIS))) { serial_write('Y'); }
#endif
#if (DUAL_AXIS_SELECT == Y_AXIS)
if (bit_istrue(lim_pin_state,bit(X_AXIS))) { serial_write('X');
if (bit_istrue(lim_pin_state,(bit(Y_AXIS)|bit(N_AXIS)))) { serial_write('Y'); }
#endif
if (bit_istrue(lim_pin_state,bit(Z_AXIS))) { serial_write('Z'); }
#else
if (bit_istrue(lim_pin_state,bit(X_AXIS))) { serial_write('X'); }
if (bit_istrue(lim_pin_state,bit(Y_AXIS))) { serial_write('Y'); }
if (bit_istrue(lim_pin_state,bit(Z_AXIS))) { serial_write('Z'); }
#endif
}
if (ctrl_pin_state) {
#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
......
......@@ -30,7 +30,6 @@
void spindle_init()
{
#ifdef VARIABLE_SPINDLE
// Configure variable spindle PWM and enable pin, if requried. On the Uno, PWM and enable are
// combined unless configured otherwise.
SPINDLE_PWM_DDR |= (1<<SPINDLE_PWM_BIT); // Configure as PWM output pin.
......@@ -39,17 +38,16 @@ void spindle_init()
#ifdef USE_SPINDLE_DIR_AS_ENABLE_PIN
SPINDLE_ENABLE_DDR |= (1<<SPINDLE_ENABLE_BIT); // Configure as output pin.
#else
SPINDLE_DIRECTION_DDR |= (1<<SPINDLE_DIRECTION_BIT); // Configure as output pin.
#ifndef ENABLE_DUAL_AXIS
SPINDLE_DIRECTION_DDR |= (1<<SPINDLE_DIRECTION_BIT); // Configure as output pin.
#endif
#endif
pwm_gradient = SPINDLE_PWM_RANGE/(settings.rpm_max-settings.rpm_min);
#else
// Configure no variable spindle and only enable pin.
SPINDLE_ENABLE_DDR |= (1<<SPINDLE_ENABLE_BIT); // Configure as output pin.
SPINDLE_DIRECTION_DDR |= (1<<SPINDLE_DIRECTION_BIT); // Configure as output pin.
#ifndef ENABLE_DUAL_AXIS
SPINDLE_DIRECTION_DDR |= (1<<SPINDLE_DIRECTION_BIT); // Configure as output pin.
#endif
#endif
spindle_stop();
......@@ -58,31 +56,39 @@ void spindle_init()
uint8_t spindle_get_state()
{
#ifdef VARIABLE_SPINDLE
#ifdef VARIABLE_SPINDLE
#ifdef USE_SPINDLE_DIR_AS_ENABLE_PIN
// No spindle direction output pin.
#ifdef INVERT_SPINDLE_ENABLE_PIN
if (bit_isfalse(SPINDLE_ENABLE_PORT,(1<<SPINDLE_ENABLE_BIT))) { return(SPINDLE_STATE_CW); }
#else
if (bit_istrue(SPINDLE_ENABLE_PORT,(1<<SPINDLE_ENABLE_BIT))) { return(SPINDLE_STATE_CW); }
#endif
// No spindle direction output pin.
#ifdef INVERT_SPINDLE_ENABLE_PIN
if (bit_isfalse(SPINDLE_ENABLE_PORT,(1<<SPINDLE_ENABLE_BIT))) { return(SPINDLE_STATE_CW); }
#else
if (bit_istrue(SPINDLE_ENABLE_PORT,(1<<SPINDLE_ENABLE_BIT))) { return(SPINDLE_STATE_CW); }
#endif
#else
if (SPINDLE_TCCRA_REGISTER & (1<<SPINDLE_COMB_BIT)) { // Check if PWM is enabled.
if (SPINDLE_DIRECTION_PORT & (1<<SPINDLE_DIRECTION_BIT)) { return(SPINDLE_STATE_CCW); }
else { return(SPINDLE_STATE_CW); }
#ifdef ENABLE_DUAL_AXIS
return(SPINDLE_STATE_CW);
#else
if (SPINDLE_DIRECTION_PORT & (1<<SPINDLE_DIRECTION_BIT)) { return(SPINDLE_STATE_CCW); }
else { return(SPINDLE_STATE_CW); }
#endif
}
#endif
#else
#ifdef INVERT_SPINDLE_ENABLE_PIN
if (bit_isfalse(SPINDLE_ENABLE_PORT,(1<<SPINDLE_ENABLE_BIT))) {
#else
if (bit_istrue(SPINDLE_ENABLE_PORT,(1<<SPINDLE_ENABLE_BIT))) {
#endif
if (SPINDLE_DIRECTION_PORT & (1<<SPINDLE_DIRECTION_BIT)) { return(SPINDLE_STATE_CCW); }
else { return(SPINDLE_STATE_CW); }
#else
#ifdef INVERT_SPINDLE_ENABLE_PIN
if (bit_isfalse(SPINDLE_ENABLE_PORT,(1<<SPINDLE_ENABLE_BIT))) {
#else
if (bit_istrue(SPINDLE_ENABLE_PORT,(1<<SPINDLE_ENABLE_BIT))) {
#endif
#ifdef ENABLE_DUAL_AXIS
return(SPINDLE_STATE_CW);
#else
if (SPINDLE_DIRECTION_PORT & (1<<SPINDLE_DIRECTION_BIT)) { return(SPINDLE_STATE_CCW); }
else { return(SPINDLE_STATE_CW); }
#endif
}
#endif
return(SPINDLE_STATE_DISABLE);
#endif
return(SPINDLE_STATE_DISABLE);
}
......@@ -223,6 +229,7 @@ void spindle_stop()
#endif
{
if (sys.abort) { return; } // Block during abort.
if (state == SPINDLE_DISABLE) { // Halt or set spindle direction and rpm.
#ifdef VARIABLE_SPINDLE
......@@ -231,8 +238,8 @@ void spindle_stop()
spindle_stop();
} else {
#ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN
#if !defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && !defined(ENABLE_DUAL_AXIS)
if (state == SPINDLE_ENABLE_CW) {
SPINDLE_DIRECTION_PORT &= ~(1<<SPINDLE_DIRECTION_BIT);
} else {
......
......@@ -67,6 +67,9 @@ typedef struct {
uint32_t steps[N_AXIS];
uint32_t step_event_count;
uint8_t direction_bits;
#ifdef ENABLE_DUAL_AXIS
uint8_t direction_bits_dual;
#endif
#ifdef VARIABLE_SPINDLE
uint8_t is_pwm_rate_adjusted; // Tracks motions that require constant laser power/rate
#endif
......@@ -106,6 +109,10 @@ typedef struct {
uint8_t step_pulse_time; // Step pulse reset time after step rise
uint8_t step_outbits; // The next stepping-bits to be output
uint8_t dir_outbits;
#ifdef ENABLE_DUAL_AXIS
uint8_t step_outbits_dual;
uint8_t dir_outbits_dual;
#endif
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
uint32_t steps[N_AXIS];
#endif
......@@ -125,6 +132,10 @@ static uint8_t segment_next_head;
// Step and direction port invert masks.
static uint8_t step_port_invert_mask;
static uint8_t dir_port_invert_mask;
#ifdef ENABLE_DUAL_AXIS
static uint8_t step_port_invert_mask_dual;
static uint8_t dir_port_invert_mask_dual;
#endif
// Used to avoid ISR nesting of the "Stepper Driver Interrupt". Should never occur though.
static volatile uint8_t busy;
......@@ -311,12 +322,21 @@ ISR(TIMER1_COMPA_vect)
// Set the direction pins a couple of nanoseconds before we step the steppers
DIRECTION_PORT = (DIRECTION_PORT & ~DIRECTION_MASK) | (st.dir_outbits & DIRECTION_MASK);
#ifdef ENABLE_DUAL_AXIS
DIRECTION_PORT_DUAL = (DIRECTION_PORT_DUAL & ~DIRECTION_MASK_DUAL) | (st.dir_outbits_dual & DIRECTION_MASK_DUAL);
#endif
// Then pulse the stepping pins
#ifdef STEP_PULSE_DELAY
st.step_bits = (STEP_PORT & ~STEP_MASK) | st.step_outbits; // Store out_bits to prevent overwriting.
#ifdef ENABLE_DUAL_AXIS
st.step_bits_dual = (STEP_PORT_DUAL & ~STEP_MASK_DUAL) | st.step_outbits_dual;
#endif
#else // Normal operation
STEP_PORT = (STEP_PORT & ~STEP_MASK) | st.step_outbits;
#ifdef ENABLE_DUAL_AXIS
STEP_PORT_DUAL = (STEP_PORT_DUAL & ~STEP_MASK_DUAL) | st.step_outbits_dual;
#endif
#endif
// Enable step pulse reset timer so that The Stepper Port Reset Interrupt can reset the signal after
......@@ -353,6 +373,9 @@ ISR(TIMER1_COMPA_vect)
st.counter_x = st.counter_y = st.counter_z = (st.exec_block->step_event_count >> 1);
}
st.dir_outbits = st.exec_block->direction_bits ^ dir_port_invert_mask;
#ifdef ENABLE_DUAL_AXIS
st.dir_outbits_dual = st.exec_block->direction_bits_dual ^ dir_port_invert_mask_dual;
#endif
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
// With AMASS enabled, adjust Bresenham axis increment counters according to AMASS level.
......@@ -384,6 +407,9 @@ ISR(TIMER1_COMPA_vect)
// Reset step out bits.
st.step_outbits = 0;
#ifdef ENABLE_DUAL_AXIS
st.step_outbits_dual = 0;
#endif
// Execute step displacement profile by Bresenham line algorithm
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
......@@ -393,6 +419,9 @@ ISR(TIMER1_COMPA_vect)
#endif
if (st.counter_x > st.exec_block->step_event_count) {
st.step_outbits |= (1<<X_STEP_BIT);
#if defined(ENABLE_DUAL_AXIS) && (DUAL_AXIS_SELECT == X_AXIS)
st.step_outbits_dual = (1<<DUAL_STEP_BIT);
#endif
st.counter_x -= st.exec_block->step_event_count;
if (st.exec_block->direction_bits & (1<<X_DIRECTION_BIT)) { sys_position[X_AXIS]--; }
else { sys_position[X_AXIS]++; }