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) {
if (dma_desc->qe.stqe_next == NULL) {
// 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_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()
@@ -546,6 +546,7 @@ void IRAM_ATTR i2s_out_delay() {
} else {
// Just wait until the data now registered in the DMA descripter
// is reflected in the I2S TX module via FIFO.
// XXX perhaps just wait until I2SO.conf1.tx_start == 0
delay(I2S_OUT_DELAY_MS);
}
I2S_OUT_PULSER_EXIT_CRITICAL();

View File

@@ -133,6 +133,7 @@ namespace Machine {
auto wait_direction = config->_directionDelayMicroSeconds;
if (wait_direction > 0) {
// stepping->turnaround(wait_direction);
// Stepper drivers need some time between changing direction and doing a pulse.
switch (config->_stepType) {
case stepper_id_t::ST_I2S_STREAM:
@@ -213,6 +214,35 @@ namespace Machine {
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:
void Axes::group(Configuration::HandlerBase& handler) {

View File

@@ -30,6 +30,8 @@ namespace Machine {
static const int MAX_NUMBER_AXIS = 6;
static constexpr const char* _names = "XYZABC";
bool _switchedStepper = false;
public:
Axes();
@@ -65,6 +67,10 @@ namespace Machine {
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.
void init();
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);
}
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.
// 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.
@@ -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 */
// Switch stepper mode to the I2S static (realtime mode)
if (save_stepper == ST_I2S_STREAM) {
Stepper::switch_mode(ST_I2S_STATIC); /* Change the stepper to reduce the delay for accurate probing. */
}
config->_axes->beginLowLatency();
// Initialize probing control variables
bool is_probe_away = bit_istrue(parser_flags, GCParserProbeIsAway);
@@ -352,7 +343,7 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
if (config->_probe->tripped()) {
sys_rt_exec_alarm = ExecAlarm::ProbeFailInitial;
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.
}
// Setup and queue probing motion. Auto cycle-start should not start the cycle.
@@ -365,13 +356,12 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
do {
protocol_execute_realtime();
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
}
} while (sys.state != State::Idle);
// Switch the stepper mode to the previous mode
RESTORE_STEPPER(save_stepper);
config->_axes->endLowLatency();
// Probing cycle complete!
// 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);
// stepping->init(_step_pin);
if (config->_stepType == ST_RMT) {
rmtConfig.rmt_mode = RMT_MODE_TX;
rmtConfig.clk_div = 20;

View File

@@ -272,16 +272,11 @@ Error home(int cycle) {
}
sys.state = State::Homing; // Set system state variable
int save_stepper = config->_stepType;
if (save_stepper == ST_I2S_STREAM) {
Stepper::switch_mode(ST_I2S_STATIC);
}
config->_axes->beginLowLatency();
mc_homing_cycle(cycle);
if (save_stepper == ST_I2S_STREAM && config->_stepType != ST_I2S_STREAM) {
Stepper::switch_mode(ST_I2S_STREAM);
}
config->_axes->endLowLatency();
if (!sys.abort) { // Execute startup scripts after successful homing.
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) {
case ST_I2S_STREAM:
// Generate the number of pulses needed to span pulse_microseconds
i2s_out_push_sample(pulseMicros);
i2s_out_push_sample(config->_pulseMicroSeconds);
config->_axes->unstep();
break;
case ST_I2S_STATIC:
case ST_TIMED:
endMicros = config->_pulseMicroSeconds + step_pulse_start_time;
// 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
}
config->_axes->unstep();
@@ -373,6 +375,7 @@ void Stepper::init() {
info_serial("Axis count %d", config->_axes->_numberAxis);
info_serial("Step type:%s Pulse:%dus Dsbl Delay:%dus Dir Delay:%dus",
// stepping->name(),
stepTypes[config->_stepType].name,
config->_pulseMicroSeconds,
config->_disableDelayMicroSeconds,
@@ -382,25 +385,6 @@ void Stepper::init() {
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.
void Stepper::wake_up() {
//info_serial("st_wake_up");
@@ -415,6 +399,7 @@ void Stepper::wake_up() {
// Reset and clear stepper subsystem variables
void Stepper::reset() {
// Initialize stepper driver idle state.
// stepping->reset();
if (config->_stepType == ST_I2S_STREAM) {
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
static void IRAM_ATTR timerWritePeriod(uint16_t timerTicks) {
// stepping->setPeriod(uint16_t timerTicks);
if (config->_stepType == ST_I2S_STREAM) {
// 1 tick = fTimers / fStepperTimer
// Pulse ISR is called for each tick of alarm_val.
@@ -956,6 +942,7 @@ static void IRAM_ATTR timerInit() {
}
static void IRAM_ATTR timerStart() {
// stepping->start();
if (config->_stepType == ST_I2S_STREAM) {
i2s_out_set_stepping();
} else {
@@ -965,6 +952,7 @@ static void IRAM_ATTR timerStart() {
}
static void IRAM_ATTR timerStop() {
// stepping->stop();
if (config->_stepType == ST_I2S_STREAM) {
i2s_out_set_passthrough();
} else if (stepTimer) {