From 5bdc9713789627987e326b74a5a465cdb11ed9a4 Mon Sep 17 00:00:00 2001 From: David Crocker Date: Mon, 16 Dec 2019 16:55:40 +0000 Subject: 3.0RC1 final(?) Fixed issue with G1 H1 moves when endstops are not already triggered. There is still an issue if a move involves only remote drivers and a main board endstop switch. Don't set up a default bed heater on Duet 3 Fixed issue when creating a switch endstop failed --- src/CAN/CanMotion.cpp | 63 +++++++++++++++++++++++++++++++++------- src/CAN/CanMotion.h | 6 ++-- src/Endstops/EndstopsManager.cpp | 9 +++++- src/Heating/Heat.cpp | 3 ++ src/Movement/DDA.cpp | 44 +++++++++++++++++++--------- src/Movement/DDARing.cpp | 14 +++++++-- src/Version.h | 2 +- 7 files changed, 111 insertions(+), 30 deletions(-) diff --git a/src/CAN/CanMotion.cpp b/src/CAN/CanMotion.cpp index 13b52110..fd311f6d 100644 --- a/src/CAN/CanMotion.cpp +++ b/src/CAN/CanMotion.cpp @@ -112,7 +112,7 @@ void CanMotion::FinishMovement(uint32_t moveStartTime) CanMessageBuffer *buf; while ((buf = movementBufferList) != nullptr) { - boardsActiveInLastMove.SetBit(buf->id.Dst()); + boardsActiveInLastMove.SetBit(buf->id.Dst()); //TODO should we set this if there were no steps for drives on the board, just drives to be enabled? movementBufferList = buf->next; buf->msg.move.whenToExecute = moveStartTime; CanInterface::SendMotion(buf); // queues the buffer for sending and frees it when done @@ -183,17 +183,45 @@ void CanMotion::InsertHiccup(uint32_t numClocks) CanInterface::WakeCanSender(); } -void CanMotion::StopDriver(DriverId driver) +void CanMotion::StopDriver(bool isBeingPrepared, DriverId driver) { - driversToStop[driversToStopIndexBeingFilled].AddEntry(driver); - CanInterface::WakeCanSender(); + if (isBeingPrepared) + { + // Search for the correct movement buffer + CanMessageBuffer* buf = movementBufferList; + while (buf != nullptr && buf->id.Dst() != driver.boardAddress) + { + buf = buf->next; + } + + if (buf != nullptr) + { + buf->msg.move.perDrive[driver.localDriver].steps = 0; + } + } + else + { + driversToStop[driversToStopIndexBeingFilled].AddEntry(driver); + CanInterface::WakeCanSender(); + } } -void CanMotion::StopAxis(size_t axis) +void CanMotion::StopAxis(bool isBeingPrepared, size_t axis) { - if (!stopAllFlag) + const AxisDriversConfig& cfg = reprap.GetPlatform().GetAxisDriversConfig(axis); + if (isBeingPrepared) + { + for (size_t i = 0; i < cfg.numDrivers; ++i) + { + const DriverId driver = cfg.driverNumbers[i]; + if (driver.IsRemote()) + { + StopDriver(true, driver); + } + } + } + else if (!stopAllFlag) { - const AxisDriversConfig& cfg = reprap.GetPlatform().GetAxisDriversConfig(axis); for (size_t i = 0; i < cfg.numDrivers; ++i) { const DriverId driver = cfg.driverNumbers[i]; @@ -206,10 +234,25 @@ void CanMotion::StopAxis(size_t axis) } } -void CanMotion::StopAll() +void CanMotion::StopAll(bool isBeingPrepared) { - stopAllFlag = true; - CanInterface::WakeCanSender(); + if (isBeingPrepared) + { + // We still send the messages so that the drives get enabled, but we set the steps to zero + for (CanMessageBuffer *buf = movementBufferList; buf != nullptr; buf = buf->next) + { + buf->msg.move.accelerationClocks = buf->msg.move.decelClocks = buf->msg.move.steadyClocks = 0; + for (size_t drive = 0; drive < ARRAY_SIZE(buf->msg.move.perDrive); ++drive) + { + buf->msg.move.perDrive[drive].steps = 0; + } + } + } + else + { + stopAllFlag = true; + CanInterface::WakeCanSender(); + } } #endif diff --git a/src/CAN/CanMotion.h b/src/CAN/CanMotion.h index ff775bde..e9b5929f 100644 --- a/src/CAN/CanMotion.h +++ b/src/CAN/CanMotion.h @@ -25,9 +25,9 @@ namespace CanMotion // The next 4 functions may be called from the step ISR, so they can't send CAN messages directly void InsertHiccup(uint32_t numClocks); - void StopDriver(DriverId driver); - void StopAxis(size_t axis); - void StopAll(); + void StopDriver(bool isBeingPrepared, DriverId driver); + void StopAxis(bool isBeingPrepared, size_t axis); + void StopAll(bool isBeingPrepared); } #endif diff --git a/src/Endstops/EndstopsManager.cpp b/src/Endstops/EndstopsManager.cpp index a3925ba6..461b92ac 100644 --- a/src/Endstops/EndstopsManager.cpp +++ b/src/Endstops/EndstopsManager.cpp @@ -293,7 +293,14 @@ GCodeResult EndstopsManager::HandleM574(GCodeBuffer& gb, const StringRef& reply, axisEndstops[lastAxisSeen] = nullptr; SwitchEndstop * const sw = new SwitchEndstop(lastAxisSeen, lastPosSeen); const GCodeResult rslt = sw->Configure(gb, reply); - axisEndstops[lastAxisSeen] = sw; + if (rslt == GCodeResult::ok) + { + axisEndstops[lastAxisSeen] = sw; + } + else + { + delete sw; + } return rslt; } diff --git a/src/Heating/Heat.cpp b/src/Heating/Heat.cpp index 1ef6c48b..aafa7b3a 100644 --- a/src/Heating/Heat.cpp +++ b/src/Heating/Heat.cpp @@ -95,7 +95,10 @@ Heat::Heat() noexcept { h = -1; } +#if !DUET3 bedHeaters[0] = DefaultBedHeater; +#endif + for (int8_t& h : chamberHeaters) { h = -1; diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp index 955685e6..abefdf56 100644 --- a/src/Movement/DDA.cpp +++ b/src/Movement/DDA.cpp @@ -1268,7 +1268,7 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept const AxisDriversConfig& config = platform.GetAxisDriversConfig(Z_AXIS); if (drive < config.numDrivers) { - const int32_t delta = lrintf(directionVector[drive] * totalDistance * reprap.GetPlatform().DriveStepsPerUnit(Z_AXIS)); + const int32_t delta = lrintf(directionVector[drive] * totalDistance * platform.DriveStepsPerUnit(Z_AXIS)); const DriverId driver = config.driverNumbers[drive]; #if SUPPORT_CAN_EXPANSION if (driver.IsRemote()) @@ -1308,7 +1308,7 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept const int32_t delta = endPoint[drive] - prev->endPoint[drive]; if (platform.GetDriversBitmap(drive) != 0) // if any of the drives is local { - reprap.GetPlatform().EnableLocalDrivers(drive); + platform.EnableLocalDrivers(drive); DriveMovement* const pdm = DriveMovement::Allocate(drive, DMState::moving); pdm->totalSteps = labs(delta); pdm->direction = (delta >= 0); @@ -1352,7 +1352,7 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept if (flags.continuousRotationShortcut && reprap.GetMove().GetKinematics().IsContinuousRotationAxis(drive)) { // This is a continuous rotation axis, so we may have adjusted the move to cross the 180 degrees position - const int32_t stepsPerRotation = lrintf(360.0 * reprap.GetPlatform().DriveStepsPerUnit(drive)); + const int32_t stepsPerRotation = lrintf(360.0 * platform.DriveStepsPerUnit(drive)); if (delta > stepsPerRotation/2) { delta -= stepsPerRotation; @@ -1436,7 +1436,7 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept { DriveMovement* const pdm = DriveMovement::Allocate(drive, DMState::moving); const bool stepsToDo = pdm->PrepareExtruder(*this, params, extrusionPending[extruder], speedChange, flags.usePressureAdvance); - reprap.GetPlatform().EnableLocalDrivers(drive); + platform.EnableLocalDrivers(drive); if (stepsToDo) { @@ -1475,7 +1475,7 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept ClearBit(additionalAxisMotorsToEnable, drive); if (platform.GetDriversBitmap(drive) != 0) // if any of the connected axis drives is local { - reprap.GetPlatform().EnableLocalDrivers(drive); + platform.EnableLocalDrivers(drive); } #if SUPPORT_CAN_EXPANSION const AxisDriversConfig& config = platform.GetAxisDriversConfig(drive); @@ -1493,9 +1493,18 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept const DDAState st = prev->state; afterPrepare.moveStartTime = (st == DDAState::executing || st == DDAState::frozen) - ? prev->afterPrepare.moveStartTime + prev->clocksNeeded // this move will follow the previous one, so calculate the start time assuming no more hiccups + ? prev->afterPrepare.moveStartTime + prev->clocksNeeded // this move will follow the previous one, so calculate the start time assuming no more hiccups : StepTimer::GetTimerTicks() + MovementStartDelayClocks; // else this move is the first so start it after a short delay + if (flags.checkEndstops) + { + // Before we send movement commands to remote drives, if any endstop switches we are monitoring are already set, make sure we don't start the motors concerned. + // This is especially important when using CAN-connected motors or endstops, because we rely on receiving "endstop changed" messages. + // Moves that check endstops are always run as isolated moves, so there can be no move in progress and the endstops must already be primed. + platform.EnableAllSteppingDrivers(); + CheckEndstops(platform); // this may modify pending CAN moves, and may set status 'completed' + } + #if SUPPORT_CAN_EXPANSION CanMotion::FinishMovement(afterPrepare.moveStartTime); #endif @@ -1520,7 +1529,10 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept #endif } - state = frozen; // must do this last so that the ISR doesn't start executing it before we have finished setting it up + if (state != completed) + { + state = frozen; // must do this last so that the ISR doesn't start executing it before we have finished setting it up + } } // Take a unit positive-hyperquadrant vector, and return the factor needed to obtain @@ -1625,8 +1637,11 @@ float DDA::NormaliseXYZ() noexcept } } +// Check the endstops, given that we know that this move checks endstops. +// Either this move is currently executing (DDARing.currentDDA == this) and the state is 'executing', or we have almost finished preparing it and the state is 'provisional'. void DDA::CheckEndstops(Platform& platform) noexcept { + const bool fromPrepare = (state == DDAState::provisional); // determine this before anything sets the state to 'completed' for (;;) { const EndstopHitDetails hitDetails = platform.GetEndstops().CheckEndstops(flags.goingSlow); @@ -1635,7 +1650,7 @@ void DDA::CheckEndstops(Platform& platform) noexcept case EndstopHitAction::stopAll: MoveAborted(); // set the state to completed and recalculate the endpoints #if SUPPORT_CAN_EXPANSION - CanMotion::StopAll(); + CanMotion::StopAll(fromPrepare); #endif if (hitDetails.isZProbe) { @@ -1658,11 +1673,11 @@ void DDA::CheckEndstops(Platform& platform) noexcept #if SUPPORT_CAN_EXPANSION if (state == completed) // if the call to StopDrive flagged the move as completed { - CanMotion::StopAll(); + CanMotion::StopAll(fromPrepare); } else { - CanMotion::StopAxis(hitDetails.axis); + CanMotion::StopAxis(fromPrepare, hitDetails.axis); } #endif if (hitDetails.setAxisLow) @@ -1681,7 +1696,7 @@ void DDA::CheckEndstops(Platform& platform) noexcept #if SUPPORT_CAN_EXPANSION if (hitDetails.driver.IsRemote()) { - CanMotion::StopDriver(hitDetails.driver); + CanMotion::StopDriver(fromPrepare, hitDetails.driver); } else #endif @@ -1761,9 +1776,12 @@ pre(state == frozen) if (activeDMs != nullptr) { - p.EnableAllSteppingDrivers(); // make sure that all drivers are enabled + if (!flags.checkEndstops) + { + p.EnableAllSteppingDrivers(); // make sure that all drivers are enabled + } const size_t numTotalAxes = reprap.GetGCodes().GetTotalAxes(); - unsigned int extrusions = 0, retractions = 0; // bitmaps of extruding and retracting drives + unsigned int extrusions = 0, retractions = 0; // bitmaps of extruding and retracting drives for (const DriveMovement* pdm = activeDMs; pdm != nullptr; pdm = pdm->nextDM) { const size_t drive = pdm->drive; diff --git a/src/Movement/DDARing.cpp b/src/Movement/DDARing.cpp index 17a66224..fc84012d 100644 --- a/src/Movement/DDARing.cpp +++ b/src/Movement/DDARing.cpp @@ -204,8 +204,18 @@ void DDARing::Spin(uint8_t simulationMode, bool shouldStartMove) noexcept // No DDA is executing, so start executing a new one if possible if (shouldStartMove || !CanAddMove()) { - PrepareMoves(getPointer, 0, 0, simulationMode); - DDA * const dda = getPointer; // capture volatile variable + DDA * dda = getPointer; // capture volatile variable + if (dda->GetState() == DDA::provisional) + { + PrepareMoves(dda, 0, 0, simulationMode); + while (dda->GetState() == DDA::completed) + { + // We prepared the move but found there was nothing to do because endstops are already triggered + getPointer = dda = dda->GetNext(); + completedMoves++; + } + } + if (dda->GetState() == DDA::frozen) { if (simulationMode != 0) diff --git a/src/Version.h b/src/Version.h index aeab5809..03511424 100644 --- a/src/Version.h +++ b/src/Version.h @@ -20,7 +20,7 @@ #endif #ifndef DATE -# define DATE "2019-12-16b3" +# define DATE "2019-12-16b7" #endif #define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman, printm3d" -- cgit v1.2.3