diff options
author | markmaker <mark@makr.zone> | 2021-02-05 16:40:34 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-05 16:40:34 +0300 |
commit | 4ddc6328895b0bcd727bec09793fcb3110046e59 (patch) | |
tree | 61b4bd44c88913043edf6dc94bfbd03afdb808d8 /src/Movement | |
parent | 21085888ef5917fa424bdabfe86c37392464c14e (diff) |
Feature / Configurable Grace Period for Starting into Moves (#471)
* Added M595 Rnn word to set the grace period, that is waited out before starting moves. The R word is given in milliseconds and it controls the idle time after receiving the last move command to process.
This will make sure fine-grained move sequences will be received in full and can be look-ahead-planned properly, right to the end. This option has been introduced after it was demonstrated that Duet would rush into premature deceleration on fine-grained interpolation move sequences send from OpenPnP. De to their nature, these motion sequences typically need to be look-ahead-planned in full, otherwise they will be degraded.
Note that M400 (and others) will release the motion sequence immediately. A motion sequence closed with M400 will therefore incur no additional wait time (once the commands have been received).
* Changes, as indicated by dc42
Diffstat (limited to 'src/Movement')
-rw-r--r-- | src/Movement/DDARing.cpp | 10 | ||||
-rw-r--r-- | src/Movement/DDARing.h | 2 | ||||
-rw-r--r-- | src/Movement/Move.cpp | 7 | ||||
-rw-r--r-- | src/Movement/Move.h | 1 |
4 files changed, 16 insertions, 4 deletions
diff --git a/src/Movement/DDARing.cpp b/src/Movement/DDARing.cpp index dad6f4e8..100445d4 100644 --- a/src/Movement/DDARing.cpp +++ b/src/Movement/DDARing.cpp @@ -18,7 +18,7 @@ constexpr uint32_t UsualMinimumPreparedTime = StepTimer::StepClockRate/10; // 100ms constexpr uint32_t AbsoluteMinimumPreparedTime = StepTimer::StepClockRate/20; // 50ms -DDARing::DDARing() noexcept : scheduledMoves(0), completedMoves(0), numHiccups(0) +DDARing::DDARing() noexcept : gracePeriod(0), scheduledMoves(0), completedMoves(0), numHiccups(0) { } @@ -99,6 +99,7 @@ GCodeResult DDARing::ConfigureMovementQueue(GCodeBuffer& gb, const StringRef& re uint32_t numDdasWanted = 0, numDMsWanted = 0; gb.TryGetUIValue('P', numDdasWanted, seen); gb.TryGetUIValue('S', numDMsWanted, seen); + gb.TryGetUIValue('R', gracePeriod, seen); if (seen) { if (!reprap.GetGCodes().LockMovementAndWaitForStandstill(gb)) @@ -143,7 +144,7 @@ GCodeResult DDARing::ConfigureMovementQueue(GCodeBuffer& gb, const StringRef& re } else { - reply.printf("DDAs %u, DMs %u", numDdasInRing, DriveMovement::NumCreated()); + reply.printf("DDAs %u, DMs %u, GracePeriod %" PRIu32, numDdasInRing, DriveMovement::NumCreated(), gracePeriod); } return GCodeResult::ok; } @@ -357,6 +358,11 @@ bool DDARing::IsIdle() const noexcept return currentDda == nullptr && getPointer->GetState() == DDA::empty; } +uint32_t DDARing::GetGracePeriod() const noexcept +{ + return gracePeriod; +} + // Try to push some babystepping through the lookahead queue, returning the amount pushed float DDARing::PushBabyStepping(size_t axis, float amount) noexcept { diff --git a/src/Movement/DDARing.h b/src/Movement/DDARing.h index d386a176..f0725c27 100644 --- a/src/Movement/DDARing.h +++ b/src/Movement/DDARing.h @@ -31,6 +31,7 @@ public: void Spin(uint8_t simulationMode, bool shouldStartMove) noexcept SPEED_CRITICAL; // Try to process moves in the ring bool IsIdle() const noexcept; // Return true if this DDA ring is idle + uint32_t GetGracePeriod() const noexcept; // Return the minimum idle time, before we should start a move. Better to have a few moves in the queue so that we can do lookahead float PushBabyStepping(size_t axis, float amount) noexcept; // Try to push some babystepping through the lookahead queue, returning the amount pushed @@ -106,6 +107,7 @@ private: volatile int32_t liveEndPoints[MaxAxesPlusExtruders]; // The XYZ endpoints of the last completed move in motor coordinates unsigned int numDdasInRing; + uint32_t gracePeriod; // The minimum idle time, before we should start a move. Better to have a few moves in the queue so that we can do lookahead uint32_t scheduledMoves; // Move counters for the code queue volatile uint32_t completedMoves; // This one is modified by an ISR, hence volatile diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp index e5504fbb..4b1f5d63 100644 --- a/src/Movement/Move.cpp +++ b/src/Movement/Move.cpp @@ -195,6 +195,7 @@ void Move::Init() noexcept moveState = MoveState::idle; lastStateChangeTime = millis(); idleCount = 0; + idleStartTime = lastStateChangeTime; simulationMode = 0; longestGcodeWaitInterval = 0; @@ -284,11 +285,12 @@ void Move::Spin() noexcept if (mainDDARing.AddStandardMove(nextMove, !IsRawMotorMove(nextMove.moveType))) { + const uint32_t now = millis(); idleCount = 0; + idleStartTime = now; if (moveState == MoveState::idle || moveState == MoveState::timing) { moveState = MoveState::collecting; - const uint32_t now = millis(); const uint32_t timeWaiting = now - lastStateChangeTime; if (timeWaiting > longestGcodeWaitInterval) { @@ -302,7 +304,8 @@ void Move::Spin() noexcept } } - mainDDARing.Spin(simulationMode, idleCount > 10); // let the DDA ring process moves. Better to have a few moves in the queue so that we can do lookahead, hence the test on idleCount. + // let the DDA ring process moves. Better to have a few moves in the queue so that we can do lookahead, hence the test on idleCount and idleTime. + mainDDARing.Spin(simulationMode, idleCount > 10 && millis() - idleStartTime >= mainDDARing.GetGracePeriod()); #if SUPPORT_ASYNC_MOVES if (auxMoveAvailable && auxDDARing.CanAddMove()) diff --git a/src/Movement/Move.h b/src/Movement/Move.h index 60a49235..5f01e390 100644 --- a/src/Movement/Move.h +++ b/src/Movement/Move.h @@ -250,6 +250,7 @@ private: unsigned int jerkPolicy; // When we allow jerk unsigned int idleCount; // The number of times Spin was called and had no new moves to process + uint32_t idleStartTime; // the time when we started to idle uint32_t longestGcodeWaitInterval; // the longest we had to wait for a new GCode float tangents[3]; // Axis compensation - 90 degrees + angle gives angle between axes |