Fix homing settling delay and prevent cycleStartEvent queue drop during simultaneous limit switch triggers - #1739
Fix homing settling delay and prevent cycleStartEvent queue drop during simultaneous limit switch triggers#1739MitchBradley with Copilot wants to merge 4 commits into
Conversation
|
@copilot I have a concern about what you said, namely "both pinActiveEvents are processed before either limitEvent, so limitEvent(X) sees both axes already in limited()". The problem is that pinActiveEvents do not directly affect the _posLimits and _negLimits variables; they are set by LimitPin::trigger(), which means that the limit events must have been processed. |
You're right to flag that — the description was imprecise. Here is the accurate chain for a GPIO limit pin:
So the masks are set inside step 2, not by During that 250 ms the polling task continues running. Because |
|
@copilot The situation that you have identified might indeed be a problem, but it does not explain the current issue for the following reason. Kinematics.h has a bug whereby homing_move()'s settling_ms parameter is "uint32_t" instead of "uint32_t&". As a result, _settling_ms in Homing.cpp remains at its initial value of 0, and thus delay_ms(_settling_ms) does not delay for long enough to allow the event queue to fill up. |
… is correctly updated
You're right — with The With a properly non-zero |
|
@copilot I think that you misunderstood me. My point is that, due to the _settle_ms reference bug, queue flooding cannot happen, thus the original issue remains unexplained. Fixing the reference bug and the queue flooding is probably worthwhile for other reasons, but probably does not solve the problem. |
You're correct. With The two fixes are still correct on their own merits:
But you're right that neither fix addresses the original reported hang. I've traced the event chain carefully and haven't found a convincing code path to an indefinite hang with |
Two independent correctness bugs are fixed in the homing subsystem.
Bug 1 —
_settling_msnever populated (uint32_t→uint32_t&)homing_move()'ssettling_msparameter was declareduint32_t(passed by value) in all kinematics implementations. BecauseaxesVector()/motorVector()write the per-axis configured settle time back through this parameter, the value-copy meantHoming::_settling_msremained at its initial value of 0 regardless of configuration. As a resultdelay_ms(_settling_ms)never actually delayed; the intended settling pause after limit contact and after pulloff completion was silently skipped.Bug 2 — Event queue too small once settling works
With a correctly non-zero
_settling_ms,delay_ms()inside the limit-event handler blocks the main loop for the full settle duration (e.g. 250 ms). During that window the GPIO polling task (running every ~5 ms) continues enqueuingpinActiveEventandlimitEventitems for any bouncing switches. WithMAX_N_AXISactive limit pins at a 5 ms rate limit, up to ~100 events can accumulate over 250 ms — more than the previous 50-slot queue capacity. If the queue fills beforehoming_move()enqueuescycleStartEvent, that event is silently dropped byxQueueSend,wake_up()is never called, and the machine hangs indefinitely in Homing state with no motion.Note: with the original buggy code (
_settling_ms = 0),delay_ms(0)yields almost immediately and queue flooding cannot occur. The queue-size fix is therefore a necessary companion to Bug 1's fix — once settling actually works the queue must be large enough to absorb bounce events accumulated during the settle delay.Changes
FluidNC/src/Kinematics/Kinematics.h,Kinematics.cpp,Cartesian.h,Cartesian.cpp,ParallelDelta.h,ParallelDelta.cpp— changehoming_move()'ssettling_msparameter fromuint32_ttouint32_t&so thatHoming::_settling_msis correctly written back fromaxesVector()/motorVector()with the per-axis configured settle time.FluidNC/src/Protocol.cpp— increaseevent_queuecapacity from 50 to 200 items so the queue cannot be exhausted by pin-debounce events accumulated during a settle delay, ensuringcycleStartEventis never dropped:Each
EventItemis 8 bytes; the extra 150 slots add 1.2 KB — negligible on ESP32. The new size covers the worst case ofMAX_N_AXISactive limit pins × (settle_ms / debounce_ms) bounce events plus headroom.