Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linear fan kickstart time #27072

Open
wants to merge 5 commits into
base: bugfix-2.1.x
Choose a base branch
from

Conversation

vovodroid
Copy link
Contributor

Description

Set kickstart time linearly based on the speed, e.g. for 20% (51) it will be FAN_KICKSTART_TIME * 0.2.

Benefits

Fan speed will not overshoot target speed for low values.

@thisiskeithb
Copy link
Member

The entire point of FAN_KICKSTART_TIME is to get the fan up to a reliable speed / overcome the initial potential stall (if you don’t tune FAN_MIN_PWM @ 1% fan speed for example) before setting the requested speed, so why would you want to reduce it?

The original FAN_KICKSTART_TIME is still desired no matter what your set fan speed is.

@vovodroid
Copy link
Contributor Author

why would you want to reduce it?

My point is to apply full power to reach the target speed ASAP, not just to overcome initial inertia and friction.

@thisiskeithb
Copy link
Member

My point is to apply full power to reach the target speed ASAP, not just to overcome initial inertia and friction.

That’s exactly what FAN_KICKSTART_TIME and FAN_KICKSTART_POWER is for. It’ll run your fan at the configured kickstart time @ power (if defined) before setting the desired speed.

The fan’s required kickstart time / power doesn’t magically become less if you request a lower speed.

@vovodroid
Copy link
Contributor Author

As I saw in the code and from the tests FAN_KICKSTART_POWER is always applied FAN_KICKSTART_TIME, disregarding what is the target speed is, isn't it?

I have 5015 blower fan, taking about 0.8 sec. to reach full speed at full power, and approximately 0.4 sec. to reach 50% speed at full power. If I set FAN_KICKSTART_TIME to value like 0.1 sec. and target speed 50%, it takes more time to reach 50% speed. But if I set FAN_KICKSTART_TIME to higher values, fan overshoot lesser speeds like 10-20%.

Setting full power and kickstart time according to desired speed produces much more accurate results.

@mh-dm
Copy link
Contributor

mh-dm commented May 11, 2024

I like the idea of applying full power for a short period to help the fan reach its target speed quicker. Since @thisiskeithb has a different take on how FAN_KICKSTART should be calibrated and used (which I agree with), may I suggest changing this PR to work outside kickstart scenarios?

As this PR is currently implemented, it can only improve the 0 to target transition time (where 0 < target <= 1). Whereas it would be neat to also improve the current to target transition times. I suggest we call a short application of full (or zero!) power "fan overdrive" as a parallel to the "overdrive" feature in lcd monitors, that in a somewhat similar manner speeds up grey-to-grey (g2g) pixel transitions.

To calibrate such a fan overdrive feature, I think you'd only need to measure the time it takes for the fan to almost hit 100%, say fan_max_time_ms.

For 0 <= current < target < 1:

  • hold FAN_MAX_PWM for (target-current) * fan_max_time_ms

For 0 < target < current <= 1:

  • hold FAN_MIN_PWM for (current-target) * fan_max_time_ms

Note the math is simplified. In the current < target case I think (target-current)/sqrt(1-current) * fan_max_time_ms would be closer to the real physics since the closer we are to 100% the less the 100% overdrive actually helps in getting to the target, probably with a quadratic component. I guess we could make a constant torque per volt assumption and that the fan load increases quadratically with the speed and do the math... But that's splitting hairs and a simple linear model like in the original PR is probably good enough.

@vovodroid
Copy link
Contributor Author

Actually accelerating/decelerating curve is more complicated than linear or sqrt, it looks more like something logarithmic.

Spinning up from 0 to 100 with full power takes about 3.5 sec., reaching almost full speed within 2.5 sec.:
image

Coming to full stop also taking 3.5 sec, but almost full deceleration happens within about 0.6 sec.:
image

Real challenge is start fan before M106 command is placed in gcode, to ensure fan is running in destination point. Assuming we have fan set for overhangs, but not for the whole model:

image

But I'm not sure it's feasible.

@mh-dm
Copy link
Contributor

mh-dm commented May 11, 2024

Spinning up from 0 to 100 with full power takes about 3.5 sec., reaching almost full speed within 2.5 sec.
Coming to full stop also taking 3.5 sec, but almost full deceleration happens within about 0.6 sec.

Neat captures! If not already done, I'd recommend hard mounting a mic on the fan body for a clearer picture (and using an unbalanced fan).

Actually accelerating/decelerating curve is more complicated than linear or sqrt, it looks more like something logarithmic.

Well yes and no. The curves shown are freqs over time which correspond to rps over time. But that's not the full story because X% set fan_pwm does not translate to X% fan speed/rps/rpm. The curve we'd want is pwm_value over time, and my guess is that it's more linear.

Overall, if we want a better curve, more data is needed. If you're interested in taking this on I'd suggest capturing a 10%->20%->30%->..->100%->90%->..->10% stepped ramp (with just enough time in each step) to get a clear pwm_value to fan rps mapping. As a bonus we can see the transition time between steps.

Now two options:
A) With this stepped ramp capture and your above captures and some tedious data mapping you can plot the fan_pwm over time and solve for the fan overdrive time.
B) Implement linear fan overdrive and see how much that speeds up the 10%->20%->30%->..->100%->90%->..->10% stepped ramp, while picking a fan_max_time_ms that keeps overshoot low. Then if it sounds fun you can start playing the fan overdrive curve guessing game. My entry to said guessing game would be difference/sqrt(1-current) for spin up and linear for spin down.

Real challenge is start fan before M106 command is placed in gcode, to ensure fan is running in destination point. Assuming we have fan set for overhangs, but not for the whole model:
But I'm not sure it's feasible.

Not ideal but there's a "Speedup time" (superslicer) slicer option to move fan commands to earlier:
Screenshot from 2024-05-11 15-12-10
As for a solution in firmware, the planner buffer could in theory be used but it's not accurately timed (or even always correct, see my PRs).

@vovodroid
Copy link
Contributor Author

if we want a better curve

That's the question - whether we want it? Anyway there is speed up time, and thus distance between GCode command and real place where speed is reached, so I don't think square or logarithmic or whatever curve will improve comparing to linearly.

Anyway, now linearly kickstart is applied also for speed increase when fan runs, not only from zero speed.

there's a "Speedup time" (superslicer) slicer option to move fan commands to earlier:

Yes, I'm familiar with SuperSlicer. Idea is great, but often it produces weird results.

@mh-dm
Copy link
Contributor

mh-dm commented May 14, 2024

I suggest calling it something other than kickstart to avoid confusion.

@thinkyhead
Copy link
Member

thinkyhead commented May 17, 2024

The basic concept of a fan kickstart is quite simple. Apply a minimum power for a minimum time required to get the fan spinning, because some fans won't spin if you only tell them to go to 10% unless they get a kick of sufficient power and duration to overcome the initial holding torque of the magnetic motor.

This initial kick will be required for any fan speed that is set below the kickstart speed (not something we have formalized in code) and presumably all requested speeds above the kickstart speed don't need a kickstart. So, we should add code to handle that case.

Meanwhile there is the question of whether it makes sense to do a half as long kick to for a 10% final speed than for a 20% final speed, where both of these speeds are too low to get the fan spinning from stopped….

It seems to me that once you've established the minimum kick power and duration required to get the fan dislodged it should apply to all requests to go from zero to any speed below the kickstart speed, and the speed and duration of the kick should not change, because any change in the negative direction only increases the likelihood that the kick will fail. The last thing we want to do is combine added complexity with increased probability of failure.

On another note, we may not want to apply this to the Controller Fan. We definitely want that kick to always succeed, and there's no harm in too much kick here, so it should always do the full (i.e., minimal) configured speed and duration.

@vovodroid
Copy link
Contributor Author

we may not want to apply this to the Controller Fan.

Reverted, I just search for all FAN_KICKSTART_TIME usage, thus controller fan was affected. It will not harm to apply too long kick start time.

The basic concept of a fan kickstart is quite simple.

Sure, I would like to use its mechanism also to reach target speed ASAP, that could be good when fan is turned on for small details like overhangs.

#error "FAN_KICKSTART_POWER must be an integer from 64 to 255."
#if FAN_KICKSTART_TIME
#if ENABLED(FAN_KICKSTART_LINEAR) && FAN_KICKSTART_POWER != 255
#error "FAN_KICKSTART_LINEAR requires a FAN_KICKSTART_POWER of 255."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requirement can probably be removed by only kick-starting the fan when the power is set below FAN_KICKSTART_POWER, and then applying the time scaling based on fan_speed / FAN_KICKSTART_POWER.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants