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"); } }