• Tags
  • Documentation
  • Order
  • Register
  • Login
Duet3D Logo Duet3D
  • Tags
  • Documentation
  • Order
  • Register
  • Login

Pressure advance and variable flow ratio

Scheduled Pinned Locked Moved
Firmware wishlist
6
14
1.7k
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • undefined
    trchen
    last edited by 16 May 2022, 17:19

    TLDR; I think the speed matching algorithm in the motion planner should favor matching the extruding velocity if applicable, instead of the combined speed, to prevent over/under-extrusion on flow ratio change.

    Dear RRF developers,

    Recently I've been investigating bridging quality issues on my RRF Voron printer. The symptom is that the beginning or bridges are always heavily under-extruded to the point that half of the time it collapses for being too thin. I made a simple bridge STL trying to troubleshoot the issue:
    bridge.png
    This is designed to test the scenario where a perimeter enters bridge without turning. I tried to adjust target printing speed so that it maintains a constant volumetric flow rate, but the problem persists. The only way I could get acceptable bridges is to reduce bridge speed to very low value (< 15mm/s).

    I believe the problem is due to the speed matching algorithm trying to match combined speed instead of extruding velocity, this caused instantaneous extruding velocity change that is impossible to compensate by pressure advance.

    void DDA::MatchSpeeds() noexcept
    {
            for (size_t drive = 0; drive < MaxAxesPlusExtruders; ++drive)
            {
                    if (directionVector[drive] != 0.0 || next->directionVector[drive] != 0.0)
                    {
                            const float totalFraction = fabsf(directionVector[drive] - next->directionVector[drive]);
                            const float jerk = totalFraction * beforePrepare.targetNextSpeed;
                            const float allowedJerk = reprap.GetPlatform().GetInstantDv(drive);
                            if (jerk > allowedJerk)
                            {
                                    beforePrepare.targetNextSpeed = allowedJerk/totalFraction;
                            }
                    }
            }
    }
    

    For example, let's say we have target perimeter speed of 60mm/s. Assuming 0.41mm extrusion width and 0.20mm layer height, the target flow rate would be 4.92mm^3/s. To maintain a constant volumetric rate, the bridge speed needs to be 39mm/s. Example:

    M83
    G0 X0
    G1 X10 E3.409 F3600
    G1 X20 E5.224 F2349
    

    However, IIUC, constant flow rate is not going to happen with the current motion planner implementation, even if XY jerk limits permit it. The behavior is to pick the slower of the two as the target transition speed, then verify if the direction change is permitted by jerk limits. In this case, the transition speed would be F2349, thus causing a mismatch in extrusion velocity, which can't be compensated by pressure advance because it requires instantaneous position change.

    This can be mitigated by setting an artificially low E jerk value, so that MatchSpeeds returns a low transition speed. However that is not ideal because it basically causes such transition to always grind to a halt, and also limit acceleration to an extreme low value due to this in DDA::InitStandardMove:

                                    if (flags.xyMoving && nextMove.usePressureAdvance)
                                    {
                                            const float compensationTime = reprap.GetPlatform().GetPressureAdvance(LogicalDriveToExtruder(drive));
                                            if (compensationTime > 0.0)
                                            {
                                                    // Compensation causes instant velocity changes equal to acceleration * k, so we may need to limit the acceleration
                                                    accelerations[drive] = min<float>(accelerations[drive], reprap.GetPlatform().GetInstantDv(drive)/compensationTime);
                                            }
                                    }
    

    I think this double usage of E jerk is a mistake. It makes no sense because not only it's being applied twice, but also it is applied in different spaces. In DDA::MatchSpeeds() it is being applied to pre-pressure-advanced velocity, while in DDA::InitStandardMove is being applied to pre-pressure-advanced acceleration, i.e. post-pressure-advanced velocity.

    IMO the two usage of the E jerk values really should have used separate variable. Or for the sake of simplicity, I propose that the allowed E jerk during DDA::MatchSpeeds really should have been 0, and we should allow the combined speed between the current move and the next move to mismatch, as long as jerk limit permits. In fact the behavior will be identical to current implementation when flow ratio remains constant, because matching extrusion velocity implies matching combined speed when flow ratio is constant.

    undefined 1 Reply Last reply 14 Jun 2022, 16:08 Reply Quote 4
    • undefined
      trchen
      last edited by 17 May 2022, 03:23

      Here's a benchmark I made to demonstrate the issue. The test prints 4 lines:

      #4 A line with 0.41mm --> 0.72mm --> 0.41mm transition, same target speed, with pause in between
      #3 A line with 0.41mm --> 0.72mm --> 0.41mm transition, variable target speed, constant target flow rate
      #2 A line with 0.41mm --> 0.72mm --> 0.41mm transition, constant target speed
      #1 A constant width line with variable speed. To demonstrate the pressure advance value being appropriate.
      (Printed from bottom to top.)

      E-jerk_test.jpg

      In theory if pressure advance is working properly line 2, 3, 4 should be printed identically. But in the actual result the top line #4 has the sharpest transition. Line #3 and #2 has transition delayed towards the right and averaged out.

      My apologies that I only have a coarse textured build plate. It should be more obvious when printed on a flat plate. Here's the gcode for you to reproduce the issue.
      E_jerk_test.gcode

      G21 ; Millimeter units
      G90 ; Absolute XYZ
      M83 ; Relative E
      T0 ; Switch to tool 0
      M190 S105 ; Set bed temperature (wait)
      M109 S250 ; Set nozzle temperature (no wait)
      M204 S1000 P1000 ; Acceleration
      M572 D0 S0.05 ; Pressure advance
      
      ; Purge line
      G1 X50 Y50 Z0.2 F18000 ; move to start
      G1 X50 Y100 E2.754 F3600
      G1 X50.72 Y100 E0.040
      G1 X50.72 Y50 E2.754
      G1 E-0.2 F2400 ; Retract
      
      ; Line 1: Same line width, different speed
      G1 X75 Y50 F18000
      G1 E0.2 F2400 ; Unretract
      G1 X125 E1.568 F1200
      G1 X175 E1.568 F3600
      G1 X225 E1.568 F1200
      G1 E-0.2 F2400 ; Retract
      
      ; Line 2: Different line width, same speed
      G1 X75 Y60 F18000
      G1 E0.2 F2400 ; Unretract
      G1 X125 E1.568 F3600
      G1 X175 E2.753 F3600
      G1 X225 E1.568 F3600
      G1 E-0.2 F2400 ; Retract
      
      ; Line 3: Different line width, maintain volumetric rate
      G1 X75 Y65 F18000
      G1 E0.2 F2400 ; Unretract
      G1 X125 E1.568 F3600
      G1 X175 E2.753 F2050
      G1 X225 E1.568 F3600
      G1 E-0.2 F2400 ; Retract
      
      ; Line 4: Different line width, same speed, with pause
      G1 X75 Y70 F18000
      G1 E0.2 F2400 ; Unretract
      G1 X125 E1.568 F3600
      G4 P1
      G1 X175 E2.753 F3600
      G4 P1
      G1 X225 E1.568 F3600
      G1 E-0.2 F2400 ; Retract
      
      ; Indicator lines
      G1 X125 Y75 F18000
      G1 E0.2 F2400 ; Unretract
      G1 Y95 E0.627 F3600
      G1 E-0.2 F2400 ; Retract
      G1 X175 Y75 F18000
      G1 E0.2 F2400 ; Unretract
      G1 Y95 E0.627 F3600
      G1 E-0.2 F2400 ; Retract
      
      ; Lift Z
      G1 Z10 F300
      
      undefined 1 Reply Last reply 14 Jun 2022, 08:45 Reply Quote 4
      • undefined
        Argo @trchen
        last edited by Argo 14 Jun 2022, 08:45

        I don't know if "Firmware Wishlist" is the right place for this as this looks to me like a unwanted behaviour of pressure advance.

        Printer: Voron 2.4
        Extruder: LGX (not lite)
        Board: Duet 3 Mini 5+
        FW: 3.4.1

        1. Pressure Advance PLA test pattern with high speeds (60mm/s to 160 mm/s at 4.000mm/S acceleration):

        1641551232003-img_0801.jpg

        Result are looking good at PA 0.06.

        1. But the print then looks like this with bulging corners (external perimeter speed at 80 mm/s, 1.200 mm/s acceleration):

        1641551242229-img_0872.jpg

        1. To get rid of the bulging corners I further increased PA (0.1) to the extend that infill lines don't connect anymore with perimeter:

        1637676609312-img_0512.jpg

        Heavily increase infill overlap to 200% or so would "solve“ this but that causes other artefacts / issues. So that is not really a solution imo.
        I saw this behaviour since the RRF 3.4 beta6(?). With RRF 3.3 corners were sharp(er). I'm using input shapers and I know that PA has to be retuned, hence the test pattern above.

        @dc42 Maybe you could please take a look at this? Normally I would not ping you but I recon RRF isn't the community were people always directly update to the newest version (RRF 3.4) when the printer is running fine. Thanks!

        oliofundefined 1 Reply Last reply 20 Jun 2022, 16:58 Reply Quote 0
        • undefined
          mikeabuilder
          last edited by 14 Jun 2022, 13:27

          @Argo - quick question (followed by no additional insight, I'm just trying to understand more on this topic since I'm trying to tune PA and IS on my machine). My question is the units on you acceleration on pictures 1 and 2 - your units are mm/S, and the value is 1.2 or 4. The value seems extremely low if the acceleration units are actually mm/sec^2. Or is this acceleration really a jerk value (mm/s per Step?)

          undefined 1 Reply Last reply 14 Jun 2022, 14:49 Reply Quote 0
          • undefined
            trchen @mikeabuilder
            last edited by 14 Jun 2022, 14:49

            @mikeabuilder I think he mean 1200mm^2/s and 4000mm^2/s. The dot is the digit delimiter, not decimal point.

            1 Reply Last reply Reply Quote 1
            • undefined
              mikeabuilder
              last edited by mikeabuilder 14 Jun 2022, 15:23

              @trchen - well, that makes a lot of sense.

              1 Reply Last reply Reply Quote 0
              • undefined
                trchen @trchen
                last edited by 14 Jun 2022, 16:08

                I think Firmware wishlist is probably not the right place for this post. It is not really a new feature, but more of tweaking.

                My apologies for tagging you directly, @dc42, just want to make sure you are aware of it. We have a few users at Voron Discord who suffered from PA-related issues that is specific to RRF.

                I did some more experiment afterwards. I wrote a SuperSlicer postprocessing script to insert a short pause G4 P1 (basically forcing RRF to decelerate to 0) when flow ratio changed by more than 5%. It mitigated my bridging problems even if printing at normal bridging speed (75mm/s). It is only circumstantial evidence but I think it's worth some investigation.

                Here's my SS script if anyone's curious:

                #!/usr/bin/python3
                
                import sys
                from io import StringIO
                from math import hypot
                
                THRESHOLD = 1.05
                
                x = y = None
                e_rate = 0.0
                buffer = StringIO()
                for line in open(sys.argv[1], "r"):
                	if not line.startswith("G1 "):
                		buffer.write(line)
                		continue
                
                	dx = dy = de = 0.0
                	for clause in line.split():
                		if clause[0] == "X":
                			if x is None:
                				dx = None
                			else:
                				dx = float(clause[1:]) - x
                			x = float(clause[1:])
                		elif clause[0] == "Y":
                			if y is None:
                				dy = None
                			else:
                				dy = float(clause[1:]) - y
                			y = float(clause[1:])
                		elif clause[0] == "E":
                			de = float(clause[1:])
                
                	if dx is None or dy is None:
                		buffer.write(line)
                		continue
                
                	dxy = hypot(dx, dy)
                	if dxy < 0.00001:
                		new_e_rate = 0.0
                	else:
                		new_e_rate = de / dxy
                
                	if e_rate == 0.0 or new_e_rate == 0.0:
                		pass
                	else:
                		ratio = new_e_rate / e_rate
                		if ratio >= THRESHOLD:
                			buffer.write("G4 P1\n")
                
                	buffer.write(line)
                	e_rate = new_e_rate
                
                with open(sys.argv[1], "w") as f:
                	f.write(buffer.getvalue())
                
                undefined 1 Reply Last reply 18 Jun 2022, 08:05 Reply Quote 2
                • undefined
                  Argo @trchen
                  last edited by 18 Jun 2022, 08:05

                  @droftarts could you please move this thread to a more suitable category? Hopefully someone will then take a look at this. Thanks!

                  droftartsundefined 1 Reply Last reply 18 Jun 2022, 09:28 Reply Quote 0
                  • droftartsundefined
                    droftarts administrators @Argo
                    last edited by 18 Jun 2022, 09:28

                    @argo it needs @dc42 to look at it. I’ll highlight the thread to him on our internal comms. We don’t really have a ‘firmware issues’ category, so here is fine.

                    Ian

                    Bed-slinger - Mini5+ WiFi/1LC | RRP Fisher v1 - D2 WiFi | Polargraph - D2 WiFi | TronXY X5S - 6HC/Roto | CNC router - 6HC | Tractus3D T1250 - D2 Eth

                    dc42undefined 1 Reply Last reply 20 Jun 2022, 10:46 Reply Quote 2
                    • dc42undefined
                      dc42 administrators @droftarts
                      last edited by 20 Jun 2022, 10:46

                      @trchen thanks for sharing your thoughts. Have you tried building a version of the firmware with permitted extruder jerk set to zero in DDA::MatchSpeeds? If you haven't, would you like me to build one for you?

                      Duet WiFi hardware designer and firmware engineer
                      Please do not ask me for Duet support via PM or email, use the forum
                      http://www.escher3d.com, https://miscsolutions.wordpress.com

                      undefined 1 Reply Last reply 21 Jun 2022, 15:17 Reply Quote 0
                      • oliofundefined
                        oliof @Argo
                        last edited by 20 Jun 2022, 16:58

                        @argo just a side note that I am not surprised RRF3.4 with IS does cause rounded corners because that's what IS effectively is for -- smoothing out the movement so it's not a sharp direction change that induces ringing. If you disable IS in 3.4, do you regain the sharp corners?

                        <>RatRig V-Minion Fly Super5Pro RRF<> V-Core 3.1 IDEX k*****r <> RatRig V-Minion SKR 2 Marlin<>

                        undefined 1 Reply Last reply 20 Jun 2022, 19:19 Reply Quote 1
                        • undefined
                          Argo @oliof
                          last edited by Argo 20 Jun 2022, 19:19

                          @oliof

                          Input Shaping only has marginal effect on how the corners do look like. I did tests with and without IS.
                          I did also play around with different jerk settings (5 mm/s up to 15 mm/s) and the result is also pretty much the same.

                          For testing purposes I would like to revert back to RRF 3.3 but it seems the 1LC rev 1.1 is not supported by RRF 3.3 because I can't activate the heater. As far as I remember I did not have this issue with RRF 3.3 but that can still be a coincidence.

                          Edit: I'm not sure the issue I'm having is related to the findings of trchen and I don't want to hijack his thread, so I'm creating a new one with my findings.

                          1 Reply Last reply Reply Quote 1
                          • undefined
                            trchen @dc42
                            last edited by 21 Jun 2022, 15:17

                            @dc42 I haven't, but I'm happy to try! I predict it will have similar effect as my slicer postprocessing script. I'll do an experiment to see if it reinforces or disproves our theory.

                            undefined 1 Reply Last reply 22 Jun 2022, 04:56 Reply Quote 0
                            • undefined
                              trchen @trchen
                              last edited by 22 Jun 2022, 04:56

                              I just got my build environment set up. I will be busy at work this week, probably will start my experiments over the weekend.

                              The first experiment would be hardcoding the E jerk during MatchSpeeds to some small value and see how bridges behaves.
                              (The jerk value can't be zero due to FP errors. Something like 0.01 is probably more reasonable. I feel MinimumJerk==0.1 may still be high for extruders.)

                              I still haven't think through what a better jerk policy should be. Allowing the total speed to mismatch between two moves doesn't feel right either because multiple rapid small moves could rack up a lot of speed change in small amount of time.

                              On the other hand, what's so different with the policy we have today? With the current jerk policy you can make a lot of small moves to form very small turn radius, effectively bypassing the acceleration limit. For example, Gyroid infills are notoriously demanding for acceleration. I suspect we are actually able to cheat by breaking down curves to multiple small moves, by setting "Slicing --> Filtering --> Internal resolution" smaller in the slicer.

                              An idea I have in mind is to maintain a "jerk potential" which is recharged at the rate of acceleration while capped at the jerk maximum. Once the jerk potential is depleted no more instantaneous speed change is allowed.

                              1 Reply Last reply Reply Quote 2
                              • undefined Argo referenced this topic 29 Oct 2022, 19:14
                              • First post
                                Last post
                              Unless otherwise noted, all forum content is licensed under CC-BY-SA