diff --git a/README.md b/README.md
index 02189ad..62f502f 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 20230926, see the [changelog](changelog.md) for details.
+Latest build date is 20231005, see the [changelog](changelog.md) for details.
__NOTE:__ A settings reset will be performed on an update of builds earlier than 20230125. Backup and restore of settings is recommended.
__IMPORTANT!__ A new setting has been introduced for ganged axes motors in build 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 4c7e76b..72f3df6 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,27 @@
## grblHAL changelog
+Build 20231005
+
+Core:
+
+* Extended secondary stepper driver code and improved debug stream handling.
+
+Drivers:
+
+* iMXRT1062: refactored timer code, improved step injection support.
+
+* STM32F4xx: fixed typo in Trinamic soft serial code.
+
+Plugins:
+
+* Plasma: changed to use rapid rate for THC cutter motion.
+
+* Keypad: increased delay before probing display I2C address to 510ms, [issue #8](https://github.com/grblHAL/Plugin_keypad/issues/8).
+
+* Spindle: added experimental support for stepper spindle. Note: not yet enabled for compilation.
+
+---
+
Build 20231002
Core:
diff --git a/grbl.h b/grbl.h
index 2445e0b..bdb9c0f 100644
--- a/grbl.h
+++ b/grbl.h
@@ -42,7 +42,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
-#define GRBL_BUILD 20231002
+#define GRBL_BUILD 20231005
#define GRBL_URL "https://github.com/grblHAL"
diff --git a/spindle_control.h b/spindle_control.h
index 1a96ba3..634c95b 100644
--- a/spindle_control.h
+++ b/spindle_control.h
@@ -82,7 +82,8 @@ typedef enum {
SpindleType_Basic, //!< 1 - on/off + optional direction
SpindleType_VFD, //!< 2
SpindleType_Solenoid, //!< 3
- SpindleType_Null, //!< 4
+ SpindleType_Stepper, //!< 4
+ SpindleType_Null, //!< 5
} spindle_type_t;
typedef enum {
diff --git a/stepper2.c b/stepper2.c
index ba32d2c..440c4be 100644
--- a/stepper2.c
+++ b/stepper2.c
@@ -29,100 +29,211 @@
#include "stepper2.h"
-#define SETDELAY(delay) ((delay) > 65535 ? 65535 : (delay))
-
typedef enum {
State_Idle = 0,
State_Accel,
State_Run,
+ State_RunInfinite,
+ State_DecelTo,
State_Decel
} st2_state_t;
struct st2_motor {
uint_fast8_t idx;
axes_signals_t axis;
- volatile int32_t position; // absolute step number
+ volatile int64_t position; // absolute step number
+ position_t ptype; //
+ st2_state_t state; // state machine state
uint32_t move; // total steps to move
uint32_t step_no; // progress of move
uint32_t step_run; //
uint32_t step_down; // start of down-ramp
- uint32_t c32; // 24.8 fixed point delay count
+ uint64_t c64; // 24.16 fixed point delay count
uint32_t delay; // integer delay count
uint32_t first_delay; // integer delay count
uint16_t min_delay; // integer delay count
- int16_t denom; // 4.n+1 in ramp algo
- uint16_t n; // accel/decel steps
- uint16_t speed; // speed mm/s
- uint16_t accel; // acceleration m/s/s
- st2_state_t state; // state machine state
+ int32_t denom; // 4.n+1 in ramp algo
+ uint32_t n; // accel/decel steps
+ float speed; // speed steps/s
+ float prev_speed; // speed steps/s
+ float acceleration; // acceleration steps/s^2
axes_signals_t dir; // current direction
uint32_t next_step;
+ st2_motor_t *next;
};
+static st2_motor_t *motors = NULL;
+static settings_changed_ptr settings_changed;
+static on_reset_ptr on_reset;
+
+static void st_motor_config (st2_motor_t *motor)
+{
+ motor->acceleration = settings.axis[motor->idx].acceleration * settings.axis[motor->idx].steps_per_mm / 3600.0f;
+ motor->first_delay = (uint32_t)(0.676f * sqrtf(2.0f / motor->acceleration) * 1000000.0f);
+}
+
+static void st2_reset (void)
+{
+ st2_motor_t *motor = motors;
+
+ while(motor) {
+ motor->state = State_Idle;
+ motor = motor->next;
+ }
+}
+
+static void st2_settings_changed (settings_t *settings, settings_changed_flags_t changed)
+{
+ st2_motor_t *motor = motors;
+
+ settings_changed(settings, changed);
+
+ while(motor) {
+ st_motor_config(motor);
+ motor = motor->next;
+ }
+}
+
st2_motor_t *st2_motor_init (uint_fast8_t axis_idx)
{
- st2_motor_t *motor;
+ st2_motor_t *motor, *new = motors;
if((motor = malloc(sizeof(st2_motor_t)))) {
+
memset(motor, 0, sizeof(st2_motor_t));
motor->idx = axis_idx;
motor->axis.mask = 1 << axis_idx;
- st2_motor_set_speed(motor, settings.axis[axis_idx].max_rate);
+
+ st_motor_config(motor);
+
+ if(new == NULL) {
+ motors = motor;
+
+ settings_changed = hal.settings_changed;
+ hal.settings_changed = st2_settings_changed;
+
+ on_reset = grbl.on_reset;
+ grbl.on_reset = st2_reset;
+
+ } else {
+ while(new->next)
+ new = new->next;
+ new->next = motor;
+ }
}
return motor;
}
-uint32_t st2_motor_set_speed (st2_motor_t *motor, uint32_t speed)
+float st2_motor_set_speed (st2_motor_t *motor, float speed)
{
- uint32_t prev_speed = (uint32_t)motor->speed;
- float acceleration = settings.axis[motor->idx].acceleration * settings.axis[motor->idx].steps_per_mm / 3600.0f;
+ motor->speed = speed > settings.axis[motor->idx].max_rate ? settings.axis[motor->idx].max_rate : speed;
+ motor->speed *= settings.axis[motor->idx].steps_per_mm / 60.0f;
- motor->speed = speed > settings.axis[motor->idx].max_rate ? settings.axis[motor->idx].max_rate : speed;
- motor->speed *= settings.axis[motor->idx].steps_per_mm;
- motor->min_delay = 1000000.0f / speed;
- motor->first_delay = (uint32_t)(0.676f * sqrtf(2.0f / acceleration) * 1000000.0f);
- motor->n = (uint32_t)(speed * speed) / (2.0f * acceleration);
+ if(motor->speed == motor->prev_speed)
+ return motor->speed;
+
+ motor->min_delay = (uint32_t)(1000000.0f / motor->speed);
+ motor->n = (uint32_t)(motor->speed * motor->speed) / (2.0f * motor->acceleration);
if(motor->n == 0)
motor->n = 1;
+ if(motor->state != State_Idle) {
+
+ int32_t pn = motor->n - ((motor->denom - 1) >> 2);
+
+ if(pn == 0)
+ return motor->speed;
+
+#ifdef DEBUGOUT
+ debug_writeln("!!");
+ debug_writeln(uitoa(motor->state));
+ debug_writeln(ftoa(motor->prev_speed, 2));
+ debug_writeln(ftoa(motor->speed, 2));
+ debug_writeln(uitoa((motor->denom - 1) >> 2));
+ debug_writeln(uitoa(motor->n));
+ debug_write(pn < 0 ? "-" : "+");
+ debug_writeln(uitoa(pn < 0 ? -pn : pn));
+ debug_writeln(uitoa(motor->denom));
+#endif
+
+ if(motor->speed > motor->prev_speed) {
+ if(motor->state == State_Accel)
+ motor->step_run += pn;
+ else {
+ motor->step_run = motor->step_no + pn;
+ motor->state = State_Accel;
+ }
+ } else {
+ if(motor->speed == 0.0f)
+ motor->state = State_Decel;
+ if(motor->state != State_Decel) {
+ motor->step_run = motor->step_no - pn;
+ motor->state = State_DecelTo;
+ }
+ }
+ }
+
+ motor->prev_speed = motor->speed;
+
if(motor->first_delay < motor->min_delay)
motor->first_delay = motor->min_delay;
- return prev_speed;
+ return motor->prev_speed;
}
bool st2_motor_move (st2_motor_t *motor, const float move, const float speed, position_t type)
{
bool dir = move < 0.0f;
- st2_motor_set_speed(motor, speed);
+ if(speed == 0.0f)
+ return false;
if((motor->dir.mask == 0) != dir)
motor->dir.mask = dir ? 0 : motor->axis.mask;
+ motor->ptype = type;
+
switch(type) {
case Stepper2_Steps:
motor->move = (uint32_t)fabs((int32_t)move);
break;
+ case Stepper2_InfiniteSteps:
+ motor->move = (uint32_t)fabs((int32_t)move);
+ break;
+
case Stepper2_mm:
motor->move = (uint32_t)fabs(move * settings.axis[motor->idx].steps_per_mm);
+
break;
}
+ st2_motor_set_speed(motor, speed);
+
motor->step_no = 0; // step counter
- if(motor->move == 1) {
+ if(type == Stepper2_InfiniteSteps) {
+
+ motor->state = State_Accel;
+ motor->step_run = motor->n;
+ motor->step_down = motor->n + 1;
+ motor->delay = motor->first_delay;
+ motor->c64 = ((uint32_t)motor->delay) << 16; // keep delay in 24.16 fixed-point format for ramp calcs
+ motor->denom = 1; // 4.n + 1, n = 0
+ motor->next_step = hal.get_micros();
+ } else if(motor->move == 1) {
motor->step_run = 1;
motor->step_down = 1;
motor->delay = motor->first_delay;
- motor->c32 = ((uint32_t)motor->delay) << 8; // keep delay in 24.8 fixed-point format for ramp calcs
+ motor->c64 = ((uint32_t)motor->delay) << 8; // keep delay in 24.16 fixed-point format for ramp calcs
motor->denom = 1; // 4.n + 1, n = 0
+ hal.stepper.output_step(motor->axis, motor->dir);
+
} else if(motor->move != 0) {
motor->state = State_Accel;
@@ -131,19 +242,50 @@ bool st2_motor_move (st2_motor_t *motor, const float move, const float speed, po
motor->step_run = motor->n;
motor->step_down = motor->move - motor->step_run;
motor->delay = motor->first_delay;
- motor->c32 = ((uint32_t)motor->delay) << 8; // keep delay in 24.8 fixed-point format for ramp calcs
+ motor->c64 = ((uint32_t)motor->delay) << 8; // keep delay in 24.16 fixed-point format for ramp calcs
motor->denom = 1; // 4.n + 1, n = 0
motor->next_step = hal.get_micros();
}
- hal.stepper.output_step(motor->axis, motor->dir);
+
+#ifdef DEBUGOUT
+ uint32_t nn = motor->n;
+ float cn = motor->first_delay;
+ do {
+ cn -= (2.0f * cn) / (4.0f * nn + 1);
+ } while(--nn);
+
+ debug_writeln("move");
+ debug_writeln(ftoa(speed, 2));
+ debug_writeln(ftoa(settings.axis[motor->idx].steps_per_mm, 3));
+ debug_writeln(uitoa(motor->n));
+ debug_writeln(uitoa(motor->delay));
+ debug_writeln(uitoa(motor->min_delay));
+ debug_writeln(ftoa(cn, 2));
+ debug_writeln(ftoa(motor->speed, 2));
+#endif
return true;
}
+int64_t st2_get_position (st2_motor_t *motor)
+{
+ return motor->position;
+}
+
+bool st2_set_position (st2_motor_t *motor, int64_t position)
+{
+ if(motor->state == State_Idle)
+ motor->position = position;
+
+ return motor->state == State_Idle;
+}
+
bool st2_motor_run (st2_motor_t *motor)
{
- if(motor->state == State_Idle || hal.get_micros() - motor->next_step < motor->delay)
+ uint32_t t = hal.get_micros();
+
+ if(motor->state == State_Idle || t - motor->next_step < motor->delay)
return motor->state != State_Idle;
// output step;
@@ -156,51 +298,83 @@ bool st2_motor_run (st2_motor_t *motor)
motor->position++;
motor->step_no++;
- motor->next_step += motor->delay;
switch(motor->state) {
case State_Accel:
- if (motor->step_no == motor->step_run) {
-
- motor->state = motor->step_run == motor->step_down ? State_Decel : State_Run;
+ if(motor->step_no == motor->step_run) {
+ motor->state = motor->step_run == motor->step_down ? State_Decel : (motor->ptype == Stepper2_InfiniteSteps ? State_RunInfinite : State_Run);
motor->denom -= 2;
- if(motor->state == State_Run)
+ if(motor->state == State_Run || motor->state == State_RunInfinite)
motor->delay = motor->min_delay;
-
} else {
-
motor->denom += 4;
- motor->c32 -= (motor->c32 << 1) / motor->denom; // ramp algorithm
- motor->delay = (motor->c32 + 128) >> 8; // round 24.8 format -> int16
-
- if (motor->delay <= motor->min_delay) { // go to constant speed?
- motor->denom -= 6;
- motor->state = State_Run;
+ motor->c64 -= (motor->c64 << 1) / motor->denom; // ramp algorithm
+ motor->delay = (motor->c64 + 32768) >> 16; // round 24.16 format -> int16
+ if (motor->delay < motor->min_delay) { // go to constant speed?
+ motor->denom -= 6; // causes issues with speed override for infinite moves
+ motor->state = motor->ptype == Stepper2_InfiniteSteps ? State_RunInfinite : State_Run;
motor->step_down = motor->move - motor->step_no;
motor->delay = motor->min_delay;
}
}
-
break;
case State_Run:
- if (motor->step_no == motor->step_down)
+ if(motor->step_no == motor->step_down)
motor->state = State_Decel;
break;
case State_Decel:
- if (motor->denom < 2) // done?
+ if(motor->denom < 2) { // done?
motor->state = State_Idle;
-
- else {
-
- motor->c32 += (motor->c32 << 1) / motor->denom; // ramp algorithm
- motor->delay = (motor->c32 - 128) >> 8; // round 24.8 format -> int16
+ motor->prev_speed = 0.0f;
+ motor->n = 0;
+#ifdef DEBUGOUT
+ debug_writeln(uitoa(motor->position));
+#endif
+ } else {
+ motor->c64 += (motor->c64 << 1) / motor->denom; // ramp algorithm
+ motor->delay = (motor->c64 - 32768) >> 16; // round 24.16 format -> int16
motor->denom -= 4;
}
break;
+ case State_DecelTo:
+ if(motor->step_no != motor->step_run) {
+ motor->c64 += (motor->c64 << 1) / motor->denom; // ramp algorithm
+ motor->delay = (motor->c64 - 32768) >> 16; // round 24.16 format -> int16
+ motor->denom -= 4;
+ } else
+ motor->state = motor->ptype == Stepper2_InfiniteSteps ? State_RunInfinite : State_Run;
+ break;
+
+ default:
+ break;
+ }
+ motor->next_step = t;
+
+ return motor->state != State_Idle;
+}
+
+bool st2_motor_stop (st2_motor_t *motor)
+{
+ switch(motor->state) {
+
+ case State_Accel:
+ motor->step_no = motor->step_down - 1;
+ motor->step_run = motor->step_down;
+ break;
+
+ case State_Run:
+ motor->step_no = motor->step_down - 1;
+ break;
+
+ case State_RunInfinite:
+ case State_DecelTo:
+ motor->state = State_Decel;
+ break;
+
default:
break;
}
@@ -208,18 +382,12 @@ bool st2_motor_run (st2_motor_t *motor)
return motor->state != State_Idle;
}
-bool st2_motor_stop (st2_motor_t *motor)
-{
- if(motor->state == State_Accel) {
- motor->step_no = motor->step_down - 1;
- motor->step_run = motor->step_down;
- } else if(motor->state == State_Run)
- motor->step_no = motor->step_down - 1;
-
- return true;
-}
-
bool st2_motor_running (st2_motor_t *motor)
{
return motor->state != State_Idle;
}
+
+bool st2_motor_cruising (st2_motor_t *motor)
+{
+ return motor->state == State_Run || motor->state == State_RunInfinite;
+}
diff --git a/stepper2.h b/stepper2.h
index b0e87f6..45d1184 100644
--- a/stepper2.h
+++ b/stepper2.h
@@ -24,6 +24,7 @@
typedef enum {
Stepper2_Steps = 0,
+ Stepper2_InfiniteSteps,
Stepper2_mm
} position_t;
@@ -31,8 +32,11 @@ struct st2_motor; // members defined in stepper2.c
typedef struct st2_motor st2_motor_t;
st2_motor_t *st2_motor_init (uint_fast8_t axis_idx);
-uint32_t st2_motor_set_speed (st2_motor_t *motor, uint32_t speed);
+float st2_motor_set_speed (st2_motor_t *motor, float speed);
bool st2_motor_move (st2_motor_t *motor, const float move, const float speed, position_t type);
bool st2_motor_run (st2_motor_t *motor);
bool st2_motor_running (st2_motor_t *motor);
+bool st2_motor_cruising (st2_motor_t *motor);
bool st2_motor_stop (st2_motor_t *motor);
+int64_t st2_get_position (st2_motor_t *motor);
+bool st2_set_position (st2_motor_t *motor, int64_t position);
diff --git a/stream.c b/stream.c
index fe61979..0105f94 100644
--- a/stream.c
+++ b/stream.c
@@ -604,7 +604,8 @@ void debug_write (const char *s)
{
if(dbg_write) {
dbg_write(s);
- while(hal.debug.get_tx_buffer_count()); // Wait until message is delivered
+ while(hal.debug.get_tx_buffer_count()) // Wait until message is delivered
+ grbl.on_execute_realtime(state_get());
}
}
@@ -613,7 +614,8 @@ void debug_writeln (const char *s)
if(dbg_write) {
dbg_write(s);
dbg_write(ASCII_EOL);
- while(hal.debug.get_tx_buffer_count()); // Wait until message is delivered
+ while(hal.debug.get_tx_buffer_count()) // Wait until message is delivered
+ grbl.on_execute_realtime(state_get());
}
}
@@ -630,7 +632,7 @@ static bool debug_claim_stream (io_stream_properties_t const *stream)
hal.debug.write = debug_write;
if(hal.periph_port.set_pin_description)
- hal.periph_port.set_pin_description(Output_TX, hal.debug.instance == 0 ? PinGroup_UART : PinGroup_UART2, "Debug out");
+ hal.periph_port.set_pin_description(Output_TX, (pin_group_t)(PinGroup_UART + hal.debug.instance), "Debug out");
}
}