Marlin: [BUG] SKR v1.3 (or any other LPC1768): problem with servo signals that cause issues with bltouch

Created on 9 Dec 2019  ·  72Comments  ·  Source: MarlinFirmware/Marlin

Bug Description

Recently i have upgraded my 3d printer to a Bigtreetech SKR v1.3. Unfortunatly i had some troubles with my bltouch clone (an older version of triaglelab 3d touch).
Every now and than on a G28 or G29, the bltouch does not trigger and the printhead continues to drive down into the bed.
At first i tried to find a solution in the inernet, but only found a forum article where someone said, that the SKR v1.3 has a bad 5V supply. Some additional Capacitors or an external 5V Supply should help. I tried both, but nothing helped! The 5V supply was not the problem!
I did some investigations myself and with the help of an Oscilloscope i found the actual issue:
It seems there is problem in the HAL of the LPC1768 (and maybe others) which can produce a wrong signal on the servo output. When the servo pulse should change from 1472µs (M280 P0 S90; stowed bltouch pin) to 647µs (M280 P0 S10;deployed pin) sometimes for one cycle the pulse is 20650µs long instead.
This long pulse seems to confuse the bltouch (clone) and even though the pin is deployed, under these circumstances the sensor will not trigger the endstop when it touches the bed.
I believe this happens every time, when the "M280 P0 S10" command is issued right in the small window where the servo pin is high for more than 647µs, but less than 1472µs. Than the falling edge for this cycle is already over and it is not executed until the next 20ms cylce (Just a guess, i have no evidence...).
But I found a quick and dirty solution that work's for me:

diff --git a/Marlin/src/HAL/HAL_LPC1768/Servo.h b/Marlin/src/HAL/HAL_LPC1768/Servo.h
index 1bbf84c73..97a7bcb54 100644
--- a/Marlin/src/HAL/HAL_LPC1768/Servo.h
+++ b/Marlin/src/HAL/HAL_LPC1768/Servo.h
@@ -58,6 +58,12 @@ class libServo: public Servo {
     static_assert(COUNT(servo_delay) == NUM_SERVOS, "SERVO_DELAY must be an array NUM_SERVOS long.");

     if (attach(servo_info[servoIndex].Pin.nbr) >= 0) {    // try to reattach
+      /* workaround for too long pulse on the servo pin */
+      if ( (servoIndex == 0) && ( extDigitalRead(SERVO0_PIN) == 1 ) ) {
+        safe_delay(3);
+      }
       write(value);
       safe_delay(servo_delay[servoIndex]); // delay to allow servo to reach position
       #if ENABLED(DEACTIVATE_SERVOS_AFTER_MOVE)

It simply checks the current status of the servo pin. If it is high, the change of the signal is delayed by 3ms. This ensures, that the pin is definitely low when the change is applyed, because the servo pulse can not be longer than 2.4ms.

But this is only a quick and dirty hack and it should be fixed in the HAL. And it should also be checked, if this issue can happen on other Controllers too.

My Configurations

Marlin_Configuration.zip

Steps to Reproduce

  1. Use a SKR v1.3 board (or any other LPC1768) with a servo configured (#define NUM_SERVOS 1)
  2. send M280 P0 S90
  3. send M280 P0 S10
  4. watch the servo signal (SKR v1.3: pin P2_00)

Expected behavior: [What you expect to happen]
A clean transition from signals with 1472µs pulse width to 647µs.

Actual behavior: [What actually happens]
Every now and than you will see a pulse width of more than 20ms on the first cycle after the command.

Additional Information

Maybe it is more likely to see, if you use "M280 P0 S180" and "M280 P0 S0" instead. (greater difference -> bigger window for the issue)

LPC176x Confirmed ! BLTouch

Most helpful comment

This shouldn't be blamed on the probe hardware. The signal being produced from the board is incorrect, and was verified using an oscilloscope. That should be fixed.

I can also confirm that the reported behavior is very similar to genuine BLTouch hardware when I was debugging all those timer conflicts causing similar issues on SKR Mini E3 boards. Invalid pulse lengths seemed to cause the BLTouch to simply forget what it was doing and caused failures.

@mlehnhoff, did you capture any images from your oscilloscope that demonstrate the problem, that you could attach to this issue?

I don't think I like the current workaround as a complete solution, but I really appreciate the level of detail mlehnhoff provided describing the issue and the workaround demonstrating that pulse apparently is the root cause of the issue.

All 72 comments

Are you able to try a genuine BLTouch?

Are you able to try a genuine BLTouch?

Also, have you tried adjusting BLTouch settings in Configuration_adv.h?: You can adjust settings like BLTOUCH_DELAY, BLTOUCH_FORCE_SW_MODE, BLTOUCH_FORCE_MODE_SET, etc.

Oh, sorry, i forgot to mention. Of course i did try different combinations of BLTOUCH_DELAY, BLTOUCH_FORCE_SW_MODE and even DELAY_BEFORE_PROBING before. Without sucess.
Now, that i found out, what the problem is, it is clear, that longer delays does not help. Because the wrong 20ms pulse that brings the bltouch to this error state happens already a couple of seconds before the buildplate is touched.
BLTOUCH_FORCE_MODE_SET is not supported by this old version of bltouch clone. It is not a "smart" one.

And no, i don't have access to an genuine BLTouch. For me and my old clone the above mentioned hack works just fine, so personally i don't need a proper fix for this issu. But i think, that this issue should be fixed anyhow, because i think that even an actual servo could possibly react on this pulse with a short shake or any other weird behavior.

Wow, @mlehnhoff, your patch ease my pain. SKR v1.3 + (not sure about an older version or not) triaglelab 3d touch - same troubles. My own 8/10 working condition: BLTOUCH_FORCE_SW_MODE + BLTOUCH_DELAY 1000. But your patch works 10/10 without SW_MODE and DELAY. Tnx!

i tested a servo based touch probe on a re-arm (same MCU) and i had no issues, but i used the deactivate after movement feature.

i have not tried without it, juse made logic sense to deactivate the servo when not needed

I have a handful of genuine BLTouches and they all work fine on an SKR 1.3 which is also LPC1768.

so jumping the gun here, is it most likely a hardware issue (wire, noise connection) or a user config issue?

Same reason for most of the extra BLTouch code/config options, it's a BLTouch clone issue.

Keep in mind that 3DTouch != BLTouch. There are a lot of closed issues related to these copies.

i would call it a hardware issue then,

yep i now 3dtouch (and others) are not a BLtouch

the big Q for me is whatever marlin supports the clones or if we only care about the genuine products?

giving a bit of thought personal i dont think its fair that marlin should support the clones

but i could be wrong, thoughts?

My two cents, no matter what the name of XXtouch. Any of them connects to SERVOS pin (not BLtouch special pin). The SERVOS should work like a servos.

But i think, that this issue should be fixed anyhow, because i think that even an actual servo could possibly react on this pulse with a short shake or any other weird behavior.
(from @mlehnhoff comment)

This shouldn't be blamed on the probe hardware. The signal being produced from the board is incorrect, and was verified using an oscilloscope. That should be fixed.

I can also confirm that the reported behavior is very similar to genuine BLTouch hardware when I was debugging all those timer conflicts causing similar issues on SKR Mini E3 boards. Invalid pulse lengths seemed to cause the BLTouch to simply forget what it was doing and caused failures.

@mlehnhoff, did you capture any images from your oscilloscope that demonstrate the problem, that you could attach to this issue?

I don't think I like the current workaround as a complete solution, but I really appreciate the level of detail mlehnhoff provided describing the issue and the workaround demonstrating that pulse apparently is the root cause of the issue.

Sorry, that i did not provide scope screenshot immediately. I thougt i had had made some, but something went wrong. But i did not realize until i had given the scope back (it is not mine).
But now i have made a new one:
scope_0
On the picture you see the transition from 1472µs to 544µ, but the first new

pulse is 20544µs.

Plus i tried an actual servo and here is the prove, that this problem is not only limited to 3dtouch or other clones.

IMG_4677.zip

The Servo should turn from 90° (lever in the middle) to 0° (lever down), but when the faulty pulse occurs, it actually turns up at first, before turning down.

By the way there are at least eight different versions of genuine bltouch (classic v1.0, v1.2, v1.3, smart v1.0, v2.0, v2.2, v3.0, v3.1) and no one knows, if all of them will work correctly ;-)

Here is another hint: When you send the M280 command manually it is very unlikely, that the issue occurs. I wrote a script to toggle the servo (used in the video) which increases the likeliness a lot:
servo_toggle.gcode.txt

I wonder if this is related to an issue I'm seeing with my BLTouch.
I power my Re-ARM over USB and use M80 to turn on the 12V power supply. There is a 5V buck converter connected to the 12V power supply that powers the BLTouch, so the BLTouch doesn't get power until the 12V supply kicks in.
When the board powers up, the BLTouch flashes red - this is apparently somewhat normal if the BLTouch gets a signal before it powers up, so I'm not concerned about that.
However, any attempt to reset it with M280 P0 S160 has absolutely no effect. Neither does it retract the pin if it is deployed.
However, M280 P0 S60 successfully switches to SW mode and also stops the blinking.
Other than the blinking and S160 apparently being ignored, the BLTouch seems to work perfectly. Even when blinking it properly deploys, stows and probes - I've done full bed probes and have never seen a probe failure and repeatability is excellent.
This is a genuine V3.1 BLTouch - not a clone.

I forgot to mention that I checked the pulses with both my cheap mini DSO and my big CRT oscilloscope and the pulse lengths seem fine. I've also tried different S values (from 155 to 165) without finding one that will trigger the reset.

I haven't looked up how the servo library for the LPC works - but:
A servo signal is a PWM. If this would be realized with a STM32 hardware timer this error would likely be caused by updating the counters compare register directly, instead of updating the new value to the preload register of the compare register. If changing the compare register from a high value to a low value while the counter is in between of the low and the high value, the (equal) compare is skipped, the pin is not changed until the counter overrun and than reaches the new value. If the preload register is used, the compare register is updated either when the counter overruns, or when the (old) compare value has a match. This has no risk of a loooong puls, only a possible delay of max about one PWM-periode (20ms).
EDIT: The chance for the error would be 5% per skipping 1ms backwards.
I suppose, here we have something similar.

This is because the lpc framework is not running the hardware pwm in latching mode, (where the pulsewidth register is shadowed and latched in on each period), it should be possible to do that with a simple mode bit .. but unfortunately I can not get it to work reliably, its a choice between a possible 1 period duration glitch, or the pulse width randomly (but quite frequently depending on how often it is updated) not changing at all.

Further research on the matter could be done, but it's really not a complicated peripheral, I wasted a long time on that glitch and in the end other things needed attention.

@mlehnhoff @kockockockoc How dp you apply the patch please?

@mlehnhoff @kockockockoc How dp you apply the patch please?

To be honest, i am pretty new to git and i am just glad, that i could create this patch via "git diff". I am sure, there must be a different git command to apply this patch back. Maybe @kockockockoc can help out...
But for this very small code fragment, you can even do it by hand. It is just as easy as adding the four lines that begin wit a "+" to the file "Marlin/src/HAL/HAL_LPC1768/Servo.h" (of course without the "+") at the shown position...

Hi, I have same board Bigtreetech SKR v1.3 and 3D Touch but the 3D Touch doens't work. I've tested the 3dTouch using some code in an Arduino Mega and does work perfect. So, I've tried any suggestion I found and also the @mlehnhoff patch but I'm still having the same problem = 3D Touch is freeze. When Marlin start the 3D Touch does a self-test and then the pin is stow and stays in this state forever without any change (throught M43 S or from the Marlin menu)
I'm really concern about that because I dont know what I have to do in order to solve this issue. Any suggestion is wellcome.

I suspect that this bug is the same one I reported here: https://github.com/MarlinFirmware/Marlin/issues/15370

I am still running a bugfix commit from 6/22/19 with no issues. I tried the latest bugfix commit today and the servo issue is still present.

@Reywas62 and all, I found this article http://fightpc.blogspot.com/2019/08/testing-skr-13-board-with-marlin-20x.html that could solve the problem. Aparently some SKR boards could have an output signal that has a low impedance (around 200 ohms) that would require a significant amount of current to work properly (and it not happens on Arduino boards, that is the reason why my 3D touch probe works propertly on the Arduino) So, apparently it is not related to firmware.

Well I'd buy that explanation except that my board works fine with an earlier commit of Marlin bugfix 2.0.x (6/22/19).

I can confirm that the "quick an dirty" solution from mlehnhoff is working. I probing a 9x9 UBL-Mesh with a BLTouch Clone. Normally 1 or 2 points of the 81 point mesh are failing when i run the meshgeneration. But with the "fix" everything works fine. So i will continue to use this solution. And i my case i think it is a problem with the long servo pulse because my push-pin is deployed an the sensor doesn't trigger.

I'd like to confirm that my problem with the 3D Touch has been solved. The problem is the low current of the SKR 1.3 Servo pins. I made the circuit and test it sucessfully. Now I've received this information after running M43:
SENDING:M43 S
Servo probe test
. using index: 0, deploy angle: 10, stow angle: 90
. Probe Z_MIN_PIN: 57
. Z_MIN_ENDSTOP_INVERTING: false
. Check for BLTOUCH
= BLTouch Classic 1.2, 1.3, Smart 1.0, 2.0, 2.2, 3.0, 3.1 detected.
* Please trigger probe within 30 sec *
. Pulse width (+/- 4ms): 10
= BLTouch pre V3.1 (or compatible) detected

Going to experiment with my setup here, but I have both a SG90 and a MG90 servo motor that intermittently moves back on disable. As it's holding the Z-Probe switch this kinda kills the machine when it crashes into the bed. Last crash totaled the Creality CR10 S5's wheel mounts. >_

When I get a chance I'll try the circuit and see if it sorts that out. but also going to try the firmware hack. :)

After trying the firmware hack, there was no change for me (as I suspected, as the hack fixes bl-touch clones, not necessarily servo movement). The Servo would occasionally still move backwards further after completing a move.

Considering that, I undid the hack and told marlin NOT to disable the servo and it seems the move back issue has gone. Seems as though disabling the servo triggers my issue. Fortunately the MG90 I'm using doesn't show any vibration/shaking on the angles I have selected. :)

I would definitely like to thank mlehnhoff for their gcode to test with. Every time I ran it the servo would play up 3 or 4 times, and when I told marlin to keep the servo enabled, the script ran fine 3 times in a row. Considering reports of low current, I also ran the test with the heaters on to put the PSU under load. :)

Don't know if it matters, but my Servo angles are 172(deployed) and 35(Stowed) and it looked like it would move the servo backwards, by the same amount each time. The servo never moved forward.

The firmware hack did not fix my issue but leaving the servo enabled stops the servo from misbehaving, as it did for DarkAlaranth. Not really a fix, but an acceptable workaround.

A little extra background I've tried this on several platforms over the past couple of days and thought I might have broken both of my AntLab BLtouch, so I ordered a third.

Here is what I've observed for the following platforms
SKR Pro V1.1 Fails to work
SKR v1.3 Fails to work
RAMPS 1.4 Fails to work
SKR v1.4 Fails to work
RAMPS 1.6 Fails to work

The symptom before probing read on a M119
Reporting endstop status
x_min: TRIGGERED
y_min: TRIGGERED
z_min: TRIGGERED

I've adjusted the pins file as well with same results.

Here is the process I used in several video of various marlin vintage
https://www.youtube.com/watch?v=5cSzFCv7K4Q&t=14s
https://www.youtube.com/watch?v=R0HeFV9nKCM
https://www.youtube.com/watch?v=HR-zn4dv1fY&t=2s
https://www.youtube.com/watch?v=-4o6-8TgpNM

I could post more videos, but my point is it's not working on any of them with 3 genuine BL touch(s).

Has something changed in the configuration? The configuration_adv.h now has a bunch of BL touch power settings.

Should there be a report temperature when homing Z-axis?
Here is the debug:
SENT: G28 Z0
SENT: M114
SENT: M105
RECV: Error:!! STOP called because of BLTouch error - restart with M999
[ERROR] Error:!! STOP called because of BLTouch error - restart with M999

M119 on RAMPS 1.6/MEGA2560
Reads correct for open on z-min
Probing appears not to work.

Have this issue.
Ender 3, SKR Mini E3 v1.2, genuine BLTouch v3.1

Works fine for me with the V2
The wiring for the skr1.3 is different from the stock orientation. I'm using the release version of Marlin 2.0.1

Are you able to try another BLTouch? To verify that it isn't a damaged probe?

No, sorry. I only have a normal BLTouch. The failure occurs only one in ~200 or so.

@mlehnhoff when you get time please have a retest

and as bugfix 2.0.x is updated daily please retest say every 14 days or so

Recompiled the latest bugfix build [2020.01.24.]
Did two probe repeatability test, 150 each.

  1. Bed heating OFF, Finished Successfully, Standard Deviation: 0.003928.
  2. Bed heating ON, Probing Failed, failed at 137.

I have observed a similar behavior when using bugfix 2.0.x on a SKR1.1 board (LPC1768) with a clone BLTouch (3DTouch).
I have tried different workarounds, but out of 25 probe points, at least for one probing point the pin is released too early (like a deploy immediately followed by stow).

@mlehnhoff when you get time please have a retest

@boelle: retesting is not necessary, because as @p3p mentioned earlier, the issue is actually not located in Marlin itself, but in the LPC framework. He said, that he had to uncomment the PWM Latching Mode, because it didn't work properly. So, as long as this is not fixed, everybody who wants to have a reliably working bltouch has to use my ugly, but working workaround.
At the moment i unfortunately don't have access to an Oscilloscope, otherwise i would like to support P3P in debugging this issue. If anybody else would like to dig deeper into this, feel free: https://github.com/p3p/pio-framework-arduino-lpc176x/blob/master/system/lpc176x/HardwarePWM.h

Have this issue.
Ender 3, SKR Mini E3 v1.2, genuine BLTouch v3.1

SKR Mini E3 v1.2 uses a STM32 microcontroller, not a LPC1768.

I wonder if the problem with latching PWM is related to the following LPC176x errata:

3.13 PWM.1: When updating the duty cycle for PWM1.1 from 100 %, in
some cases the output can stay low for a full PWM period before the
update takes effect
Introduction:
On the LPC176x PWM peripheral, two match registers can be used to provide a single
edge controlled PWM output. One match register (PWM1MR0) controls the PWM cycle
rate, by resetting the count upon match. The other match register controls the PWM edge
position. As an example, match register PWM1MR1 controls PWM1's edge position.
Multiple single edge controlled PWM outputs will all have a rising edge at the beginning of
each PWM cycle, when a PWM1MR0 match occurs.
Problem:
Only in single-edge mode, if the duty cycle for PWM1.1 (Pulse Width Modulator 1, channel
1 output) is updated from 100 % (PWM1MR1 = PWM1MR0), then the output for PWM1.1
could unexpectedly remain low for a full PWM period before the new desired duty cycle
takes effect. This problem only affects the output for PWM1.1. Other PWM channels
(PWM1.2 to PWM1.6) are not affected by this problem.
Work-around:
A software fix can be implemented where the user can load PWM1MR1 with
PWM1MR0 + 1 (at least 1) to avoid any delays in the PWM1.1's output update.

I expect it isn't, since I wouldn't think that we ever put a servo pin in 100% PWM mode.

Then again, on the PWM 1.1 is used for P2_0 which is the servo pin on the SKR 1.3...

I have been looking into a similar issue (with a genuine BL Touch 3.1 and a SKR PRO 1.1).
I have documented what I found in #16986 but basically I found that mine was related to the XY_PROBE_SPEED. A figure of 10000 causes the BL Touch signal to change from a pulse to a DC level on the 15 probing point (which is also the first after the first Y move), a figure of 6000 for me didn't show any issues.

I have tested this workaround for more than a month on two Ender 3's with SKR v1.3 and 3D Touch v2 (and Pi 3B). Previously, I have always had regular failures when performing ABL (at least 1 in 3-5 prints) where the probe would not trigger (but blink red immediately) and the nozzle would crash into the bed, were it not for the mechanical Z end-stop I left on purpose. And I have tried most, if not all, permutations of the probing/BL Touch configurations in Marlin 2.0.x.
Since I have had 0 failures during countless probings during these weeks (both M48 and many actual prints), I have to deem this workaround a clear success in my case. I will, of course, update my findings should the results change.
I have also tested that it works independent of XY probe speed (tried 6-8-10000 mm/s), Z probe speed and without disabling heaters/steppers during probing. Basically, probing setup in Marlin seems no longer a factor for avoiding failures (but may still impact precision, at least the Z speed is).
Only issue is that the LCD's backlight (5V) blinks temporarily during probing if its 5V is drawn from the SKR, likely indicating a voltage drop due to the probe's current consumption (but did not want to isolate and probe the whole thing with my scope). Thus, I wired 5V to the Pi instead (but could just as well be any external 5V source) with two GND wires spliced near the probe, one running to the SKR and the other running to the Pi (for a poor man's star ground).

@mlehnhoff
Please test the bugfix-2.0.x branch to see where it stands.

I will be testing this shortly on my genuine BLTouch, I believe I have the same issue.

Edit: Not the same board (STM32F103RC ) but identical issues! Trying to figure out if its a timing issue or something else! But when doing a 91 UBL mesh I get maybe 1 or 2 failed probes in the same way as described here?

Well I figured out my board seems to be using the 'shared' servo code. I have added the below after some trial and error and it seems safe_delay of 6ms/us? is working! The sensor seems to trigger quicker if that makes any sense? And I have now managed to get my first mesh without any sensor fails? Will keep an eye on it and run more test but initially looks promising! This is with a genuine BLTouch, I had ordered a second one thinking it was faulty! I dont think its other hardware as this setup was working fine on the original stock board, only since moving to BTT V2.0 and Marlin has this issue occurred. Previously I was running Klipper with no issues.

if ( (servoIndex == 0) && ( extDigitalRead(SERVO0_PIN) == 1 ) ) { safe_delay(6); }

@aslater3 How can I tell if my board (SKR Mini E3 v1.2) has 'shared' servo code?

@boelle sorry i was quite busy with different things. I just tested the latest bugfix-2.0.x (which seems to be 2.0.5.4). The issue is still present. That is because it is still not fixed in pio-framework-arduino-lpc176x.
But i have access to an oscilloscope now an i am willing to investigate it further (and eventually fix it)...

2.0.5.4 (2.0.x) and bugfix-2.0.x are two different branches. Please try the latest bugfix-2.0.x and let us know if you're still experiencing this issue.

2.0.5.4 (2.0.x) and bugfix-2.0.x are two different branches. Please try the latest bugfix-2.0.x and let us know if you're still experiencing this issue.

Yes I know and I did use the latest bugfix-2.0.x! 2.0.5.4 is only what the LCD menu tells me

But this does not matter anyways, because the bug is not inside the MarlinFw Code it is inside the pio-framework-arduino-lpc176x

It is even well known which part of the code is causing the issue: the disabled latching of the HW-PWM.

The problem is to find a way to re-enable the latching without having other problems. This is why the latching has been disabled.

I was chatting with @p3p about this, since I've been investigating similar problems on other platforms. I don't think there is any chance this behavior has been changed, and it's not really worth the effort to re-test right now, unless as part of actually implementing a more permanent solution.

2.0.5.4 is only what the LCD menu tells me

Then you are not using the latest bugfix. Your LCD will say bugfix-2.0.x.

I'm aware of the 1 period glitch when setting a shorter duty cycle after already passing the new match value, currently I'm not sure how to mitigate the issue. The hardware does not appear to do what it is supposed to do when the pwm shadow registers are enabled.

2.0.5.4 is only what the LCD menu tells me

Then you are not using the latest bugfix. Your LCD will say bugfix-2.0.x.

okay, my bad, i accidentially cloned the branch 2.0.x instead of bugfix-2.0.x... now i fixed that -> no difference (of course)

I'm aware of the 1 period glitch when setting a shorter duty cycle after already passing the new match value, currently I'm not sure how to mitigate the issue. The hardware does not appear to do what it is supposed to do when the pwm shadow registers are enabled.

@p3p Can you please tell me, what issues you experienced, when you had latching enabled?

From what I remember (it's been a long time since I was debugging this), with the shadow registers enabled the pulse width would sporadically not update at all, as you can imagine I chose the 1 period glitch rather than that. It seemed to possibly be caused by updating the pulse width more than once in the same period but I wasn't sure.

A commanded servo angle has to stay at least 20 ms to be visible on the output as a changed pulse width.
To make the new pulse width recognizable by the device/servo it likely needs to stay several pulses.
So changing the angle within at least 20 ms has to be forbidden.
From what @sjasonsmith found out for the BL_Touch and pointed out in https://github.com/MarlinFirmware/Marlin/issues/18598#issuecomment-657406598 better about 60 ms.

Updating the shadow register more often does not make sense. The register should not be written more often than the angle value changes. (Shadow variable for the shadow register?)
Likely it needs an additional patch at a higher level of the servo library to prevent too frequent changes. We already have something similar withSERVO_DELAY, originally ought for preventing the servo signal shutdown before the servo (mechanically) arrives its target.

@AnHardt I know that changing the shadow registers multiple times per period is pointless but I don't see why changing them multiple times before the values are pushed to the real registers on the period end would cause a problem, I'm not sure what the solution to stopping the client application updating the hardware PWM too often would be (if that really is the issue), without a significant performance hit in one way or another anyway.

@AnHardt I know that changing the shadow registers multiple times per period is pointless but I don't see why changing them multiple times before the values are pushed to the real registers on the period end would cause a problem,

I also don't know why or if there is a problem. But if you tell us it causes problems we should try to avoid it.
A construct like:

static float last_servo_angle = 0.0f;
if (servo_angle != last_servo_angle) {
  set_servo(sevo_angle);
  last_servo_angle = servo_angle;
}

would at least prevent writing multiple times to the shadow register with the same value.

If i remember correctly, the last time i touched the SERVO_PROBE code, before the BL-Touch appeared, i carefully avoided moving the servo and the steppers at the same time with syncs - but i always tested with DEACTIVATE_SERVOS_AFTER_MOVE, because my servos jittered when the stepper was moving, producing a SERVO_DELAY (a few hundred ms) pause after setting the servo_angle. Compared to that the much shorter delays i suggest now are a win in performance.

If the BL-Touch code tries to move servo and steppers at the same time that does not feel to me like the ball i have to play.

Because the BL-Touches want to have a constantly on servo signal DEACTIVATE_SERVOS_AFTER_MOVE is not possible. For the interrupt driven servo libraries a delayed interrupt became catastrophic, messing up the servo signal. A hardware driven PWM would be immune. Usually we have only one servo.

However, i'm quite sure a set_servo(0); set_servo(180); set_servo(0); without pauses will cause absolutely no reaction - neither on a real servo, nor on a BL-Touch.

Sorry. Likely my thoughts are to much focused to hardware PWM, at the moment, where the timers compare register only has to be updatet every now and then.

Sorry. Likely my thoughts are to much focused to hardware PWM, at the moment, where the timers compare register only has to be updatet every now and then.

This problem is with the Hardware PWM, and I agree with everything you said, I was just thinking of the problem at the framework level, as in how to make the hardware work reliably even when the client application is doing crazy amount of updates (Marlin) in the same period. The client will expect the last update to take effect, rather than the first, and I have no way of knowing that there are not going to be subsequent updates before the end of the period.

I'l have to look again at the problem to see if a new solution comes to mind, and if that diagnoses is actually correct and I wasn't just being stupid.

I'd try
when to short lasting positions can be omitted:

servo_update(angle) only updates a volatile variable lets say inter_angle.

an interrupt, either overflow or compare could be:
{  
  static uint32_t counter = 0;
  static uint16_t last_inter_angle = 0;
  if (counter++ > 3) { // if counter should overflow there is a small risk of delaying another 3*20 ms. Every ~55min if 16 bit.
    if (inter_angle != last_inter_angle) { // if counter above 3 the update will be immediate when inter_angle changed.
      update_shadow_compare_register(inter_angle);
      counter = 0;
      last_inter_angle = inter_angle;
    }
  }
}

running about every 20 ms.
That should hold the output puls length constant for at least 3*20 ms and then put in the newest commanded angle only. However it will not know what angle comes next or if an update will follow at all - that's impossible to know - some when you will have to begin. It youst warrants the send pulses can be read and the shadow register is not updated very often.

To warrant each and every update is done for at least that time the volatile variable has to be replaced by a queue.

In RC-flying the intermediate positions can likely be omitted. In case of BL-Touch stowing, deploying, resetting, changing_modes, ... is all equally important. Noting of this can be omitted, every command hast to stay long enough to be recognized. There is no universal right solution for a universal servo library.

Additionally for the BL-Touch all commands have to be in sync to the steppers moves. Retracting the probe while going down for the probe should better be omitted. :-)
So from my point of view Marlin must be responsible for not updating the angle to frequent.


Edit:
Likely the compare interrupt is the right one to update the shadow compare register. The interrupt could then be delayed by higher priority interrupts by about 17ms and still would be in time to have the update-register ready for the copy to the compare-register when the overflow occurs.
Should be possible to stop the interrupt if the counter is above 3. Could the be restarted when inter_angle is updated.

I'm having the same problem with the SKR mini 1.1.
No matter what position i put, the servo always go to same point.

https://www.youtube.com/watch?v=HVyaKdpJsP0

1
2

@Matheusschmitz the SKR mini uses a different platform and would be unique from this issue. Some changes went in a little over a week ago to improve BLTouch reliability for STM32F1 boards (like yours). Please try using the bugfix-2.0.x branch to see if it resolves your issue.

If you still have problems please go discuss at one of the support venues such as Discord. This particular issue should remain focused on LPC176x boards.

I also run into this issue with my SKR1.3 and BLTouch clone.
I have managed to capture it on video, right around the 1:54 mark:
https://www.youtube.com/watch?v=wF0Mia49ECI&t=114s
(video is 1080p YouTube has to process it)

Here's also an image showing what it does when it happens during UBL
more points

I have tried, like others, the various settings that could help, they didn't help.
I am on the latest bugfix-2.0.x branch

Same issue on my side.
I will test the workaround as well

This issue has had no activity in the last 30 days. Please add a reply if you want to keep this issue active, otherwise it will be automatically closed within 7 days.

I think this is worth keeping open until a permanent solution can be found.

I agree with that sentiment

This issue has had no activity in the last 30 days. Please add a reply if you want to keep this issue active, otherwise it will be automatically closed within 7 days.

I think this issue should be keep open.

Was this page helpful?
5 / 5 - 1 ratings

Related issues

ahsnuet09 picture ahsnuet09  ·  3Comments

ShadowOfTheDamn picture ShadowOfTheDamn  ·  3Comments

esenapaj picture esenapaj  ·  3Comments

heming3501 picture heming3501  ·  4Comments

Anion-anion picture Anion-anion  ·  3Comments