diff --git a/README.md b/README.md
index a478954..5aff7e8 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ It has been written to complement grblHAL and has features such as proper keyboa
---
-Latest build date is 20221101, see the [changelog](changelog.md) for details.
+Latest build date is 20221115, see the [changelog](changelog.md) for details.
__NOTE:__ A settings reset will be performed on an update for versions earlier than 20211122. Backup and restore of settings is recommended.
__IMPORTANT!__ A new setting has been introduced for ganged axes motors in version 20211121.
I have only bench tested this for a couple of drivers, correct function should be verified after updating by those who have more than three motors configured.
diff --git a/changelog.md b/changelog.md
index 54a9c41..65a5a2a 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,24 @@
## grblHAL changelog
+Build 20221115
+
+Core:
+
+* Updated settings reports to output correct units and descriptions for settings related to axes configured as rotary.
+__Note:__ Senders may have to be restarted to display these after a configuration change \($376 - rotatational axes\) and even then they might not display them correctly.
+
+* Internal change to allow flagging settings to have a minimum value or length different from 0 and still allow to them to be 0 or have length 0.
+
+Plugins:
+
+* Some: updated for core settings change.
+
+Drivers:
+
+* Some: updated for core settings change.
+
+---
+
Build 20221101
Core:
@@ -396,7 +415,7 @@ __Note:__ NVS storage of settings has been moved to the end of flash, backup and
Core:
-* Addded virtual file system \(VFS\) handler, Linux/Unix style with mount directories.
+* Added virtual file system \(VFS\) handler, Linux/Unix style with mount directories.
* Now raises alarm if homed state becomes invalid on settings changes when homing on startup is required. Issue #173.
Plugins:
diff --git a/grbl.h b/grbl.h
index c305d27..e2b475a 100644
--- a/grbl.h
+++ b/grbl.h
@@ -38,7 +38,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
-#define GRBL_BUILD 20221101
+#define GRBL_BUILD 20221115
#define GRBL_URL "https://github.com/grblHAL"
diff --git a/nuts_bolts.c b/nuts_bolts.c
index c55dbcb..ceab01e 100644
--- a/nuts_bolts.c
+++ b/nuts_bolts.c
@@ -42,17 +42,17 @@ static char buf[STRLEN_COORDVALUE + 1];
static const float froundvalues[MAX_PRECISION + 1] =
{
- 0.5, // 0
- 0.05, // 1
- 0.005, // 2
- 0.0005, // 3
- 0.00005, // 4
- 0.000005, // 5
- 0.0000005, // 6
- 0.00000005, // 7
- 0.000000005, // 8
- 0.0000000005, // 9
- 0.00000000005 // 10
+ 0.5f, // 0
+ 0.05f, // 1
+ 0.005f, // 2
+ 0.0005f, // 3
+ 0.00005f, // 4
+ 0.000005f, // 5
+ 0.0000005f, // 6
+ 0.00000005f, // 7
+ 0.000000005f, // 8
+ 0.0000000005f, // 9
+ 0.00000000005f // 10
};
#if N_AXIS > 6 && defined(AXIS_REMAP_ABC2UVW)
diff --git a/report.c b/report.c
index de5f3cf..55ec566 100644
--- a/report.c
+++ b/report.c
@@ -1504,13 +1504,13 @@ static void report_settings_detail (settings_format_t format, const setting_deta
}
}
- if(setting->reboot_required)
+ if(setting->flags.reboot_required)
hal.stream.write(", reboot required");
#ifndef NO_SETTINGS_DESCRIPTIONS
// Add description if driver is capable of outputting it...
if(hal.stream.write_n) {
- const char *description = setting_get_description(setting->id);
+ const char *description = setting_get_description(setting->id + offset);
if(description && *description != '\0') {
char *lf;
hal.stream.write(ASCII_EOL);
@@ -1525,7 +1525,7 @@ static void report_settings_detail (settings_format_t format, const setting_deta
hal.stream.write(description);
}
}
- if(setting->reboot_required) {
+ if(setting->flags.reboot_required) {
if(description && *description != '\0')
hal.stream.write(ASCII_EOL ASCII_EOL);
hal.stream.write(SETTINGS_HARD_RESET_REQUIRED + 4);
@@ -1558,7 +1558,7 @@ static void report_settings_detail (settings_format_t format, const setting_deta
if(setting->max_value)
hal.stream.write(setting->max_value);
hal.stream.write(vbar);
- hal.stream.write(uitoa(setting->reboot_required));
+ hal.stream.write(uitoa(setting->flags.reboot_required));
hal.stream.write("]");
break;
@@ -1676,7 +1676,7 @@ static void report_settings_detail (settings_format_t format, const setting_deta
#ifndef NO_SETTINGS_DESCRIPTIONS
const char *description = setting_get_description((setting_id_t)(setting->id + offset));
hal.stream.write(description ? description : "");
- if(setting->reboot_required)
+ if(setting->flags.reboot_required)
hal.stream.write(SETTINGS_HARD_RESET_REQUIRED + (description && *description != '\0' ? 0 : 4));
#endif
hal.stream.write("\t");
@@ -1691,7 +1691,7 @@ static void report_settings_detail (settings_format_t format, const setting_deta
hal.stream.write("\t");
- hal.stream.write(uitoa(setting->reboot_required));
+ hal.stream.write(uitoa(setting->flags.reboot_required));
}
break;
}
@@ -1816,7 +1816,7 @@ status_code_t report_setting_description (settings_format_t format, setting_id_t
}
// hal.stream.write(description == NULL ? (is_setting_available(setting_get_details(id, NULL)) ? "" : "N/A") : description); // TODO?
hal.stream.write(description ? description : (setting ? "" : "N/A"));
- if(setting && setting->reboot_required)
+ if(setting && setting->flags.reboot_required)
hal.stream.write(SETTINGS_HARD_RESET_REQUIRED + (description && *description != '\0' ? 0 : 4));
if(format == SettingsFormat_MachineReadable)
diff --git a/settings.c b/settings.c
index 2ff7b59..4f01f17 100644
--- a/settings.c
+++ b/settings.c
@@ -413,6 +413,10 @@ static char spindle_signals[] = "Spindle enable,Spindle direction,PWM";
static char coolant_signals[] = "Flood,Mist";
static char ganged_axes[] = "X-Axis,Y-Axis,Z-Axis";
static char spindle_types[100] = "";
+static char axis_dist[4] = "mm";
+static char axis_rate[8] = "mm/min";
+static char axis_accel[10] = "mm/sec^2";
+static char axis_steps[9] = "step/mm";
PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_PulseMicroseconds, Group_Stepper, "Step pulse time", "microseconds", Format_Decimal, "#0.0", "2.0", NULL, Setting_IsLegacy, &settings.steppers.pulse_microseconds, NULL, NULL },
@@ -520,12 +524,12 @@ PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_PositionIGain, Group_Spindle_Sync, "Spindle sync I-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.position.pid.i_gain, NULL, is_group_available },
{ Setting_PositionDGain, Group_Spindle_Sync, "Spindle sync D-gain", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.position.pid.d_gain, NULL, is_group_available },
{ Setting_PositionIMaxError, Group_Spindle_Sync, "Spindle sync PID max I error", NULL, Format_Decimal, "###0.000", NULL, NULL, Setting_IsExtended, &settings.position.pid.i_max_error, NULL, is_group_available },
- { Setting_AxisStepsPerMM, Group_Axis0, "?-axis travel resolution", "step/mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
- { Setting_AxisMaxRate, Group_Axis0, "?-axis maximum rate", "mm/min", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
- { Setting_AxisAcceleration, Group_Axis0, "?-axis acceleration", "mm/sec^2", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
- { Setting_AxisMaxTravel, Group_Axis0, "?-axis maximum travel", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
+ { Setting_AxisStepsPerMM, Group_Axis0, "?-axis travel resolution", axis_steps, Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
+ { Setting_AxisMaxRate, Group_Axis0, "?-axis maximum rate", axis_rate, Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
+ { Setting_AxisAcceleration, Group_Axis0, "?-axis acceleration", axis_accel, Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
+ { Setting_AxisMaxTravel, Group_Axis0, "?-axis maximum travel", axis_dist, Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacyFn, set_axis_setting, get_float, NULL },
#ifdef ENABLE_BACKLASH_COMPENSATION
- { Setting_AxisBacklash, Group_Axis0, "?-axis backlash compensation", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsExtendedFn, set_axis_setting, get_float, NULL },
+ { Setting_AxisBacklash, Group_Axis0, "?-axis backlash compensation", axis_dist, Format_Decimal, "#####0.000", NULL, NULL, Setting_IsExtendedFn, set_axis_setting, get_float, NULL },
#endif
{ Setting_AxisAutoSquareOffset, Group_Axis0, "?-axis dual axis offset", "mm", Format_Decimal, "-0.000", "-10", "10", Setting_IsExtendedFn, set_axis_setting, get_float, is_setting_available },
{ Setting_SpindleAtSpeedTolerance, Group_Spindle, "Spindle at speed tolerance", "percent", Format_Decimal, "##0.0", NULL, NULL, Setting_IsExtended, &settings.spindle.at_speed_tolerance, NULL, is_setting_available },
@@ -569,7 +573,7 @@ PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_SpindleOnDelay, Group_Spindle, "Spindle on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtended, &settings.safety_door.spindle_on_delay, NULL, is_setting_available },
{ Setting_SpindleType, Group_Spindle, "Default spindle", NULL, Format_RadioButtons, spindle_types, NULL, NULL, Setting_IsExtendedFn, set_spindle_type, get_int, is_setting_available },
#ifdef BLOCK_BUFFER_DYNAMIC
- { Setting_PlannerBlocks, Group_General, "Planner buffer blocks", NULL, Format_Int16, "####0", "30", "1000", Setting_IsExtended, &settings.planner_buffer_blocks, NULL, NULL, true },
+ { Setting_PlannerBlocks, Group_General, "Planner buffer blocks", NULL, Format_Int16, "####0", "30", "1000", Setting_IsExtended, &settings.planner_buffer_blocks, NULL, NULL, { .reboot_required = On } },
#endif
};
@@ -686,6 +690,7 @@ PROGMEM static const setting_descr_t setting_descr[] = {
{ Setting_PositionDGain, "" },
{ Setting_PositionIMaxError, "Spindle sync PID max integrator error." },
{ Setting_AxisStepsPerMM, "Travel resolution in steps per millimeter." },
+ { Setting_AxisStepsPerMM + 1, "Travel resolution in steps per degree." }, // "Hack" to get correct description for rotary axes
{ Setting_AxisMaxRate, "Maximum rate. Used as G0 rapid rate." },
{ Setting_AxisAcceleration, "Acceleration. Used for motion planning to not exceed motor torque and lose steps." },
{ Setting_AxisMaxTravel, "Maximum axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances." },
@@ -2062,6 +2067,39 @@ setting_group_t settings_get_parent_group (setting_group_t group)
}
*/
+static inline bool axis_is_rotary (uint_fast8_t axis_idx)
+{
+ return bit_istrue(settings.steppers.is_rotational.mask, bit(axis_idx));
+}
+
+static void set_axis_setting_unit (const setting_detail_t *setting, uint_fast8_t axis_idx)
+{
+ bool is_rotary = axis_is_rotary(axis_idx);
+
+ switch(setting->id) {
+
+ case Setting_AxisStepsPerMM:
+ strcpy((char *)setting->unit, is_rotary ? "step/deg" : "step/mm");
+ break;
+
+ case Setting_AxisMaxRate:
+ strcpy((char *)setting->unit, is_rotary ? "deg/min" : "mm/min");
+ break;
+
+ case Setting_AxisAcceleration:
+ strcpy((char *)setting->unit, is_rotary ? "deg/sec^2" : "mm/sec^2");
+ break;
+
+ case Setting_AxisMaxTravel:
+ case Setting_AxisBacklash:
+ strcpy((char *)setting->unit, is_rotary ? "deg" : "mm");
+ break;
+
+ default:
+ break;
+ }
+}
+
bool settings_iterator (const setting_detail_t *setting, setting_output_ptr callback, void *data)
{
bool ok = false;
@@ -2089,6 +2127,7 @@ bool settings_iterator (const setting_detail_t *setting, setting_output_ptr call
{
uint_fast8_t axis_idx = 0;
for(axis_idx = 0; axis_idx < N_AXIS; axis_idx++) {
+ set_axis_setting_unit(setting, axis_idx);
if(callback(setting, axis_idx, data))
ok = true;
}
@@ -2126,6 +2165,8 @@ const setting_detail_t *setting_get_details (setting_id_t id, setting_details_t
do {
for(idx = 0; idx < details->n_settings; idx++) {
if(details->settings[idx].id == id && is_available(&details->settings[idx])) {
+ if(details->settings[idx].group == Group_Axis0)
+ set_axis_setting_unit(&details->settings[idx], offset);
if(offset && offset >= (details->settings[idx].group == Group_Encoder0 ? hal.encoder.get_n_encoders() : N_AXIS))
return NULL;
if(set)
@@ -2152,8 +2193,11 @@ const char *setting_get_description (setting_id_t id)
if(settings->descriptions) {
idx = settings->n_descriptions;
do {
- if(settings->descriptions[--idx].id == setting->id)
+ if(settings->descriptions[--idx].id == setting->id) {
+ if(setting->id == Setting_AxisStepsPerMM && axis_is_rotary(id - setting->id))
+ idx++;
description = settings->descriptions[idx].description;
+ }
} while(idx && description == NULL);
}
} while(description == NULL && (settings = settings->next));
@@ -2188,13 +2232,13 @@ static status_code_t validate_value (const setting_detail_t *setting, float valu
if(!read_float((char *)setting->min_value, &set_idx, &val))
return Status_BadNumberFormat;
- if(value < val)
+ if(!(value >= val || (setting->flags.allow_null && value == 0.0f)))
return Status_SettingValueOutOfRange;
} else if(value < 0.0f)
return Status_NegativeValue;
- if (setting->max_value) {
+ if(setting->max_value) {
set_idx = 0;
if(!read_float((char *)setting->max_value, &set_idx, &val))
diff --git a/settings.h b/settings.h
index 3bfd268..1f97541 100644
--- a/settings.h
+++ b/settings.h
@@ -714,6 +714,15 @@ typedef union {
float fvalue;
} setting_limit_t;
+typedef union {
+ uint8_t value;
+ struct {
+ uint8_t reboot_required :1,
+ allow_null: 1,
+ unused :6;
+ };
+} setting_detail_flags_t;
+
typedef struct setting_detail {
setting_id_t id;
setting_group_t group;
@@ -727,7 +736,7 @@ typedef struct setting_detail {
void *value;
void *get_value;
bool (*is_available)(const struct setting_detail *setting);
- bool reboot_required;
+ setting_detail_flags_t flags;
} setting_detail_t;
typedef struct {