Added kinematics for asymmetric (differing step/mm) ganged or auto squared axis,

claims the highest number axis > Z for the second motor.
This commit is contained in:
Terje Io
2026-06-18 09:17:43 +02:00
parent 4fcdbaee11
commit 41abd8c84d
21 changed files with 687 additions and 1087 deletions
+1
View File
@@ -45,6 +45,7 @@ target_sources(grbl INTERFACE
${CMAKE_CURRENT_LIST_DIR}/encoders.c
${CMAKE_CURRENT_LIST_DIR}/pid.c
${CMAKE_CURRENT_LIST_DIR}/fs_device.c
${CMAKE_CURRENT_LIST_DIR}/kinematics/asymmetric_ganging.c
${CMAKE_CURRENT_LIST_DIR}/kinematics/corexy.c
${CMAKE_CURRENT_LIST_DIR}/kinematics/wall_plotter.c
${CMAKE_CURRENT_LIST_DIR}/kinematics/delta.c
+2 -2
View File
@@ -1,6 +1,6 @@
## grblHAL ##
Latest build date is 20260525, see the [changelog](changelog.md) for details.
Latest build date is 20260618, see the [changelog](changelog.md) for details.
> [!NOTE]
> A settings reset will be performed on an update of builds prior to 20241208. Backup and restore of settings is recommended.
@@ -89,4 +89,4 @@ G/M-codes not supported by [legacy Grbl](https://github.com/gnea/grbl/wiki) are
Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes.
---
20260311
20260618
+29
View File
@@ -1,5 +1,34 @@
## grblHAL changelog
<a name="20260618">Build 20260618
Core:
* Added kinematics for asymmetric \(differing step/mm\) ganged or auto squared axis, claims the highest number axis > Z for the second motor.
* Ignore single block mode while executing startup code. Ref. issue [#963](https://github.com/grblHAL/core/issues/963).
* For developers: added API call, `system_claim_axis()`, for claiming highest numbered axis > Z, hides its related settings.
* Fixed a typo causing ganged Z compilation failure.
* Fixed code guard. Ref. discussion [#968](https://github.com/grblHAL/core/discussions/968).
Plugins:
* Misc, MCP23017: added plugin for [MCP23017](https://ww1.microchip.com/downloads/en/devicedoc/20001952c.pdf) 16 channel I2C I/O expander,
compile time configurable for 8 channel input and output, 16 channel input or 16 channel output.
Drivers:
* RP2040: "hardened" neopixel code.
* IMXRT1062: fixed typo causing compilation to fail if axis is remapped as C. Fixed incorrect function decorators in the core. Ref. issue #[965](https://github.com/grblHAL/core/issues/965).
* STM32F7xx: fixed copy paste error affecting handling of AUX IRQ for pins 10 - 15.
---
<a name="20260602">Build 20260602
Core:
+12 -10
View File
@@ -120,15 +120,6 @@ generate a solution.
//#define KINEMATICS_API // Uncomment to add HAL entry points for custom kinematics
/*! \def MASLOW_ROUTER
\brief Enable Maslow router kinematics.
Experimental - testing required and homing needs to be worked out.
*/
#if !defined MASLOW_ROUTER || defined __DOXYGEN__
// Enable Maslow router kinematics.
// Experimental - testing required and homing needs to be worked out.
#define MASLOW_ROUTER Off
#endif
/*! \def WALL_PLOTTER
\brief Enable wall plotter kinematics.
@@ -159,7 +150,6 @@ Experimental - testing required and homing needs to be worked out.
#define POLAR_ROBOT Off
#endif
/*! \def COREXY
\brief Enable CoreXY kinematics. Use ONLY with CoreXY machines.
<br>__IMPORTANT:__ If homing is enabled, you must reconfigure the homing cycle \#defines above to
@@ -173,6 +163,18 @@ have the same steps per mm internally.
#define COREXY Off
#endif
/*! \def ASYMMETRIC_GANGING
\brief Enable asymmetric ganging for X, Y or Z axis.
<br> To be used when the screw pitch is not equal. The highest numbered axis is claimed for the second motor.
*/
//#define ASYMMETRIC_GANGING Y_AXIS // Uncomment to enable
/*! \def ASYMMETRIC_AUTO_SQUARE
\brief Enable asymmetric ganging + auto squaring for X, Y or Z axis.
<br> To be used when the screw pitch is not equal. The highest numbered axis is claimed for the second motor.
*/
//#define ASYMMETRIC_AUTO_SQUARE Y_AXIS // Uncomment to enable
/*! \def CHECK_MODE_DELAY
\brief
Add a short delay for each block processed in Check Mode to
+5 -1
View File
@@ -310,7 +310,11 @@
#define SPINDLE_DIR 0b100
#ifndef SPINDLE0_ENABLE
#define SPINDLE0_ENABLE DEFAULT_SPINDLE
#ifdef SPINDLE_ENABLE
#define SPINDLE0_ENABLE 0
#else
#define SPINDLE0_ENABLE DEFAULT_SPINDLE
#endif
#endif
#ifndef SPINDLE1_ENABLE
+9 -1
View File
@@ -31,7 +31,7 @@ extern void board_ports_init (void); // default is a weak function
// I2C expanders
#if PCA9654E_ENABLE || MCP3221_ENABLE || MCP4725_ENABLE || FLEXGPIO_ENABLE
#if PCA9654E_ENABLE || MCP3221_ENABLE || MCP4725_ENABLE || MCP23017_ENABLE || FLEXGPIO_ENABLE
#if defined(I2C_ENABLE) && !I2C_ENABLE
#undef I2C_ENABLE
@@ -53,6 +53,10 @@ extern void mcp4725_init (void);
extern void pca9654e_init (void);
#endif
#if MCP23017_ENABLE
extern void mcp23017_init (void);
#endif
// Third party I2C expander plugins goes after this line
#if FLEXGPIO_ENABLE
@@ -133,6 +137,10 @@ static inline void io_expanders_init (void)
mcp4725_init();
#endif
#if MCP23017_ENABLE
mcp23017_init();
#endif
#if R4SLS08_ENABLE
r4sls08_init();
#endif
+2 -2
View File
@@ -42,7 +42,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
#define GRBL_BUILD 20260602
#define GRBL_BUILD 20260618
#define GRBL_URL "https://github.com/grblHAL"
@@ -86,7 +86,7 @@
#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
#endif
#if (COREXY || WALL_PLOTTER || DELTA_ROBOT || POLAR_ROBOT || MASLOW_ROUTER) && !defined(KINEMATICS_API)
#if (COREXY || WALL_PLOTTER || DELTA_ROBOT || POLAR_ROBOT || ASYMMETRIC_GANGING || ASYMMETRIC_AUTO_SQUARE) && !defined(KINEMATICS_API)
#define KINEMATICS_API
#endif
+9 -16
View File
@@ -45,22 +45,6 @@
#include "kinematics.h"
#endif
#if COREXY
#include "kinematics/corexy.h"
#endif
#if WALL_PLOTTER
#include "kinematics/wall_plotter.h"
#endif
#if DELTA_ROBOT
#include "kinematics/delta.h"
#endif
#if POLAR_ROBOT
#include "kinematics/polar.h"
#endif
static void task_execute (sys_state_t state);
typedef union {
@@ -357,21 +341,30 @@ FLASHMEM int grbl_enter (void)
#endif
#if COREXY
extern void corexy_init (void);
corexy_init();
#endif
#if WALL_PLOTTER
extern void wall_plotter_init (void);
wall_plotter_init();
#endif
#if DELTA_ROBOT
extern void delta_robot_init (void);
delta_robot_init();
#endif
#if POLAR_ROBOT
extern void polar_init (void);
polar_init();
#endif
#if defined(ASYMMETRIC_GANGING) || defined(ASYMMETRIC_AUTO_SQUARE)
extern void asymmetric_ganging_init (void);
asymmetric_ganging_init();
#endif
#if NVSDATA_BUFFER_ENABLE
nvs_buffer_init();
#endif
+346
View File
@@ -0,0 +1,346 @@
/*
asymmetric_ganging.c - kinematics implementation for asymmetric ganging of two axis motors
Part of grblHAL
Copyright (c) 2026 Terje Io
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
grblHAL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../grbl.h"
#if defined(ASYMMETRIC_GANGING) || defined(ASYMMETRIC_AUTO_SQUARE)
#if N_AXIS <= 3
#error "Kinematics for asymmetric ganging must have N_AXIS > 3"
#endif
#include <math.h>
#include "../hal.h"
#include "../settings.h"
#include "../planner.h"
#include "../kinematics.h"
#ifdef ASYMMETRIC_AUTO_SQUARE
#define PRIMARY_AXIS ASYMMETRIC_AUTO_SQUARE
#else
#define PRIMARY_AXIS ASYMMETRIC_GANGING
#endif
#define PRIMARY_AXIS_BIT (1 << PRIMARY_AXIS)
#define GANGED_AXIS (N_AXIS - 1)
#define GANGED_AXIS_BIT (1 << GANGED_AXIS)
static on_report_options_ptr on_report_options;
static on_settings_changed_ptr on_settings_changed;
static stepper_get_ganged_ptr get_ganged_axes;
#ifdef ASYMMETRIC_AUTO_SQUARE
static axes_signals_t motor_disable = {0};
static stepper_disable_motors_ptr disable_motors;
static limits_get_state_ptr get_limits_state;
static home_get_state_ptr get_home_state;
static stepper_pulse_start_ptr pulse_start;
static void onDisableMotors (axes_signals_t axes, squaring_mode_t mode)
{
if(disable_motors)
disable_motors(axes, mode);
if(!axes.bits)
motor_disable.bits = 0;
else if(axes.bits & (1 << PRIMARY_AXIS)) {
/*
if(mode == SquaringMode_A)
sys.homing_axis_lock.bits &= ~(1 << PRIMARY_AXIS);
else
sys.homing_axis_lock.bits &= ~GANGED_AXIS_BIT;
*/
motor_disable.y = mode == SquaringMode_A;
if(mode == SquaringMode_B)
motor_disable.bits |= GANGED_AXIS_BIT;
else
motor_disable.bits &= ~GANGED_AXIS_BIT;
}
}
static limit_signals_t onGetLimitsState (void)
{
limit_signals_t limits = get_limits_state();
limits.min2.y = !!(limits.min.bits & GANGED_AXIS_BIT);
return limits;
}
/*
ISR_CODE static home_signals_t ISR_FUNC(onGetHomingState)(void)
{
home_signals_t home = get_home_state();
if(home.a.bits && GANGED_AXIS_BIT) {
home.b.y = On;
home.a.bits &= ~GANGED_AXIS_BIT;
}
return home;
}
*/
void ISR_CODE ISR_FUNC(onStepperPulse) (stepper_t *stepper)
{
if(stepper->step_out.bits & motor_disable.bits) {
if(motor_disable.bits & PRIMARY_AXIS_BIT)
stepper->step_out.bits &= ~PRIMARY_AXIS_BIT;
if(motor_disable.bits & GANGED_AXIS_BIT)
stepper->step_out.bits &= ~GANGED_AXIS_BIT;
}
pulse_start(stepper);
}
static bool homing_cycle_validate (axes_signals_t cycle)
{
return !(cycle.bits & PRIMARY_AXIS_BIT) || ((cycle.bits & PRIMARY_AXIS_BIT) && (cycle.bits & GANGED_AXIS_BIT));
}
static axes_signals_t onGetGangedAxes (bool auto_squared)
{
axes_signals_t axes = {0};
if(get_ganged_axes)
axes = get_ganged_axes(auto_squared);
axes.bits |= PRIMARY_AXIS_BIT;
return axes;
}
#else
static bool homing_cycle_validate (axes_signals_t cycle)
{
return true;
}
static axes_signals_t onGetGangedAxes (bool auto_squared)
{
axes_signals_t axes = {0};
if(get_ganged_axes)
axes = get_ganged_axes(auto_squared);
if(!auto_squared)
axes.bits |= PRIMARY_AXIS_BIT;
return axes;
}
#endif // ASYMMETRIC_AUTO_SQUARE
static float *convert_array_steps_to_mpos (float *position, int32_t *steps)
{
uint_fast8_t idx = N_AXIS;
do {
idx--;
position[idx] = steps[idx] / settings.axis[idx].steps_per_mm;
} while(idx);
return position;
}
// Transform position from cartesian coordinate system to corexy coordinate system
static inline float *transform_from_cartesian (float *target, float *position)
{
memcpy(target, position, sizeof(coord_data_t));
target[GANGED_AXIS] = position[PRIMARY_AXIS];
return target;
}
static uint_fast8_t get_axis_mask (uint_fast8_t idx)
{
return bit(idx);
}
static void set_target_pos (uint_fast8_t idx) // fn name?
{
sys.position[idx] = 0;
}
// Set machine positions for homed limit switches. Don't update non-homed axes.
// NOTE: settings.max_travel[] is stored as a negative value.
static void set_machine_positions (axes_signals_t cycle)
{
limits_set_machine_positions(cycle, true);
if(!settings.homing.flags.force_set_origin)
sys.position[GANGED_AXIS] = lroundf(sys.home_position[PRIMARY_AXIS] * settings.axis[GANGED_AXIS].steps_per_mm);
}
// called from mc_line() to segment lines if not overridden, default implementation for pass-through
static float *kinematics_segment_line (float *target, float *position, plan_line_data_t *pl_data, bool init)
{
static uint_fast8_t iterations;
static coord_data_t trsf;
if(init) {
iterations = 2;
transform_from_cartesian(trsf.values, target);
}
return iterations-- == 0 ? NULL : trsf.values;
}
static float homing_cycle_get_feedrate (axes_signals_t cycle, float feedrate, homing_mode_t mode)
{
return feedrate;
}
static void onSettingsChanged (settings_t *settings, settings_changed_flags_t changed)
{
uint_fast8_t idx = sizeof(settings->homing.cycle) / sizeof(axes_signals_t);
on_settings_changed(settings, changed);
float steps_per_mm = settings->axis[GANGED_AXIS].steps_per_mm;
memcpy(&settings->axis[GANGED_AXIS], &settings->axis[PRIMARY_AXIS], sizeof(axis_settings_t));
settings->axis[GANGED_AXIS].steps_per_mm = steps_per_mm;
do {
if(settings->homing.cycle[--idx].bits & PRIMARY_AXIS_BIT)
settings->homing.cycle[idx].bits |= GANGED_AXIS_BIT;
else if(settings->homing.cycle[idx].bits & GANGED_AXIS_BIT)
settings->homing.cycle[idx].bits &= GANGED_AXIS_BIT;
} while(idx);
if(settings->steppers.enable_invert.bits & PRIMARY_AXIS_BIT)
settings->steppers.enable_invert.bits |= GANGED_AXIS_BIT;
else
settings->steppers.enable_invert.bits &= ~GANGED_AXIS_BIT;
if(settings->steppers.dir_invert.bits & PRIMARY_AXIS_BIT)
settings->steppers.dir_invert.bits |= GANGED_AXIS_BIT;
else
settings->steppers.dir_invert.bits &= ~GANGED_AXIS_BIT;
if(settings->steppers.step_invert.bits & PRIMARY_AXIS_BIT)
settings->steppers.step_invert.bits |= GANGED_AXIS_BIT;
else
settings->steppers.step_invert.bits &= ~GANGED_AXIS_BIT;
if(settings->steppers.energize.bits & PRIMARY_AXIS_BIT)
settings->steppers.energize.bits |= GANGED_AXIS_BIT;
else
settings->steppers.energize.bits &= ~GANGED_AXIS_BIT;
if(settings->homing.dir_mask.bits & PRIMARY_AXIS_BIT)
settings->homing.dir_mask.bits |= GANGED_AXIS_BIT;
else
settings->homing.dir_mask.bits &= ~GANGED_AXIS_BIT;
settings->steppers.is_rotary.bits &= ~GANGED_AXIS_BIT;
#ifdef ASYMMETRIC_AUTO_SQUARE
if(settings->limits.invert.bits & PRIMARY_AXIS_BIT)
settings->limits.invert.bits |= GANGED_AXIS_BIT;
else
settings->limits.invert.bits &= ~GANGED_AXIS_BIT;
if(hal.stepper.pulse_start != onStepperPulse) {
pulse_start = hal.stepper.pulse_start;
hal.stepper.pulse_start = onStepperPulse;
}
#endif
}
PROGMEM static const char label[] = {
#if PRIMARY_AXIS == X_AXIS
"Ganged X-motor travel resolution"
#elif PRIMARY_AXIS == Y_AXIS
"Ganged Y-motor travel resolution"
#elif PRIMARY_AXIS == Z_AXIS
"Ganged Z-motor travel resolution"
#endif
};
PROGMEM static const setting_detail_t axis_settings[] = {
{ Setting_AxisStepsPerMM + GANGED_AXIS, Group_Axis0 + PRIMARY_AXIS, label, "step/mm", Format_Decimal, "#####0.000##", NULL, NULL, Setting_IsLegacy, &settings.axis[GANGED_AXIS].steps_per_mm, NULL, NULL },
};
static void report_options (bool newopt)
{
on_report_options(newopt);
if(!newopt)
hal.stream.write("[KINEMATICS:Asymmetric ganging v0.01]" ASCII_EOL);
}
// Initialize API pointers for xxx kinematics
void asymmetric_ganging_init (void)
{
static setting_details_t axis_setting_details = {
.is_core = true,
.settings = axis_settings,
.n_settings = sizeof(axis_settings) / sizeof(setting_detail_t),
.save = settings_write_global
};
system_claim_axis();
kinematics.limits_set_target_pos = set_target_pos;
kinematics.limits_get_axis_mask = get_axis_mask;
kinematics.limits_set_machine_positions = set_machine_positions;
kinematics.transform_from_cartesian = transform_from_cartesian;
kinematics.transform_steps_to_cartesian = convert_array_steps_to_mpos;
kinematics.segment_line = kinematics_segment_line;
kinematics.homing_cycle_validate = homing_cycle_validate;
kinematics.homing_cycle_get_feedrate = homing_cycle_get_feedrate;
settings_register(&axis_setting_details);
on_report_options = grbl.on_report_options;
grbl.on_report_options = report_options;
on_settings_changed = grbl.on_settings_changed;
grbl.on_settings_changed = onSettingsChanged;
get_ganged_axes = hal.stepper.get_ganged;
hal.stepper.get_ganged = onGetGangedAxes;
#ifdef ASYMMETRIC_AUTO_SQUARE
get_limits_state = hal.limits.get_state;
hal.limits.get_state = onGetLimitsState;
get_home_state = hal.homing.get_state;
// hal.homing.get_state = onGetHomingState;
disable_motors = hal.stepper.disable_motors;
hal.stepper.disable_motors = onDisableMotors;
#endif
}
#endif // ASYMMETRIC_GANGING || ASYMMETRIC_AUTO_SQUARE
-29
View File
@@ -1,29 +0,0 @@
/*
corexy.c - corexy kinematics implementation
Part of grblHAL
Copyright (c) 2019 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
grblHAL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _COREXY_H_
#define _COREXY_H_
// Initialize HAL pointers for CoreXY kinematics
void corexy_init (void);
#endif
-28
View File
@@ -1,28 +0,0 @@
/*
delta.c - delta kinematics implementation
Part of grblHAL
Copyright (c) 2023 Terje Io
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
grblHAL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _delta_H_
#define _delta_H_
// Initialize HAL pointers for delta kinematics
void delta_robot_init (void);
#endif
-681
View File
File diff suppressed because it is too large Load Diff
-161
View File
@@ -1,161 +0,0 @@
/*
maslow.h - Maslow router kinematics implementation
Part of grblHAL
Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Grbl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
The basis for this code has been pulled from MaslowDue created by Larry D O'Cull.
<https://github.com/ldocull/MaslowDue>
Some portions of that package directly or indirectly has been pulled from from the Maslow CNC
firmware for Aduino Mega. Those parts are Copyright 2014-2017 Bar Smith.
<https://www.maslowcnc.com/>
It has been adapted for grbl by Terje Io.
*** TO BE COMPLETED ***
*/
#include "../grbl.h"
#ifndef _MASLOW_H_
#define _MASLOW_H_
#define FP_SCALING 1024.0f
#define SPROCKET_RADIUS_MM (10.1f)
#define MAX_SEG_LENGTH_MM 2.0f /* long lines must be segmented due to circular motion */
// PID position loop factors X: Kp = 25000 Ki = 15000 Kd = 22000 Imax = 5000
// 14.000 fixed point arithmetic S13.10
#ifdef DRIVER_TLE5206
#define MASLOW_A_KP 10.0f
#define MASLOW_A_KI 21.0f
#define MASLOW_A_KD 18.0f
#define MASLOW_A_IMAX 5000
#define MASLOW_B_KP 10.0f
#define MASLOW_B_KI 21.0f
#define MASLOW_B_KD 18.0f
#define MASLOW_B_IMAX 5000
#define MASLOW_Z_KP 10.0f
#define MASLOW_Z_KI 21.0f
#define MASLOW_Z_KD 17.0f
#define MASLOW_Z_IMAX 5000
#else
#define MASLOW_A_KP 22.0f
#define MASLOW_A_KI 17.0f
#define MASLOW_A_KD 20.0f
#define MASLOW_A_IMAX 5000
#define MASLOW_B_KP 22.0f
#define MASLOW_B_KI 17.0f
#define MASLOW_B_KD 20.0f
#define MASLOW_B_IMAX 5000
#define MASLOW_Z_KP 20.0f
#define MASLOW_Z_KI 17.0f
#define MASLOW_Z_KD 18.0f
#define MASLOW_Z_IMAX 5000
#endif
#define MASLOW_MACHINEWIDTH 2400.0f
#define MASLOW_MACHINEHEIGHT 1200.0f
#define MASLOW_DISTBETWEENMOTORS 3000.0f
#define MASLOW_MOTOROFFSETY 600.0f
#define MASLOW_CHAINLENGTH 3000.0f
#define MASLOW_CHAINOVERSPROCKET 0
#define MASLOW_CHAINSAGCORRECTION 59.504839f
#define MASLOW_LEFTCHAINTOLERANCE 0.0f
#define MASLOW_RIGHTCHAINTOLERANCE 0.0f
#define MASLOW_ROTATIONDISKRADIUS 104.3f
#define MASLOW_SLEDHEIGHT 139.0f
#define MASLOW_SLEDWIDTH 310.0f
#define MASLOW_ACORRSCALING 1.003922f
#define MASLOW_BCORRSCALING 1.002611f
typedef enum {
Maslow_ChainOverSprocket = 260,
Maslow_MachineWidth,
Maslow_MachineHeight,
Maslow_DistBetweenMotors,
Maslow_MotorOffsetY,
Maslow_AcorrScaling,
Maslow_BcorrScaling,
Maslow_SettingMax,
} maslow_setting_t;
typedef enum {
AxisSetting_MaslowKP = 10,
AxisSetting_MaslowKI,
AxisSetting_MaslowKD,
AxisSetting_MaslowIMax,
AxisSetting_MaslowMaxSetting
} maslow_axis_setting_t;
typedef struct {
float Kp;
float Ki;
float Kd;
float Imax;
} maslow_pid_coefficients_t;
typedef struct {
maslow_pid_coefficients_t pid[N_AXIS];
uint32_t chainOverSprocket;
float machineWidth; /* Maslow specific settings */
float machineHeight;
float distBetweenMotors;
float motorOffsetY;
float chainSagCorrection;
float leftChainTolerance;
float rightChainTolerance;
float rotationDiskRadius;
float chainLength;
float sledHeight;
float sledWidth;
float XcorrScaling;
float YcorrScaling;
} maslow_settings_t;
typedef struct {
float Error;
float Integral;
float iterm;
float DiffTerm;
float speed;
} maslow_debug_t;
typedef struct {
maslow_settings_t settings;
void (*pid_settings_changed)(uint_fast8_t idx);
void (*move)(uint_fast8_t idx, int_fast16_t distance);
void (*reset_pid)(uint_fast8_t idx);
void (*pos_enable)(bool enable);
void (*tuning_enable)(bool enable);
int32_t (*set_step_size)(uint_fast8_t idx, int32_t step_size);
maslow_debug_t *(*get_debug_data)(uint_fast8_t idx);
} maslow_hal_t;
extern maslow_hal_t maslow_hal;
// Initialize HAL pointers for Maslow Router kinematics
bool maslow_init (void);
static status_code_t maslow_tuning (uint_fast16_t state, char *line);
#endif
-28
View File
@@ -1,28 +0,0 @@
/*
corexy.c - polar kinematics implementation
Part of grblHAL
Copyright (c) 2023 Terje Io
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
grblHAL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _POLAR_H_
#define _POLAR_H_
// Initialize HAL pointers for Polar kinematics
void polar_init (void);
#endif // _POLAR_H_
-28
View File
@@ -1,28 +0,0 @@
/*
wall_plotter.h - wall plotter kinematics implementation
Part of grblHAL
Copyright (c) 2019 Terje Io
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
grblHAL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WALL_PLOTTER_H_
#define _WALL_PLOTTER_H_
// Initialize HAL pointers for Wall Plotter kinematics
void wall_plotter_init (void);
#endif
+10 -9
View File
@@ -139,8 +139,6 @@ FLASHMEM void limits_set_work_envelope (void)
} while(idx);
}
#ifndef KINEMATICS_API
// Set machine positions for homed limit switches. Don't update non-homed axes.
// NOTE: settings.max_travel[] is stored as a negative value.
FLASHMEM void limits_set_machine_positions (axes_signals_t cycle, bool add_pulloff)
@@ -164,8 +162,6 @@ FLASHMEM void limits_set_machine_positions (axes_signals_t cycle, bool add_pullo
} while(idx);
}
#endif
// Set, get homing pulloff
FLASHMEM coord_data_t *limits_homing_pulloff (coord_data_t *distance)
{
@@ -204,11 +200,12 @@ FLASHMEM static bool limits_pull_off (axes_signals_t axis, coord_data_t *distanc
plan_data.feed_rate = settings.axis[0].homing_seek_rate * sqrtf(n_axis); // Adjust so individual axes all move at pull-off rate.
plan_data.condition.coolant = gc_state.modal.coolant;
// Bypass mc_line(). Directly plan homing motion.
#ifdef KINEMATICS_API
coord_data_t k_target;
plan_buffer_line(kinematics.transform_from_cartesian(k_target.values, target.values), &plan_data); // Bypass mc_line(). Directly plan homing motion.;
plan_buffer_line(kinematics.transform_from_cartesian(k_target.values, target.values), &plan_data);
#else
plan_buffer_line(target.values, &plan_data); // Bypass mc_line(). Directly plan homing motion.
plan_buffer_line(target.values, &plan_data);
#endif
sys.step_control.flags = 0; // Clear existing flags and
@@ -419,7 +416,7 @@ FLASHMEM static bool homing_cycle (axes_signals_t cycle, axes_signals_t auto_squ
idx = N_AXIS;
do {
idx--;
if ((axislock.mask & step_pin[idx]) && (homing_state.mask & bit(idx))) {
if((axislock.mask & step_pin[idx]) && (homing_state.mask & bit(idx))) {
#ifdef KINEMATICS_API
axislock.mask &= ~kinematics.limits_get_axis_mask(idx);
#else
@@ -432,7 +429,7 @@ FLASHMEM static bool homing_cycle (axes_signals_t cycle, axes_signals_t auto_squ
sys.homing_axis_lock.mask = axislock.mask;
if (autosquare_check && abs(initial_trigger_position - sys.position[dual_motor_axis]) > autosquare_fail_distance) {
if(autosquare_check && abs(initial_trigger_position - sys.position[dual_motor_axis]) > autosquare_fail_distance) {
system_set_exec_alarm(Alarm_HomingFailAutoSquaringApproach);
mc_reset();
protocol_execute_realtime();
@@ -523,9 +520,11 @@ FLASHMEM static bool homing_cycle (axes_signals_t cycle, axes_signals_t auto_squ
if(auto_square.mask && settings.axis[dual_motor_axis].dual_axis_offset != 0.0f) {
hal.stepper.disable_motors(auto_square, settings.axis[dual_motor_axis].dual_axis_offset < 0.0f ? SquaringMode_B : SquaringMode_A);
distance.values[dual_motor_axis] = fabs(settings.axis[dual_motor_axis].dual_axis_offset);
#if defined(ASYMMETRIC_GANGING) || defined(ASYMMETRIC_AUTO_SQUARE)
auto_square.mask |= (1 << (N_AXIS - 1));
#endif
if(!limits_pull_off(auto_square, &distance, 1.0f))
return false;
hal.stepper.disable_motors((axes_signals_t){0}, SquaringMode_Both);
}
// The active cycle axes should now be homed and machine limits have been located. By
@@ -615,6 +614,8 @@ FLASHMEM status_code_t limits_go_home (axes_signals_t cycle)
if((auto_squared.mask & homing_signals_select(hal.homing.get_state(), (axes_signals_t){0}, SquaringMode_Both).mask) && !limits_pull_off(auto_square, &homing_pulloff, HOMING_AXIS_LOCATE_SCALAR))
return Status_LimitsEngaged; // Auto squaring with limit switch asserted is not allowed.
hal.stepper.disable_motors((axes_signals_t){0}, SquaringMode_Both);
}
return grbl.home_machine(cycle, auto_square) ? Status_OK : Status_Unhandled;
+1 -1
View File
@@ -474,7 +474,7 @@
#define Z2_STEP_PORT MOTOR_IO(Z2_MOTOR_IDX, _STEP_PORT)
#define Z2_STEP_PIN MOTOR_IO(Z2_MOTOR_IDX, _STEP_PIN)
#define Z2_STEP_BIT (1<<<Z2_STEP_PIN)
#define Z2_STEP_BIT (1<<Z2_STEP_PIN)
#define Z2_DIRECTION_PORT MOTOR_IO(Z2_MOTOR_IDX, _DIRECTION_PORT)
#define Z2_DIRECTION_PIN MOTOR_IO(Z2_MOTOR_IDX, _DIRECTION_PIN)
#define Z2_DIRECTION_BIT (1<<Z2_DIRECTION_PIN)
+11 -11
View File
@@ -80,12 +80,12 @@ static char *get_axis_values_mm (float *axis_values)
buf[0] = '\0';
for (idx = 0; idx < N_AXIS; idx++) {
for (idx = 0; idx < system_n_axis(); idx++) {
if(idx == X_AXIS && gc_state.modal.diameter_mode)
strcat(buf, ftoa(axis_values[idx] * 2.0f, N_DECIMAL_COORDVALUE_MM));
else
strcat(buf, ftoa(axis_values[idx], N_DECIMAL_COORDVALUE_MM));
if (idx < (N_AXIS - 1))
if(idx < (system_n_axis() - 1))
strcat(buf, ",");
}
@@ -99,7 +99,7 @@ static char *get_axis_values_inches (float *axis_values)
buf[0] = '\0';
for (idx = 0; idx < N_AXIS; idx++) {
for (idx = 0; idx < system_n_axis(); idx++) {
if(idx == X_AXIS && gc_state.modal.diameter_mode)
strcat(buf, ftoa(axis_values[idx] * INCH_PER_MM * 2.0f, N_DECIMAL_COORDVALUE_INCH));
#if N_AXIS > 3
@@ -108,7 +108,7 @@ static char *get_axis_values_inches (float *axis_values)
#endif
else
strcat(buf, ftoa(axis_values[idx] * INCH_PER_MM, N_DECIMAL_COORDVALUE_INCH));
if (idx < (N_AXIS - 1))
if (idx < (system_n_axis() - 1))
strcat(buf, ",");
}
@@ -691,7 +691,7 @@ FLASHMEM void report_ngc_parameters (void)
static inline bool is_g92_active (void)
{
bool active = false;
uint_fast32_t idx = N_AXIS;
uint_fast32_t idx = system_n_axis();
do {
idx--;
@@ -959,7 +959,7 @@ FLASHMEM void report_build_info (char *line, bool extended)
hal.stream.write(uitoa(hal.rx_buffer_size));
if(extended) {
hal.stream.write(",");
hal.stream.write(uitoa((uint32_t)N_AXIS));
hal.stream.write(uitoa((uint32_t)system_n_axis()));
hal.stream.write(",");
hal.stream.write(uitoa(grbl.tool_table.n_tools));
}
@@ -971,12 +971,12 @@ FLASHMEM void report_build_info (char *line, bool extended)
nvs_io_t *nvs = nvs_buffer_get_physical();
atc_status_t atc = hal.tool.atc_get_state();
strcat(strcpy(buf, "[AXS:"), uitoa(N_AXIS));
strcat(strcpy(buf, "[AXS:"), uitoa((uint32_t)system_n_axis()));
append = &buf[6];
*append++ = ':';
for(idx = 0; idx < N_AXIS; idx++)
for(idx = 0; idx < system_n_axis(); idx++)
*append++ = *axis_letter[idx];
*append = '\0';
@@ -1267,7 +1267,7 @@ void report_realtime_status (stream_write_ptr stream_write, status_report_tracki
// Calculate distance-to-go in current block (i.e., difference between target / end-of-block) and current position)
plan_block_t *cur_block = plan_get_current_block();
if((report->flags.distance_to_go = !!cur_block)) {
for(idx = 0; idx < N_AXIS; idx++) {
for(idx = 0; idx < system_n_axis(); idx++) {
dist_remaining[idx] = cur_block->target_mm[idx] - print_position[idx];
}
}
@@ -1275,7 +1275,7 @@ void report_realtime_status (stream_write_ptr stream_write, status_report_tracki
if(!settings.status_report.machine_position) {
// Apply work coordinate offsets and tool length offset to current position.
for(idx = 0; idx < N_AXIS; idx++) {
for(idx = 0; idx < system_n_axis(); idx++) {
wco[idx] = gc_get_offset(idx, true);
print_position[idx] -= wco[idx];
}
@@ -1433,7 +1433,7 @@ void report_realtime_status (stream_write_ptr stream_write, status_report_tracki
if(report->flags.wco) {
if(settings.status_report.machine_position) {
for(idx = 0; idx < N_AXIS; idx++)
for(idx = 0; idx < system_n_axis(); idx++)
wco[idx] = gc_get_offset(idx, true);
}
stream_write("|WCO:");
+219 -79
View File
@@ -57,7 +57,7 @@ const settings_restore_t settings_all = {
.driver_parameters = SETTINGS_RESTORE_DRIVER_PARAMETERS
};
PROGMEM const settings_t defaults = {
PROGMEM static const settings_t defaults = {
.version.id = SETTINGS_VERSION,
.version.build = (GRBL_BUILD - 20000000UL),
@@ -399,7 +399,7 @@ PROGMEM const settings_t defaults = {
static bool group_is_available (const setting_group_detail_t *group)
{
return true;
return group->id < Group_XAxis || group->id > Group_WAxis || group->id < Group_Axis0 + system_n_axis();
}
PROGMEM static const setting_group_detail_t setting_group_detail [] = {
@@ -582,27 +582,164 @@ static void homing_pulloff_init (float pulloff)
limits_homing_pulloff(&distance);
}
FLASHMEM static status_code_t set_axis_mask (setting_id_t id, uint_fast16_t value)
{
status_code_t status = Status_OK;
value &= AXES_BITMASK;
switch(id) {
case Setting_StepInvertMask:
settings.steppers.step_invert.mask = value;
break;
case Setting_DirInvertMask:
settings.steppers.dir_invert.mask = value;
break;
case Setting_InvertStepperEnable:
#if COMPATIBILITY_LEVEL > 2
static status_code_t set_enable_invert_mask (setting_id_t id, uint_fast16_t int_value)
{
settings.steppers.enable_invert.mask = int_value ? 0 : AXES_BITMASK;
return Status_OK;
}
settings.steppers.enable_invert.mask = value ? 0 : AXES_BITMASK;
#else
settings.steppers.enable_invert.mask = value;
#endif
break;
case Setting_LimitPinsInvertMask:
#if COMPATIBILITY_LEVEL > 1
settings.steppers.enable_invert.mask = value ? 0 : AXES_BITMASK;
#else
settings.steppers.enable_invert.mask = value;
#endif
break;
static status_code_t set_limits_invert_mask (setting_id_t id, uint_fast16_t int_value)
{
settings.limits.invert.mask = (int_value ? ~(DEFAULT_LIMIT_SIGNALS_INVERT_MASK) : DEFAULT_LIMIT_SIGNALS_INVERT_MASK) & AXES_BITMASK;
case Setting_LimitPullUpDisableMask:
settings.limits.disable_pullup.mask = value;
break;
return Status_OK;
case Setting_HomingDirMask:
settings.homing.dir_mask.value = value;
break;
case Setting_SteppersEnergize:
settings.steppers.energize.mask = value;
break;
case Setting_HomingCycle_1:
case Setting_HomingCycle_2:
case Setting_HomingCycle_3:
case Setting_HomingCycle_4:
case Setting_HomingCycle_5:
case Setting_HomingCycle_6:
settings.homing.cycle[id - Setting_HomingCycle_1].mask = value;
break;
case Setting_HomePinsInvertMask:
settings.home_invert.mask = value;
break;
case Setting_MotorWarningsEnable:
settings.motor_warning_enable.mask = value;
break;
case Setting_MotorWarningsInvert:
settings.motor_warning_invert.mask = value;
break;
case Setting_MotorFaultsEnable:
settings.motor_fault_enable.mask = value;
break;
case Setting_MotorFaultsInvert:
settings.motor_fault_invert.mask = value;
break;
default:
// Should never enter here
break;
}
return status;
}
FLASHMEM static uint32_t get_axis_mask (setting_id_t id, uint_fast16_t int_value)
{
uint32_t value = 0;
switch(id) {
case Setting_StepInvertMask:
value = settings.steppers.step_invert.mask;
break;
case Setting_DirInvertMask:
value = settings.steppers.dir_invert.mask;
break;
case Setting_InvertStepperEnable:
#if COMPATIBILITY_LEVEL > 2
value = !!settings.steppers.enable_invert.mask;
#else
value = settings.steppers.enable_invert.mask;
#endif
break;
case Setting_LimitPinsInvertMask:
#if COMPATIBILITY_LEVEL > 1
value = settings.steppers.enable_invert.mask == DEFAULT_LIMIT_SIGNALS_INVERT_MASK ? 0 : 1;
#else
value = settings.steppers.enable_invert.mask;
#endif
break;
case Setting_LimitPullUpDisableMask:
value = settings.limits.disable_pullup.mask;
break;
case Setting_HomingDirMask:
value = settings.homing.dir_mask.value;
break;
case Setting_SteppersEnergize:
value = settings.steppers.energize.mask;
break;
case Setting_HomingCycle_1:
case Setting_HomingCycle_2:
case Setting_HomingCycle_3:
case Setting_HomingCycle_4:
case Setting_HomingCycle_5:
case Setting_HomingCycle_6:
value = settings.homing.cycle[id - Setting_HomingCycle_1].mask & system_axis_mask();
break;
case Setting_HomePinsInvertMask:
value = settings.home_invert.mask;
break;
case Setting_MotorWarningsEnable:
value = settings.motor_warning_enable.mask;
break;
case Setting_MotorWarningsInvert:
value = settings.motor_warning_invert.mask;
break;
case Setting_MotorFaultsEnable:
value = settings.motor_fault_enable.mask;
break;
case Setting_MotorFaultsInvert:
value = settings.motor_fault_invert.mask;
break;
default:
break;
}
return value & system_axis_mask();
}
static status_code_t validate_pulse_width (float max_rate, float steps_per_mm, float pulse_width)
{
@@ -622,7 +759,7 @@ static status_code_t set_pulse_width (setting_id_t id, float value)
do {
idx--;
#if N_AXIS > 3
if(bit_isfalse(settings.steppers.is_rotary.mask, bit(idx)))
if(system_n_axis() > 3 && bit_isfalse(settings.steppers.is_rotary.mask, bit(idx)))
#endif
status = validate_pulse_width(settings.axis[idx].max_rate, settings.axis[idx].steps_per_mm, value);
} while(idx && status == Status_OK);
@@ -663,15 +800,6 @@ static status_code_t set_ganged_dir_invert (setting_id_t id, uint_fast16_t int_v
return Status_OK;
}
static status_code_t set_stepper_energize_mask (setting_id_t id, uint_fast16_t int_value)
{
settings.steppers.energize.mask = int_value;
hal.stepper.enable(settings.steppers.energize, true);
return Status_OK;
}
static status_code_t set_report_interval (setting_id_t setting, uint_fast16_t int_value)
{
if((settings.report_interval = int_value) == 0)
@@ -993,14 +1121,6 @@ static status_code_t set_restore_overrides (setting_id_t id, uint_fast16_t int_v
#endif // NO_SAFETY_DOOR_SUPPORT
static status_code_t set_homing_cycle (setting_id_t id, uint_fast16_t int_value)
{
settings.homing.cycle[id - Setting_HomingCycle_1].mask = int_value;
limits_set_homing_axes();
return Status_OK;
}
static status_code_t set_homing_pulloff (setting_id_t id, float value)
{
settings.homing.pulloff = value;
@@ -1012,7 +1132,7 @@ static status_code_t set_homing_pulloff (setting_id_t id, float value)
static status_code_t set_homing_feedrates (setting_id_t id, float value)
{
uint_fast8_t idx = N_AXIS;
uint_fast8_t idx = system_n_axis();
if(!settings.homing.flags.per_axis_feedrates) switch(id) {
@@ -1516,18 +1636,6 @@ FLASHMEM static uint32_t get_int (setting_id_t id)
switch(id) {
#if COMPATIBILITY_LEVEL > 2
case Setting_InvertStepperEnable:
value = settings.steppers.enable_invert.mask ? 0 : 1;
break;
#endif
#if COMPATIBILITY_LEVEL > 1
case Setting_LimitPinsInvertMask:
value = settings.limits.invert.mask == DEFAULT_LIMIT_SIGNALS_INVERT_MASK ? 0 : 1;
break;
#endif
case Setting_SpindlePWMOptions:
value = settings.pwm_spindle.flags.pwm_disable
? 0
@@ -1538,6 +1646,10 @@ FLASHMEM static uint32_t get_int (setting_id_t id)
(settings.pwm_spindle.flags.ignore_delays ? 0b10000 : 0));
break;
case Setting_HomingDirMask:
value = settings.homing.dir_mask.mask & system_axis_mask();
break;
case Setting_Mode:
value = settings.mode;
break;
@@ -1620,15 +1732,6 @@ FLASHMEM static uint32_t get_int (setting_id_t id)
value = settings.parking.flags.value;
break;
case Setting_HomingCycle_1:
case Setting_HomingCycle_2:
case Setting_HomingCycle_3:
case Setting_HomingCycle_4:
case Setting_HomingCycle_5:
case Setting_HomingCycle_6:
value = settings.homing.cycle[id - Setting_HomingCycle_1].mask;
break;
case Setting_RestoreOverrides:
value = settings.flags.restore_overrides;
break;
@@ -1959,6 +2062,24 @@ FLASHMEM static bool is_setting_available (const setting_detail_t *setting, uint
available = spindle_get_caps(false).variable;
break;
#if N_AXIS > 3
case Setting_HomingCycle_4:
case Settings_RotaryAxes:
case Setting_RotaryWrap:
available = system_n_axis() > 3;
break;
#endif
#if N_AXIS > 4
case Setting_HomingCycle_5:
available = system_n_axis() > 4;
break;
#endif
#if N_AXIS > 5
case Setting_HomingCycle_6:
available = system_n_axis() > 5;
break;
#endif
case Setting_SleepEnable:
available = SLEEP_DURATION > 0.0f;
break;
@@ -2156,17 +2277,17 @@ FLASHMEM static void _settings_write_global (void)
PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_PulseMicroseconds, Group_Stepper, "Step pulse time", "microseconds", Format_Decimal, "#0.0", step_us_min, NULL, Setting_IsLegacyFn, set_pulse_width, get_float, NULL },
{ Setting_StepperIdleLockTime, Group_Stepper, "Step idle delay", "milliseconds", Format_Int16, "####0", NULL, "65535", Setting_IsLegacy, &settings.steppers.idle_lock_time, NULL, NULL },
{ Setting_StepInvertMask, Group_Stepper, "Step pulse invert", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.steppers.step_invert.mask, NULL, NULL },
{ Setting_DirInvertMask, Group_Stepper, "Step direction invert", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.steppers.dir_invert.mask, NULL, NULL },
{ Setting_StepInvertMask, Group_Stepper, "Step pulse invert", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacyFn, set_axis_mask, get_axis_mask, NULL },
{ Setting_DirInvertMask, Group_Stepper, "Step direction invert", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacyFn, set_axis_mask, get_axis_mask, NULL },
#if COMPATIBILITY_LEVEL <= 2
{ Setting_InvertStepperEnable, Group_Stepper, "Invert stepper enable output(s)", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.steppers.enable_invert.mask, NULL, NULL },
{ Setting_InvertStepperEnable, Group_Stepper, "Invert stepper enable output(s)", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacyFn, set_axis_mask, get_axis_mask, NULL },
#else
{ Setting_InvertStepperEnable, Group_Stepper, "Invert stepper enable output", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_enable_invert_mask, get_int, NULL },
{ Setting_InvertStepperEnable, Group_Stepper, "Invert stepper enable output", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_axis_mask, get_axis_mask, NULL },
#endif
#if COMPATIBILITY_LEVEL <= 1
{ Setting_LimitPinsInvertMask, Group_Limits, "Invert limit inputs", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.limits.invert.mask, NULL, NULL },
{ Setting_LimitPinsInvertMask, Group_Limits, "Invert limit inputs", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacyFn, set_axis_mask, get_axis_mask, NULL },
#else
{ Setting_LimitPinsInvertMask, Group_Limits, "Invert limit inputs", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_limits_invert_mask, get_int, NULL },
{ Setting_LimitPinsInvertMask, Group_Limits, "Invert limit inputs", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_axis_mask, get_axis_mask, NULL },
#endif
{ Setting_InvertProbePin, Group_Probing, "Invert probe inputs", NULL, Format_Bitfield, probe_signals, NULL, NULL, Setting_IsLegacyFn, set_probe_invert, get_int, is_setting_available },
{ Setting_SpindlePWMBehaviour, Group_Spindle, "Deprecated", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_pwm_mode, get_int, is_setting_available },
@@ -2184,7 +2305,7 @@ PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_CoolantInvertMask, Group_Coolant, "Invert coolant outputs", NULL, Format_Bitfield, coolant_signals, NULL, NULL, Setting_IsExtended, &settings.coolant.invert.mask, NULL, NULL },
{ Setting_SpindleInvertMask, Group_Spindle, "Invert spindle signals", NULL, Format_Bitfield, spindle_signals, NULL, NULL, Setting_IsExtendedFn, set_spindle_invert, get_int, is_setting_available, { .reboot_required = On } },
{ Setting_ControlPullUpDisableMask, Group_ControlSignals, "Pullup disable control inputs", NULL, Format_Bitfield, control_signals, NULL, NULL, Setting_IsExtendedFn, set_control_disable_pullup, get_int, is_setting_available },
{ Setting_LimitPullUpDisableMask, Group_Limits, "Pullup disable limit inputs", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.limits.disable_pullup.mask, NULL, NULL },
{ Setting_LimitPullUpDisableMask, Group_Limits, "Pullup disable limit inputs", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, NULL },
{ Setting_ProbePullUpDisable, Group_Probing, "Pullup disable probe inputs", NULL, Format_Bitfield, probe_signals, NULL, NULL, Setting_IsLegacyFn, set_probe_disable_pullup, get_int, is_setting_available },
{ Setting_SoftLimitsEnable, Group_Limits, "Soft limits enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_soft_limits_enable, get_int, NULL },
#if COMPATIBILITY_LEVEL <= 1
@@ -2201,7 +2322,7 @@ PROGMEM static const setting_detail_t setting_detail[] = {
#else
{ Setting_HomingEnable, Group_Homing, "Homing cycle enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_homing_enable, get_int, NULL },
#endif
{ Setting_HomingDirMask, Group_Homing, "Homing direction invert", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacy, &settings.homing.dir_mask.value, NULL, NULL },
{ Setting_HomingDirMask, Group_Homing, "Homing direction invert", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsLegacyFn, set_axis_mask, get_axis_mask, NULL },
{ Setting_HomingFeedRate, Group_Homing, "Homing locate feed rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsLegacyFn, set_homing_feedrates, get_float, NULL },
{ Setting_HomingSeekRate, Group_Homing, "Homing search seek rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsLegacyFn, set_homing_feedrates, get_float, NULL },
{ Setting_HomingDebounceDelay, Group_Homing, "Homing switch debounce delay", "milliseconds", Format_Int16, "##0", NULL, NULL, Setting_IsLegacy, &settings.homing.debounce_delay, NULL, NULL },
@@ -2217,24 +2338,24 @@ PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_PWMOffValue, Group_Spindle, "Spindle PWM off value", "percent", Format_Decimal, "##0.0", NULL, "100", Setting_IsExtended, &settings.pwm_spindle.pwm_off_value, NULL, is_setting_available },
{ Setting_PWMMinValue, Group_Spindle, "Spindle PWM min value", "percent", Format_Decimal, "##0.0", NULL, "100", Setting_IsExtended, &settings.pwm_spindle.pwm_min_value, NULL, is_setting_available },
{ Setting_PWMMaxValue, Group_Spindle, "Spindle PWM max value", "percent", Format_Decimal, "##0.0", NULL, "100", Setting_IsExtended, &settings.pwm_spindle.pwm_max_value, NULL, is_setting_available },
{ Setting_SteppersEnergize, Group_Stepper, "Steppers to keep enabled", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_stepper_energize_mask, get_int, NULL },
{ Setting_SteppersEnergize, Group_Stepper, "Steppers to keep enabled", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, NULL },
{ Setting_SpindlePPR, Group_Spindle, "Spindle pulses per revolution (PPR)", NULL, Format_Int16, "###0", NULL, NULL, Setting_IsExtended, &settings.spindle.ppr, NULL, is_setting_available, { .reboot_required = On } },
{ Setting_EnableLegacyRTCommands, Group_General, "Enable legacy RT commands", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_enable_legacy_rt_commands, get_int, NULL },
{ Setting_JogSoftLimited, Group_Jogging, "Limit jog commands", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_jog_soft_limited, get_int, NULL },
{ Setting_ParkingEnable, Group_SafetyDoor, "Parking cycle", NULL, Format_XBitfield, "Enable,Deactivate upon init,Enable parking override control", NULL, NULL, Setting_IsExtendedFn, set_parking_enable, get_int, NULL },
{ Setting_ParkingAxis, Group_SafetyDoor, "Parking axis", NULL, Format_RadioButtons, "X,Y,Z", NULL, NULL, Setting_IsExtended, &settings.parking.axis, NULL, NULL },
{ Setting_HomingLocateCycles, Group_Homing, "Homing passes", NULL, Format_Int8, "##0", "1", "128", Setting_IsExtended, &settings.homing.locate_cycles, NULL, NULL },
{ Setting_HomingCycle_1, Group_Homing, "Axes homing, first phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingCycle_2, Group_Homing, "Axes homing, second phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingCycle_3, Group_Homing, "Axes homing, third phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingCycle_1, Group_Homing, "Axes homing, first phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, NULL },
{ Setting_HomingCycle_2, Group_Homing, "Axes homing, second phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, NULL },
{ Setting_HomingCycle_3, Group_Homing, "Axes homing, third phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, NULL },
#if N_AXIS > 3
{ Setting_HomingCycle_4, Group_Homing, "Axes homing, fourth phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingCycle_4, Group_Homing, "Axes homing, fourth phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, is_setting_available },
#endif
#if N_AXIS > 4
{ Setting_HomingCycle_5, Group_Homing, "Axes homing, fifth phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingCycle_5, Group_Homing, "Axes homing, fifth phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, is_setting_available },
#endif
#if N_AXIS > 5
{ Setting_HomingCycle_6, Group_Homing, "Axes homing, sixth phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL },
{ Setting_HomingCycle_6, Group_Homing, "Axes homing, sixth phase", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, is_setting_available },
#endif
{ Setting_ParkingPulloutIncrement, Group_SafetyDoor, "Parking pull-out distance", "mm", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.pullout_increment, NULL, NULL },
{ Setting_ParkingPulloutRate, Group_SafetyDoor, "Parking pull-out rate", "mm/min", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.pullout_rate, NULL, NULL },
@@ -2291,7 +2412,7 @@ PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_DisableG92Persistence, Group_General, "Disable G92 persistence", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_g92_disable_persistence, get_int, NULL },
#endif
#if N_AXIS > 3
{ Settings_RotaryAxes, Group_Stepper, "Rotary axes", NULL, Format_Bitfield, rotary_axes, NULL, NULL, Setting_IsExtendedFn, set_rotary_axes, get_int, NULL },
{ Settings_RotaryAxes, Group_Stepper, "Rotary axes", NULL, Format_Bitfield, rotary_axes, NULL, NULL, Setting_IsExtendedFn, set_rotary_axes, get_int, is_setting_available },
#endif
{ Setting_DoorSpindleOnDelay, Group_SafetyDoor, "Spindle on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtended, &settings.safety_door.spindle_on_delay, NULL, NULL, { .allow_null = On } },
{ Setting_DoorCoolantOnDelay, Group_SafetyDoor, "Coolant on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtended, &settings.safety_door.coolant_on_delay, NULL, NULL, { .allow_null = On } },
@@ -2312,16 +2433,16 @@ PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_RGB_StripLengt0, Group_AuxPorts, "LED strip 1 length", NULL, Format_Int8, "##0", NULL, "255", Setting_NonCore, &settings.rgb_strip.length0, NULL, is_setting_available },
{ Setting_RGB_StripLengt1, Group_AuxPorts, "LED strip 2 length", NULL, Format_Int8, "##0", NULL, "255", Setting_NonCore, &settings.rgb_strip.length1, NULL, is_setting_available },
#if N_AXIS > 3
{ Setting_RotaryWrap, Group_Stepper, "Fast rotary go to G28", NULL, Format_Bitfield, rotary_axes, NULL, NULL, Setting_IsExtendedFn, set_rotary_wrap_axes, get_int, NULL },
{ Setting_RotaryWrap, Group_Stepper, "Fast rotary go to G28", NULL, Format_Bitfield, rotary_axes, NULL, NULL, Setting_IsExtendedFn, set_rotary_wrap_axes, get_int, is_setting_available },
#endif
{ Setting_SpindleOffDelay, Group_Spindle, "Spindle off delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtendedFn, set_float, get_float, is_setting_available, { .allow_null = On } },
{ Setting_FSOptions, Group_General, "File systems options", NULL, Format_Bitfield, fs_options, NULL, NULL, Setting_IsExtended, &settings.fs_options.mask, NULL, is_setting_available },
{ Setting_HomePinsInvertMask, Group_Limits, "Invert home inputs", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.home_invert.mask, NULL, is_setting_available },
{ Setting_HomePinsInvertMask, Group_Limits, "Invert home inputs", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, is_setting_available },
{ Setting_CoolantOnDelay, Group_Coolant, "Coolant on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtendedFn, set_float, get_float, is_setting_available, { .allow_null = On } },
{ Setting_MotorWarningsEnable, Group_Stepper, "Motor warning inputs enable", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.motor_warning_enable, NULL, is_setting_available },
{ Setting_MotorWarningsInvert, Group_Stepper, "Invert motor warning inputs", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.motor_warning_invert, NULL, is_setting_available },
{ Setting_MotorFaultsEnable, Group_Stepper, "Motor fault inputs enable", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.motor_fault_enable, NULL, is_setting_available },
{ Setting_MotorFaultsInvert, Group_Stepper, "Invert motor fault inputs", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.motor_fault_invert, NULL, is_setting_available },
{ Setting_MotorWarningsEnable, Group_Stepper, "Motor warning inputs enable", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, is_setting_available },
{ Setting_MotorWarningsInvert, Group_Stepper, "Invert motor warning inputs", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, is_setting_available },
{ Setting_MotorFaultsEnable, Group_Stepper, "Motor fault inputs enable", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, is_setting_available },
{ Setting_MotorFaultsInvert, Group_Stepper, "Invert motor fault inputs", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_axis_mask, get_axis_mask, is_setting_available },
{ Setting_ResetActions, Group_General, "Reset actions", NULL, Format_Bitfield, "Clear homed status if position was lost,Clear offsets (except G92),Clear rapids override,Clear feed override", NULL, NULL, Setting_IsExtendedFn, set_reset_actions, get_int, NULL },
{ Setting_StepperEnableDelay, Group_Stepper, "Stepper enable delay", "ms", Format_Int16, "##0", NULL, "500", Setting_IsExtended, &settings.stepper_enable_delay, NULL, NULL },
{ Setting_SubroutineOptions, Group_General, "Subroutine options", NULL, Format_Bitfield, "Prescan for internal M98 subroutines", NULL, NULL, Setting_IsExtendedFn, set_suboptions, get_int, is_setting_available }
@@ -2897,7 +3018,7 @@ FLASHMEM bool settings_iterator (const setting_detail_t *setting, setting_output
uint_fast8_t axis_idx = 0;
for(axis_idx = 0; axis_idx < N_AXIS; axis_idx++) {
for(axis_idx = 0; axis_idx < system_n_axis(); axis_idx++) {
if(setting->is_available == NULL || setting->is_available(setting, axis_idx)) {
@@ -3210,7 +3331,7 @@ FLASHMEM static status_code_t setting_validate_me_uint (const setting_detail_t *
break;
case Format_AxisMask:
if(value >= (1 << N_AXIS))
if(value >= (1 << system_n_axis()))
status = Status_SettingValueOutOfRange;
break;
@@ -3416,6 +3537,25 @@ FLASHMEM status_code_t settings_store_setting (setting_id_t id, char *svalue)
machine_mode_changed = false;
set->on_changed(&settings, changed);
switch(setting->id) {
case Setting_SteppersEnergize:
hal.stepper.enable(settings.steppers.energize, true);
break;
case Setting_HomingCycle_1:
case Setting_HomingCycle_2:
case Setting_HomingCycle_3:
case Setting_HomingCycle_4:
case Setting_HomingCycle_5:
case Setting_HomingCycle_6:
limits_set_homing_axes();
break;
default:
break;
}
}
}
@@ -3570,7 +3710,7 @@ FLASHMEM void settings_init (void)
setting_remove_elements(Setting_DoorOptions, ((!settings.parking.flags.enabled || hal.signals_cap.safety_door_ajar) << 1) | hal.signals_cap.safety_door_ajar, true);
#endif
#if N_AXIS > 3
for(idx = 3; idx < N_AXIS; idx++)
for(idx = 3; idx < system_n_axis(); idx++)
*(rotary_axes + (idx - 3) * 7) = *axis_letter[idx];
#endif
+27
View File
@@ -33,6 +33,8 @@
#include "kinematics.h"
#endif
static uint8_t n_axis = N_AXIS;
/*! \internal \brief Simple hypotenuse computation function.
\param x length
\param y height
@@ -43,6 +45,27 @@ inline static float hypot_f (float x, float y)
return sqrtf(x * x + y * y);
}
FLASHMEM uint8_t system_claim_axis (void)
{
return n_axis > 3 ? n_axis-- : 0;
}
uint8_t system_n_axis (void)
{
return n_axis;
}
FLASHMEM uint8_t system_axis_mask (void)
{
uint8_t axis_mask = 0;
uint_fast32_t idx = n_axis;
while(idx--)
axis_mask = (axis_mask << 1) | 1;
return axis_mask;
}
void system_init_switches (void)
{
control_signals_t signals = hal.control.get_state();
@@ -165,6 +188,8 @@ FLASHMEM void system_execute_startup (void *data)
uint_fast8_t idx;
char line[sizeof(stored_line_t)];
bool single_block = sys.flags.single_block;
sys.flags.single_block = Off; // Disable single block mode when executing startup code.
for(idx = 0; idx < N_STARTUP_LINE; idx++) {
if(!settings_read_startup_line(idx, line))
@@ -176,6 +201,8 @@ FLASHMEM void system_execute_startup (void *data)
} while((block = strtok(NULL, "|")));
}
}
sys.flags.single_block = single_block;
}
}
+4
View File
@@ -319,6 +319,10 @@ typedef struct sys_commands_str {
extern system_t sys;
uint8_t system_n_axis (void);
uint8_t system_axis_mask (void);
uint8_t system_claim_axis (void);
status_code_t system_execute_line (char *line);
void system_execute_startup (void *data);
void system_flag_wco_change (void);