Fast filament motion sensor does not keep up - false triggers

Basic Information:

Printer Model: Ender 3 heavily modified
MCU / Printerboard: STM32G0B1RE / BTT Manta E3EZ
klippy.log
klippy.zip (819.8 KB)

Fill out above information and in all cases attach your klippy.log file (use zip to compress it, if too big). Pasting your printer.cfg is not needed
Be sure to check our “Knowledge Base” Category first. Most relevant items, e.g. error messages, are covered there

Describe your issue:

I’m building a custom filament motion sensor. It’s using an encoder wheel, the same principle from computer ball mouses: an optical sensor is turned on and off by the encoder wheel. The sensor is connected to the filament sensor on my Manta E3EZ board, it worked before on the Creality 4.2.2, and it’s working since several weeks with the previous version of the sensor.
For the previous one the encoder wheel had a diameter of 18mm and 20 light holes. So by running ~54mm of filament the sensor sent 20 on/off impulses to the board, that’s one for every 2,67mm. With a setting of detection_length: 5.0 it worked just fine.
The current version has a higher resolution. What I have now is 50 impulses from the same optical sensor (Lerdge type) for every ~9mm, that would be an impulse for 0,2mm of filament. And it’s not working very well. Even with the setting of detection_length: 2.0 Klipper detects a runout at every couple minutes of print. And no, it’s not slipping. I’ve printed a 150mm test cube, making a video in slow motion, and counted the number of times the onboard LED lit up. It was consistent with my calculations, 35-36 triggers for each side, in line with the almost 7mm of filament used. At a printing speed of 50mm/sec one side would print in about 3 seconds (acceleration and deceleration not included), that’s a cadence of rough 10 triggers per second.
Is it possible that Klipper doesn’t keep up with the shorter and more frequently impulses for the filament motion sensor pin? I know that Klipper can monitor fan tachometers, those are really fast, but how about the filament motion sensor pin? How often does it look at it? It could be the speed, it could be the length of the impulse.
The rationale for a higher resolution sensor is on one hand that when printing with a 0.2 nozzle the detection_length of more than 7mm on the usual filament sensors like BTT’s is simply not good enough, ruining the print anyway; on the other hand fast printers are pretty common these days, and they eat filament like crazy.

I’m building a high resolution filament sensor myself (GitHub - EiNSTeiN-/roadrunner-filament-sensor: High resolution filament sensor for 3D printers based on the AS5600 magnetic rotary encoder) and while I’m not using Klipper’s filament_motion_sensor code I used it as a base, and I believe I accidentally stumbled on the answer to your problem.

The motion sensor code calls self._get_extruder_pos(eventtime) which itself ends up calling self.extruder.find_past_position(print_time) every so often to get the estimated extruder position at a given point in time. When an extrusion is requested we should see the extruder accelerate up to speed and maintain a constant speed until the move is done and find_past_position catches up to the requested position. Calling find_past_position repeatedly and graphing the results should produce an approximately straight line going up with a constant slope.

The issue I’m noticing is when I request a long extrusion move, let’s say for example with G1 E45 for the first few seconds find_past_position returns a large value, e.g. it will return 5 for the first 3 seconds right after the G1 command and afterwards start returning linearly increasing values until the 45mm is fully extruded. In other words at the beginning of a move there is a large jump in the expected extruder position which doesn’t catch up to reality for a few seconds.

Going back to your issue, I believe there might be a pulse from your sensor right before a long move occurs, at which point this code is executed:

self.filament_runout_pos = (
                self._get_extruder_pos(eventtime) +
                self.detection_length)

Which means the filament is detected as “present” as long as self._get_extruder_pos(eventtime) < self.filament_runout_pos. Now because of the behavior I explained above with find_past_position, the estimated extruder position can increase by a value larger than detection_length at the beginning of an extrusion move and trigger the runout code.

Here’s a graph of the problem:

In green you can see the “commanded” move, i.e. the toolhead position which is way ahead of reality since the position changes immediately at the beginning of a move.
In purple the return value from extruder.find_past_position(print_time) taken every 100ms.
In blue you can see readings from my filament sensor at 100ms interval which matches the actual extruder movement closely.

The graph shows three consecutive G1 E45 commands at low speed (~1.3mm/s). You can see the problem very clearly, at the start of a G1 move there’s a discontinuity where the value returned by find_past_position jumps ahead to ~3mm instead of sloping nicely up as we see for the rest of the move.

So can a software modification change the behavior to be accurate and correct?

FYI, there were some changes and some proposed changes to the code recently that may impact the report here:

-Kevin

Thank you!
Hopefully I will test my filament sensor on his full potential in the future (Now it’s running with the handbrake pulled) :slight_smile:

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.