Skip to content

Commit 7ade244

Browse files
committed
Improved handling of extended M commands (plugin based) command words.
Fixes issues for programs containing extended M-codes using single meaning words (which they as a rule should not do). Added core support for spindle encoder binding to spindles. Added sorting of spindle report: enabled spindles are sorted first in order of spindle number, disabled by type then spindle id. Changed realtime report to report spindle number instead of spindle id on changes in the |S: element.
1 parent 01142dc commit 7ade244

10 files changed

+224
-61
lines changed

changelog.md

+35
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
11
## grblHAL changelog
22

3+
<a name="20240812">Build 20240812
4+
5+
Core:
6+
7+
* Improved handling of extended M commands \(plugin based\) command words. Fixes issues for programs containing extended M-codes using single meaning words \(which they as a rule should not do\).
8+
9+
* Added core support for spindle encoder binding to spindles.
10+
11+
* Added sorting of spindle report: enabled spindles are sorted first in order of spindle number, disabled by type then spindle id.
12+
13+
* Changed realtime report to report spindle number instead of spindle id on changes in the `|S:` element. Part of fix for ioSender [issue #399](https://github.com/terjeio/ioSender/issues/399).
14+
15+
Drivers:
16+
17+
* imXRT1061, MSP432, STM32F4xx, STM32F7xx: Updated to take advandage of new spindle encoder binding functionality.
18+
19+
Plugins:
20+
21+
* Spindle: updated relevant drivers to use new spindle encoder binding functionality, simplified code. Fixes [issue #30](https://github.com/grblHAL/Plugins_spindle/issues/30).
22+
23+
---
24+
25+
<a name="20240805">Build 20240805
26+
27+
Core:
28+
29+
* Added function for getting speed \(RPM\) of stepper controlled by secondary stepper motor driver.
30+
31+
Plugins:
32+
33+
* Spindle: stepper spindle code now uses new function for getting speed \(RPM\) of motor.
34+
HAL functions for getting spindle data \(actual RPM, angular position etc.\) directed to stepper spindle code,
35+
36+
---
37+
338
<a name="20240801">Build 20240801
439

540
Core:

gcode.c

+29-20
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ status_code_t gc_execute_block (char *block)
848848
// Initialize command and value words and parser flags variables.
849849
modal_groups_t command_words = {0}; // Bitfield for tracking G and M command words. Also used for modal group violations.
850850
gc_parser_flags_t gc_parser_flags = {0}; // Parser flags for handling special cases.
851-
static parameter_words_t user_words = {0}; // User M-code words "taken"
851+
parameter_words_t user_words = {0}; // User M-code words "taken"
852852

853853
// Determine if the line is a jogging motion or a normal g-code block.
854854
if (block[0] == '$') { // NOTE: `$J=` already parsed when passed to this function.
@@ -1680,6 +1680,24 @@ status_code_t gc_execute_block (char *block)
16801680
// same way. If there is an explicit/implicit axis command, XYZ words are always used and are
16811681
// are removed at the end of error-checking.
16821682

1683+
// [0. User defined M commands ]:
1684+
if(command_words.M10 && gc_block.user_mcode) {
1685+
1686+
user_words.mask = gc_block.words.mask;
1687+
if((int_value = (uint_fast16_t)hal.user_mcode.validate(&gc_block, &gc_block.words)))
1688+
FAIL((status_code_t)int_value);
1689+
user_words.mask ^= gc_block.words.mask; // Flag "taken" words for execution
1690+
1691+
if(user_words.i)
1692+
ijk_words.i = Off;
1693+
if(user_words.j)
1694+
ijk_words.j = Off;
1695+
if(user_words.k)
1696+
ijk_words.k = Off;
1697+
1698+
axis_words.mask = 0;
1699+
}
1700+
16831701
// [1. Comments ]: MSG's may be supported by driver layer. Comment handling performed by protocol.
16841702

16851703
// [2. Set feed rate mode ]: G93 F word missing with G1,G2/3 active, implicitly or explicitly. Feed rate
@@ -1736,7 +1754,7 @@ status_code_t gc_execute_block (char *block)
17361754

17371755
// [4. Set spindle speed and address spindle ]: S or D is negative (done.)
17381756
if(gc_block.words.$) {
1739-
bool single_spindle_only = (gc_block.words.s && !user_words.s) ||
1757+
bool single_spindle_only = gc_block.words.s ||
17401758
(command_words.G0 && (gc_block.modal.motion == MotionMode_SpindleSynchronized ||
17411759
gc_block.modal.motion == MotionMode_RigidTapping ||
17421760
gc_block.modal.motion == MotionMode_Threading)) ||
@@ -1779,11 +1797,11 @@ status_code_t gc_execute_block (char *block)
17791797
gc_state.modal.spindle.rpm_mode = gc_block.modal.spindle.rpm_mode;
17801798
}
17811799

1782-
spindle_event = gc_block.words.s && !user_words.s;
1800+
spindle_event = gc_block.words.s;
17831801

1784-
if (!gc_block.words.s)
1802+
if(!gc_block.words.s)
17851803
gc_block.values.s = gc_state.modal.spindle.rpm_mode == SpindleSpeedMode_RPM ? gc_state.spindle.rpm : gc_state.spindle.hal->param->css.max_rpm;
1786-
else if(!user_words.s && gc_state.modal.spindle.rpm_mode == SpindleSpeedMode_CSS) {
1804+
else if(gc_state.modal.spindle.rpm_mode == SpindleSpeedMode_CSS) {
17871805
// Unsure what to do about S values when in SpindleSpeedMode_CSS - ignore? For now use it to (re)calculate surface speed.
17881806
// Reinsert commented out code above if this is removed!!
17891807
gc_block.values.s *= (gc_block.modal.units_imperial ? MM_PER_INCH * 12.0f : 1000.0f); // convert surface speed to mm/min
@@ -1796,9 +1814,9 @@ status_code_t gc_execute_block (char *block)
17961814
if(set_tool) { // M61
17971815
if(!gc_block.words.q)
17981816
FAIL(Status_GcodeValueWordMissing);
1799-
if (floorf(gc_block.values.q) - gc_block.values.q != 0.0f)
1817+
if(!isintf(gc_block.values.q))
18001818
FAIL(Status_GcodeCommandValueNotInteger);
1801-
if ((uint32_t)gc_block.values.q > (grbl.tool_table.n_tools ? grbl.tool_table.n_tools : MAX_TOOL_NUMBER))
1819+
if((uint32_t)gc_block.values.q > (grbl.tool_table.n_tools ? grbl.tool_table.n_tools : MAX_TOOL_NUMBER))
18021820
FAIL(Status_GcodeIllegalToolTableEntry);
18031821

18041822
gc_block.values.t = (uint32_t)gc_block.values.q;
@@ -1815,7 +1833,7 @@ status_code_t gc_execute_block (char *block)
18151833
}
18161834
}
18171835
#endif
1818-
} else if (!gc_block.words.t)
1836+
} else if(!gc_block.words.t)
18191837
gc_block.values.t = gc_state.tool_pending;
18201838

18211839
if(command_words.M10 && port_command) {
@@ -1952,15 +1970,6 @@ status_code_t gc_execute_block (char *block)
19521970
}
19531971
}
19541972

1955-
// [9a. User defined M commands ]:
1956-
if (command_words.M10 && gc_block.user_mcode) {
1957-
user_words.mask = gc_block.words.mask;
1958-
if((int_value = (uint_fast16_t)hal.user_mcode.validate(&gc_block, &gc_block.words)))
1959-
FAIL((status_code_t)int_value);
1960-
user_words.mask ^= gc_block.words.mask; // Flag "taken" words for execution
1961-
axis_words.mask = ijk_words.mask = 0;
1962-
}
1963-
19641973
// [10. Dwell ]: P value missing. NOTE: See below.
19651974
if (gc_block.non_modal_command == NonModal_Dwell) {
19661975
if (!gc_block.words.p)
@@ -3071,7 +3080,7 @@ status_code_t gc_execute_block (char *block)
30713080
}
30723081
}
30733082

3074-
if(!user_words.s && ((gc_state.spindle.rpm != gc_block.values.s) || gc_parser_flags.spindle_force_sync)) {
3083+
if(gc_state.spindle.rpm != gc_block.values.s || gc_parser_flags.spindle_force_sync) {
30753084
if(gc_state.modal.spindle.state.on && !gc_parser_flags.laser_is_motion) {
30763085
if(gc_block.spindle) {
30773086
gc_block.spindle->param->rpm = gc_block.values.s;
@@ -3215,7 +3224,7 @@ status_code_t gc_execute_block (char *block)
32153224
bool spindle_ok = false;
32163225
if(gc_block.spindle) {
32173226
if(grbl.on_spindle_programmed)
3218-
grbl.on_spindle_programmed(gc_block.spindle, gc_block.modal.spindle.state, plan_data.spindle.rpm, gc_block.modal.spindle.rpm_mode);
3227+
grbl.on_spindle_programmed(gc_block.spindle, gc_block.modal.spindle.state, plan_data.spindle.rpm, gc_block.modal.spindle.rpm_mode);
32193228
if((spindle_ok = spindle_sync(gc_block.spindle, gc_block.modal.spindle.state, plan_data.spindle.rpm)))
32203229
gc_block.spindle->param->state = gc_block.modal.spindle.state;
32213230
} else {
@@ -3224,7 +3233,7 @@ status_code_t gc_execute_block (char *block)
32243233
if(spindle_is_enabled(--idx)) {
32253234
spindle_ptrs_t *spindle = spindle_get(idx);
32263235
if(grbl.on_spindle_programmed)
3227-
grbl.on_spindle_programmed(spindle, gc_block.modal.spindle.state, plan_data.spindle.rpm, gc_block.modal.spindle.rpm_mode);
3236+
grbl.on_spindle_programmed(spindle, gc_block.modal.spindle.state, plan_data.spindle.rpm, gc_block.modal.spindle.rpm_mode);
32283237
if(spindle_sync(spindle, gc_block.modal.spindle.state, plan_data.spindle.rpm))
32293238
spindle->param->state = gc_block.modal.spindle.state;
32303239
else

grbl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
#else
4343
#define GRBL_VERSION "1.1f"
4444
#endif
45-
#define GRBL_BUILD 20240801
45+
#define GRBL_BUILD 20240812
4646

4747
#define GRBL_URL "https://github.com/grblHAL"
4848

modbus.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#define _MODBUS_H_
2626

2727
#ifndef MODBUS_MAX_ADU_SIZE
28-
#define MODBUS_MAX_ADU_SIZE 10
28+
#define MODBUS_MAX_ADU_SIZE 12
2929
#endif
3030
#ifndef MODBUS_QUEUE_LENGTH
3131
#define MODBUS_QUEUE_LENGTH 8

report.c

+68-3
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,16 @@ static void report_help_message (void)
333333
hal.stream.write("[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H $B ~ ! ? ctrl-x]" ASCII_EOL);
334334
}
335335

336+
// Prints plugin info.
337+
void report_plugin (const char *name, const char *version)
338+
{
339+
hal.stream.write("[PLUGIN:");
340+
hal.stream.write(name);
341+
hal.stream.write(" v");
342+
hal.stream.write(version);
343+
hal.stream.write("]" ASCII_EOL);
344+
}
345+
336346
static bool report_group_settings (const setting_group_detail_t *groups, const uint_fast8_t n_groups, char *args)
337347
{
338348
bool found = false;
@@ -1088,7 +1098,6 @@ void report_build_info (char *line, bool extended)
10881098
}
10891099
}
10901100

1091-
10921101
// Prints the character string line grblHAL has received from the user, which has been pre-parsed,
10931102
// and has been sent into protocol_execute_line() routine to be executed by grblHAL.
10941103
void report_echo_line_received (char *line)
@@ -1098,6 +1107,15 @@ void report_echo_line_received (char *line)
10981107
hal.stream.write("]" ASCII_EOL);
10991108
}
11001109

1110+
#if N_SYS_SPINDLE == 1 && N_SPINDLE > 1
1111+
1112+
static void report_spindle_num (spindle_info_t *spindle, void *data)
1113+
{
1114+
if(spindle->id == *((spindle_id_t *)data))
1115+
hal.stream.write_all(appendbuf(2, "|S:", uitoa((uint32_t)spindle->num)));
1116+
}
1117+
1118+
#endif
11011119

11021120
// Prints real-time data. This function grabs a real-time snapshot of the stepper subprogram
11031121
// and the actual location of the CNC machine. Users may change the following function to their
@@ -1246,7 +1264,7 @@ void report_realtime_status (void)
12461264

12471265
#elif N_SPINDLE > 1
12481266
if(report.spindle_id)
1249-
hal.stream.write_all(appendbuf(2, "|S:", uitoa((uint32_t)spindle_0->id)));
1267+
spindle_enumerate_spindles(report_spindle_num, &spindle_0->id);
12501268
#endif
12511269

12521270
if(settings.status_report.pin_state) {
@@ -2516,9 +2534,56 @@ static void report_spindle (spindle_info_t *spindle, void *data)
25162534
}
25172535
}
25182536

2537+
#if N_SPINDLE > 1
2538+
2539+
typedef struct {
2540+
uint32_t idx;
2541+
uint32_t n_spindles;
2542+
spindle_info_t *spindles;
2543+
} spindle_rdata_t;
2544+
2545+
static void get_spindles (spindle_info_t *spindle, void *data)
2546+
{
2547+
memcpy(&((spindle_rdata_t *)data)->spindles[((spindle_rdata_t *)data)->idx++], spindle, sizeof(spindle_info_t));
2548+
}
2549+
2550+
static int cmp_spindles (const void *a, const void *b)
2551+
{
2552+
uint32_t key_a = ((spindle_info_t *)a)->num == -1 ? ((((spindle_info_t *)a)->hal->type + 1) << 8) | ((spindle_info_t *)a)->id : ((spindle_info_t *)a)->num,
2553+
key_b = ((spindle_info_t *)b)->num == -1 ? ((((spindle_info_t *)b)->hal->type + 1) << 8) | ((spindle_info_t *)b)->id : ((spindle_info_t *)b)->num;
2554+
2555+
return key_a - key_b;
2556+
}
2557+
2558+
#endif
2559+
25192560
status_code_t report_spindles (bool machine_readable)
25202561
{
2521-
if(!spindle_enumerate_spindles(report_spindle, (void *)machine_readable) && !machine_readable)
2562+
bool has_spindles;
2563+
2564+
#if N_SPINDLE > 1
2565+
2566+
spindle_rdata_t spindle_data = {0};
2567+
2568+
if((spindle_data.spindles = malloc(N_SPINDLE * sizeof(spindle_info_t)))) {
2569+
2570+
has_spindles = spindle_enumerate_spindles(get_spindles, &spindle_data);
2571+
2572+
spindle_data.n_spindles = spindle_data.idx;
2573+
2574+
qsort(spindle_data.spindles, spindle_data.n_spindles, sizeof(spindle_info_t), cmp_spindles);
2575+
for(spindle_data.idx = 0; spindle_data.idx < spindle_data.n_spindles; spindle_data.idx++)
2576+
report_spindle(&spindle_data.spindles[spindle_data.idx], (void *)machine_readable);
2577+
2578+
free(spindle_data.spindles);
2579+
2580+
} else
2581+
2582+
#endif
2583+
2584+
has_spindles = spindle_enumerate_spindles(report_spindle, (void *)machine_readable);
2585+
2586+
if(!has_spindles && !machine_readable)
25222587
hal.stream.write("No spindles registered." ASCII_EOL);
25232588

25242589
return Status_OK;

report.h

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ void report_warning (void *message);
5252
// Prints Grbl help.
5353
status_code_t report_help (char *args);
5454

55+
void report_plugin (const char *name, const char *version);
56+
5557
// Prints Grbl settings
5658
void report_grbl_settings (bool all, void *data);
5759

0 commit comments

Comments
 (0)