1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-09-01 18:32:37 +02:00

Baby steps toward better steps

Created beginLowLatency() and endLowLatency() to
eliminate switch_stepper()
This commit is contained in:
Mitch Bradley
2021-07-05 12:26:55 -10:00
parent 31bc285bf9
commit 8dd1de3de2
7 changed files with 57 additions and 46 deletions

View File

@@ -503,7 +503,7 @@ static void IRAM_ATTR i2sOutTask(void* parameter) {
} else if (i2s_out_pulser_status == WAITING) { } else if (i2s_out_pulser_status == WAITING) {
if (dma_desc->qe.stqe_next == NULL) { if (dma_desc->qe.stqe_next == NULL) {
// Tail of the DMA descriptor found // Tail of the DMA descriptor found
// I2S TX module has alrewdy stopped by ISR // I2S TX module has already stopped by ISR
i2s_out_stop(); i2s_out_stop();
i2s_clear_o_dma_buffers(0); // 0 for static I2S control mode (right ch. data is always 0) i2s_clear_o_dma_buffers(0); // 0 for static I2S control mode (right ch. data is always 0)
// You need to set the status before calling i2s_out_start() // You need to set the status before calling i2s_out_start()
@@ -546,6 +546,7 @@ void IRAM_ATTR i2s_out_delay() {
} else { } else {
// Just wait until the data now registered in the DMA descripter // Just wait until the data now registered in the DMA descripter
// is reflected in the I2S TX module via FIFO. // is reflected in the I2S TX module via FIFO.
// XXX perhaps just wait until I2SO.conf1.tx_start == 0
delay(I2S_OUT_DELAY_MS); delay(I2S_OUT_DELAY_MS);
} }
I2S_OUT_PULSER_EXIT_CRITICAL(); I2S_OUT_PULSER_EXIT_CRITICAL();

View File

@@ -133,6 +133,7 @@ namespace Machine {
auto wait_direction = config->_directionDelayMicroSeconds; auto wait_direction = config->_directionDelayMicroSeconds;
if (wait_direction > 0) { if (wait_direction > 0) {
// stepping->turnaround(wait_direction);
// Stepper drivers need some time between changing direction and doing a pulse. // Stepper drivers need some time between changing direction and doing a pulse.
switch (config->_stepType) { switch (config->_stepType) {
case stepper_id_t::ST_I2S_STREAM: case stepper_id_t::ST_I2S_STREAM:
@@ -213,6 +214,35 @@ namespace Machine {
return SIZE_MAX; return SIZE_MAX;
} }
// Wait for motion to complete; the axes can still be moving
// after the data has been sent to the stepping engine, due
// to queuing delays.
void Axes::synchronize() {
if (config->_stepType == ST_I2S_STREAM) {
// XXX instead of a delay, we could sense when the DMA and
// FIFO have drained. It might be as simple as waiting for
// I2SO.conf1.tx_start == 0, while yielding.
delay_ms(I2S_OUT_DELAY_MS);
}
}
void Axes::beginLowLatency() {
_switchedStepper = config->_stepType == ST_I2S_STREAM;
if (_switchedStepper) {
config->_stepType = ST_I2S_STATIC;
}
}
void Axes::endLowLatency() {
if (_switchedStepper) {
if (i2s_out_get_pulser_status() != PASSTHROUGH) {
// Called during streaming. Stop streaming.
debug_serial("Stop the I2S streaming and switch to the passthrough mode.");
i2s_out_set_passthrough();
i2s_out_delay(); // Wait for a change in mode.
}
config->_stepType = ST_I2S_STREAM;
}
}
// Configuration helpers: // Configuration helpers:
void Axes::group(Configuration::HandlerBase& handler) { void Axes::group(Configuration::HandlerBase& handler) {

View File

@@ -30,6 +30,8 @@ namespace Machine {
static const int MAX_NUMBER_AXIS = 6; static const int MAX_NUMBER_AXIS = 6;
static constexpr const char* _names = "XYZABC"; static constexpr const char* _names = "XYZABC";
bool _switchedStepper = false;
public: public:
Axes(); Axes();
@@ -65,6 +67,10 @@ namespace Machine {
return false; return false;
} }
void synchronize(); // Wait for motion to complete
void beginLowLatency();
void endLowLatency();
// These are used for setup and to talk to the motors as a group. // These are used for setup and to talk to the motors as a group.
void init(); void init();
void read_settings(); // more like 'after read settings, before init'. Oh well... void read_settings(); // more like 'after read settings, before init'. Oh well...

View File

@@ -274,12 +274,6 @@ bool mc_dwell(int32_t milliseconds) {
return delay_msec(milliseconds, DwellMode::Dwell); return delay_msec(milliseconds, DwellMode::Dwell);
} }
inline void RESTORE_STEPPER(int save_stepper) {
if (save_stepper == ST_I2S_STREAM && config->_stepType != ST_I2S_STREAM) {
Stepper::switch_mode(ST_I2S_STREAM); /* Put the stepper back on. */
}
}
// Perform homing cycle to locate and set machine zero. Only '$H' executes this command. // Perform homing cycle to locate and set machine zero. Only '$H' executes this command.
// NOTE: There should be no motions in the buffer and Grbl must be in an idle state before // NOTE: There should be no motions in the buffer and Grbl must be in an idle state before
// executing the homing cycle. This prevents incorrect buffered plans after homing. // executing the homing cycle. This prevents incorrect buffered plans after homing.
@@ -337,10 +331,7 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
int save_stepper = config->_stepType; /* remember the stepper */ int save_stepper = config->_stepType; /* remember the stepper */
// Switch stepper mode to the I2S static (realtime mode) config->_axes->beginLowLatency();
if (save_stepper == ST_I2S_STREAM) {
Stepper::switch_mode(ST_I2S_STATIC); /* Change the stepper to reduce the delay for accurate probing. */
}
// Initialize probing control variables // Initialize probing control variables
bool is_probe_away = bit_istrue(parser_flags, GCParserProbeIsAway); bool is_probe_away = bit_istrue(parser_flags, GCParserProbeIsAway);
@@ -352,8 +343,8 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
if (config->_probe->tripped()) { if (config->_probe->tripped()) {
sys_rt_exec_alarm = ExecAlarm::ProbeFailInitial; sys_rt_exec_alarm = ExecAlarm::ProbeFailInitial;
protocol_execute_realtime(); protocol_execute_realtime();
RESTORE_STEPPER(save_stepper); // Switch the stepper mode to the previous mode config->_axes->endLowLatency();
return GCUpdatePos::None; // Nothing else to do but bail. return GCUpdatePos::None; // Nothing else to do but bail.
} }
// Setup and queue probing motion. Auto cycle-start should not start the cycle. // Setup and queue probing motion. Auto cycle-start should not start the cycle.
info_serial("Found"); info_serial("Found");
@@ -365,13 +356,12 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
do { do {
protocol_execute_realtime(); protocol_execute_realtime();
if (sys.abort) { if (sys.abort) {
RESTORE_STEPPER(save_stepper); // Switch the stepper mode to the previous mode config->_axes->endLowLatency();
return GCUpdatePos::None; // Check for system abort return GCUpdatePos::None; // Check for system abort
} }
} while (sys.state != State::Idle); } while (sys.state != State::Idle);
// Switch the stepper mode to the previous mode config->_axes->endLowLatency();
RESTORE_STEPPER(save_stepper);
// Probing cycle complete! // Probing cycle complete!
// Set state variables and error out, if the probe failed and cycle with error is enabled. // Set state variables and error out, if the probe failed and cycle with error is enabled.

View File

@@ -57,6 +57,7 @@ namespace Motors {
_dir_pin.setAttr(Pin::Attr::Output); _dir_pin.setAttr(Pin::Attr::Output);
// stepping->init(_step_pin);
if (config->_stepType == ST_RMT) { if (config->_stepType == ST_RMT) {
rmtConfig.rmt_mode = RMT_MODE_TX; rmtConfig.rmt_mode = RMT_MODE_TX;
rmtConfig.clk_div = 20; rmtConfig.clk_div = 20;

View File

@@ -272,16 +272,11 @@ Error home(int cycle) {
} }
sys.state = State::Homing; // Set system state variable sys.state = State::Homing; // Set system state variable
int save_stepper = config->_stepType; config->_axes->beginLowLatency();
if (save_stepper == ST_I2S_STREAM) {
Stepper::switch_mode(ST_I2S_STATIC);
}
mc_homing_cycle(cycle); mc_homing_cycle(cycle);
if (save_stepper == ST_I2S_STREAM && config->_stepType != ST_I2S_STREAM) { config->_axes->endLowLatency();
Stepper::switch_mode(ST_I2S_STREAM);
}
if (!sys.abort) { // Execute startup scripts after successful homing. if (!sys.abort) { // Execute startup scripts after successful homing.
sys.state = State::Idle; // Set to IDLE when complete. sys.state = State::Idle; // Set to IDLE when complete.

View File

@@ -348,17 +348,19 @@ static void IRAM_ATTR pulse_func() {
} }
} }
auto pulseMicros = config->_pulseMicroSeconds; // stepping->unStep(pulseMicros);
uint64_t endMicros;
switch (config->_stepType) { switch (config->_stepType) {
case ST_I2S_STREAM: case ST_I2S_STREAM:
// Generate the number of pulses needed to span pulse_microseconds // Generate the number of pulses needed to span pulse_microseconds
i2s_out_push_sample(pulseMicros); i2s_out_push_sample(config->_pulseMicroSeconds);
config->_axes->unstep(); config->_axes->unstep();
break; break;
case ST_I2S_STATIC: case ST_I2S_STATIC:
case ST_TIMED: case ST_TIMED:
endMicros = config->_pulseMicroSeconds + step_pulse_start_time;
// wait for step pulse time to complete...some time expired during code above // wait for step pulse time to complete...some time expired during code above
while (esp_timer_get_time() - step_pulse_start_time < pulseMicros) { while ((esp_timer_get_time() - endMicros) < 0) {
NOP(); // spin here until time to turn off step NOP(); // spin here until time to turn off step
} }
config->_axes->unstep(); config->_axes->unstep();
@@ -373,6 +375,7 @@ void Stepper::init() {
info_serial("Axis count %d", config->_axes->_numberAxis); info_serial("Axis count %d", config->_axes->_numberAxis);
info_serial("Step type:%s Pulse:%dus Dsbl Delay:%dus Dir Delay:%dus", info_serial("Step type:%s Pulse:%dus Dsbl Delay:%dus Dir Delay:%dus",
// stepping->name(),
stepTypes[config->_stepType].name, stepTypes[config->_stepType].name,
config->_pulseMicroSeconds, config->_pulseMicroSeconds,
config->_disableDelayMicroSeconds, config->_disableDelayMicroSeconds,
@@ -382,25 +385,6 @@ void Stepper::init() {
timerInit(); timerInit();
} }
void Stepper::switch_mode(stepper_id_t new_stepper) {
debug_serial("Switch stepper: %s -> %s", stepTypes[config->_stepType].name, stepTypes[new_stepper].name);
if (config->_stepType == new_stepper) {
// do not need to change
return;
}
if (config->_stepType == ST_I2S_STREAM) {
if (i2s_out_get_pulser_status() != PASSTHROUGH) {
// Called during streaming. Stop streaming.
debug_serial("Stop the I2S streaming and switch to the passthrough mode.");
i2s_out_set_passthrough();
i2s_out_delay(); // Wait for a change in mode.
}
}
config->_stepType = new_stepper;
}
// enabled. Startup init and limits call this function but shouldn't start the cycle. // enabled. Startup init and limits call this function but shouldn't start the cycle.
void Stepper::wake_up() { void Stepper::wake_up() {
//info_serial("st_wake_up"); //info_serial("st_wake_up");
@@ -415,6 +399,7 @@ void Stepper::wake_up() {
// Reset and clear stepper subsystem variables // Reset and clear stepper subsystem variables
void Stepper::reset() { void Stepper::reset() {
// Initialize stepper driver idle state. // Initialize stepper driver idle state.
// stepping->reset();
if (config->_stepType == ST_I2S_STREAM) { if (config->_stepType == ST_I2S_STREAM) {
i2s_out_reset(); i2s_out_reset();
} }
@@ -930,6 +915,7 @@ float Stepper::get_realtime_rate() {
// The argument is in units of ticks of the timer that generates ISRs // The argument is in units of ticks of the timer that generates ISRs
static void IRAM_ATTR timerWritePeriod(uint16_t timerTicks) { static void IRAM_ATTR timerWritePeriod(uint16_t timerTicks) {
// stepping->setPeriod(uint16_t timerTicks);
if (config->_stepType == ST_I2S_STREAM) { if (config->_stepType == ST_I2S_STREAM) {
// 1 tick = fTimers / fStepperTimer // 1 tick = fTimers / fStepperTimer
// Pulse ISR is called for each tick of alarm_val. // Pulse ISR is called for each tick of alarm_val.
@@ -956,6 +942,7 @@ static void IRAM_ATTR timerInit() {
} }
static void IRAM_ATTR timerStart() { static void IRAM_ATTR timerStart() {
// stepping->start();
if (config->_stepType == ST_I2S_STREAM) { if (config->_stepType == ST_I2S_STREAM) {
i2s_out_set_stepping(); i2s_out_set_stepping();
} else { } else {
@@ -965,6 +952,7 @@ static void IRAM_ATTR timerStart() {
} }
static void IRAM_ATTR timerStop() { static void IRAM_ATTR timerStop() {
// stepping->stop();
if (config->_stepType == ST_I2S_STREAM) { if (config->_stepType == ST_I2S_STREAM) {
i2s_out_set_passthrough(); i2s_out_set_passthrough();
} else if (stepTimer) { } else if (stepTimer) {