Polar Printer: Scale velocity

Hi, quick background intro:
I built a polar printer and did some modifications to Klipper to make it print reliable. I’m currently trying to polish my code so it can be pushed into the main branch (hopefully :D). And to confirm, that my ideas are not completely stupid, I want to discuss some of them over the next few months here.

The Idea
Automatic scaling of velocity in the polar kinematic.

The Problem
If the printhead moves closer to the origin, the bed moves faster and faster until there is an MCU timer error, because the motor has to run too fast.

Scope
We ignore the elephant in the room: the “singularity” in the origin (0/0). I just want to print on all other points.

The Current Implementation
The speed and acceleration is currently adjusted, depending on the distance of the line to be travelled from the origin (dashed line in the picture). The scaling factor is calculated by dividing a “maximum rotational velocity”-variable from the config by the max rotational velocity component of the move. The latter is calculated by splitting the “max_cruise_v2” from the check_move(move) variable into R-velocity and rotational-velocity components.
Since this scaled every move, I clamped the value to a minimum velocity (so it will not go down to basically 0) and a maximum activation distance (green dotted line).

Current Problems

  • Every move coming too close to origin will be scaled → If you go from one side to the other, it will be scaled down and takes for ages. My current solution would be to split the moves, but I have no idea how to implement this properly into the polar kinematic. Maybe the new plugin system can be used, or an “extra” will be written.

Thx for reading, I hope for a fruitful discussion :slight_smile:

Interesting.

Scaling moves around the origin is something I’ve looked at briefly in the past. I think you point out some of the main difficulties (detecting moves near the origin, having to slow the entire move, and determining how much to slow).

One thing I’d be careful of is slowing moves by a variable amount. In my experience, when one changes the speed between nozzle and print it can have a noticeable impact on the print quality (for example, it changes the flow rate and impacts pressure advance). One possible solution would be to only slow moves that come within a relatively small distance of the origin. One could also slow to a given speed for a range of distances (such that minor changes in distance would likely be given the same speed). Thus encouraging similar speeds for the vast majority of moves.

It’s also possible to break up long moves into smaller chunks so that a single long move would not be painfully slow for its entire duration. As you’ve indicated, that does require some additional complexity.

I look forward to seeing your results.

Cheers,
-Kevin

2 Likes

The current implementation just scales the move, if a critical velocity is hit. Otherwise, nothing will be scaled, so it should just catch errors which might stop the print. But yeah, I see the problem with pressure advance and so on. I will keep you updated!

1 Like

This is pretty interesting, I didn’t know Polar printers were a thing. Sounds like a unique challenge. Seems like Polar printers would be a good candidate for a BLDC motor under the bed to handle the high accelerations needed.

Which reminds me… I’ve been wanting to build an Encoder/BLDC driven 3D Printer for a few years now. I might have to look back into that.

A BLDC would definitely solve some of the limitations I have currently :smiley:

1 Like

Hey! I wrote the code for prexz - armchair engineering’s polar corexz (i know, it’s actually polar corerz but that didn’t ring quite the same). I ended up solving this by segmenting moves into smaller moves based on a series of “milestone” radii - iirc, i halve the radius, then halve that, then continue until i’m within a set amount from zero. each time a move crosses one of these bounds, it’s split, and scaled accordingly. this gets us a reasonably decent approximation of stable velocity as we travel through the bed.

The prexz code is in a very rough state (was written across several manic, hyperfocus-driven nights and I haven’t had the motivation / time to go and clean it all up again) and is definitely nowhere near as performant as it could or should be, but you can find it in its entirety here: https://github.com/DangerKlippers/danger-klipper/pull/119

Also happy to talk about our solution for zero crossing if you’re interested, it seems to work pretty well!

2 Likes

Interesting idea! I think I will stay with my “continuous” approach, since then I can separate move splitting and speed scaling. But I will definitely salvage everything from your code as possible, :stuck_out_tongue: actually I already copied some of it from your armchair engineering repo.
I will definitely like to talk about your zero crossing approach, but in the future, in another post :smiley:

So I was looking at this a bit more and, maybe I’m dumb as I’ve never messed with a polar printer, but my thought was…

Why not invert the problem?

Set your maximum rotational velocity at a certain radius (very close to the origin), since really you wouldn’t need to even spin the printer at the true origin since it’s a point.

Then you scale your rotational velocity downwards as you move outwards.

Something like…

image

Where r(min) is your minimum radius (where omega is max)

I would THINK that your minimum radius would be dependent on your nozzle size/extrusion width that way you avoid a weird asymptote trying to get closer and closer to the origin.

Sadly, that does not really work for my application. The problem is, that it is too fast in the center and not the outside. So scaling down the outside values is not necessary. Also, nozzle parameters are mostly irrelevant, since it’s just a pure movement problem (either the timers are too close for the stepper or the load on the motor is too big).

Yes, Your max velocity is going to be dictated by the movement close to the origin.

That’s what I mean, I know the outer movement isn’t an issue. What I’m saying is, make sure the bed isn’t moving too fast for Klipper at it’s fastest (at the point near the origin) and then scale the speed down as you move out so that you have a normalized rotational speed at every radius.

Know what I mean?

ohhh, now I get it.
I dont’ think that is necessary. Since you could also do that in a slicer (basically print everything at 1mm/s or something like this).
What you describe is basically how I test my parameters.

You can’t scale your velocity in a slicer.

What I’m saying is…

Your bed motor can only spin so fast right?
It has a maximum angular velocity (𝜔) possible and trying to drive it any faster than that you get problems (like you’re experiencing).

What I’m proposing is to base all your kinematics around THAT fact.
Lets call it 𝜔_𝑚𝑎𝑥, the maximum rotational velocity of your bed motor.

Your LINEAR velocity is determined by…
image

Which is pretty straight forward, the larger the radius the larger the arc and the more distance traveled.

But the problem you’re running into is ANGULAR velocity, which with a little algebra is…

image

You already know this, but based on that equation, the smaller the radii (closer to the origin) the faster the bed needs to spin (angular velocity) for the same given LINEAR velocity.


So here’s what I propose, You figure out the 𝜔_𝑚𝑎𝑥 of your bed motor.

image

For fun lets say your motor (I’m assuming stepper) has a max usable RPM of 1000 RPM.

1000 RPM x (2pi/60) = 104.72 rad/s

Let’s assume you’re using a .4mm nozzle and a .4 extrusion width. Since you don’t need to spin the bed at the origin (0,0) because that’s a “point”, your next radius would be .6mm from the origin (.4 from the origin + (.4 * 1/2) to center the nozzle).

So your max angular velocity would need to be at a .6mm radius.

We already determined your max angular velocity is 104.72 rad/s.
Converting .6 mm to meters to match units (.0006)
.0006m x 104.72 rad/s = .062832 m/s or 62.832 mm/s MAX speed at .6mm MINIMUM radius

Now that you have a MAX speed for MINIMUM radius, you can scale outwards from there using

image

And thus you won’t ever outrun your bed motor

You can setup your Klipper config to work with these values if you ever change your nozzle diameter.

1 Like

ok, classic mix of misunderstanding and language barrier :smiley:
That is exacly how it is basically implemented.

Then how are you running into this issue? If you’ve already set your speed at a limit that won’t exceed what Klipper can handle?