-
-
Notifications
You must be signed in to change notification settings - Fork 386
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
Spindle ramping feature with fixed parameters. #295
base: main
Are you sure you want to change the base?
Conversation
Any ideas for how to configure it? |
Laser inherits from PWM without overriding I think this should be a new class inheriting from PWM. |
We thought two possible ways up to now:
|
Yes, we think so too. |
It is sort of like acceleration. |
We also do not accept PRs against main. https://github.com/bdring/FluidNC/wiki/Pull-Request-Guidelines |
So, the thing about Bresenham is that it hits the intermediate points as accurately as possible. That isn't a bad thing, but neither is it really necessary for a ramp-up to avoid overcurrent. Is there a simpler formulation that is good enough? |
Maybe something with a fixed step size with a fixed delay? |
If you treat it as a max acceleration problem instead of always inventing a ramp regardless of the total delta speed, then it looks rather different. Instead of bresenham you just have a max increment, and you keep adding or subtracting that until you reach the target. It seems to me that applying a ramp to small speed changes is pointless.
|
The parameter could be maximum percentage change per step, with the spinup delay giving the time to change 100%. So if %change is 10% and spinup delay is 3 seconds, each step takes 300 ms. |
Hi @MitchBradley, I will try it with a bit of testing, and I'll also implementi the changes @bdring suggested for the class and PR, and get back to you. |
Just did a couple of test with the solution @MitchBradley proposed, but writing some values as constant numbers for now.
I tested with an oscilloscope and it works pretty well, taking care to use reasonable parameters value. |
It is important to have a user friendly set of config values. These should be in real world units. Something like a full scale maximum ramp time in milliseconds. Have to program do the math and not the user. You should use log_debug(...) for debugging info. |
The easiest way to implement this might be to add a single new boolean item: ramp_on: with a default of false. If this is true it uses spinup_ms for the ramp timing. It would internally calculate everything else it needs. Laser inherits from PWM, but it already overrides the creation of config items, so it would not be affected. |
Boolean doesn't do it because you need to know how many steps in the ramp. Here is my earlier suggestion:
|
Could the steps be done in a fixed time? Then it could be calculated. Is there a downside to doing short delays? |
The problem is essentially identical to the acceleration problem in motion where you have to ramp up to cruising speed. The motion parameter is the time derivative of the max speed parameter, in other words the maximum change of speed in a given time. In motion we do not have a fixed number of intervals for the ramp, but rather accelerate at the max rate until cruising speed is achieved. For most spindles, the control signal can be changed instantly to the new value and the motor or vfd will deal with it. The motor drive will have an inherent hardware current limit, or the VFD will be smart about applying a ramp-up internally. But, according to this ticket, there are spindles where the hardware can apply more instant power than is desirable. To handle both "ordinary" and "must limit in software", there needs to be a parameter to adjust what that power is. A boolean that enables a fixed number of ramp steps does not give us the necessary degree of control. If, for example, the fixed number of steps is 8, then the max power is 1/8 of the full-on power. But what if 1/2 works just fine? The percentage parameterization mimics the motion model. If max% is 20, then any speed change of less than 20% of full speed will be done in one bump of the PWM or whatever, and so on until a 0 to full-on speed change would be divided into 5 bumps. An alternative would the reciprocal of max%, i.e. the number of bumps to full speed. Either way, you add one numeric parameter that lets you adjust the thing you need. A boolean with a fixed number of steps makes us guess, and set in stone, what the appropriate adjustment factor is. |
You already know the total time and the range, therefore you can determine the acceleration. By fixed time, I mean the value changes every 50ms (TBD). You use the other parameters to choose how much it changes on each interval. |
Having said all that, I totally missed the fundamental problem with this patch - you must not delay in set_output(). Spindle::set_output() is called from the stepper interrupt service routine via the call chain pulse_func .. spindle->setSpeedfromISR .. set_output . Delaying will stall the interrupt and cause all manner of havoc. The way to make it work would be to integrate the spindle speed ramp into the segment generator code, having that split the spindle speed change into bumps in the same way that the segment generator does acceleration for motion. That would require some very careful work. Edit - actually it is not the segment generator that needs to change, because segments are inherently too short to be of use in this scenario. It needs to be done in Spindle::setState() which is not used in an ISR, but rather from the GCode parser after synchronization. |
I really dislike wiring in an assumption when you can easily, with no extra config variables, make it configurable. Or is the current suggestion that we have no new config variables, and always do a ramp? |
If you request a ramp, it uses the spinup_ms for the full range ramp duration. It determines an amount per interval that the speed increases in the init(). We could either use a fast, one size fits all, interval or calculate an optimized one in init(). The spinup_ms is not used for any delay when a ramp is used. The user only cares about how much time they want to give it. They already have the config values to do that. It is not much different than what goes on in a VFD. You give it max speed and a duration. The user does not need to know what is done to make that happen. |
What information is used to optimize the interval? |
I don't know that we need to optimize it. If we find a reason, we could do it. It is better than Joe StepStick trying to optimize it. |
The more I think about this the more complicated it gets. I have some code to implement a ramp in setState(), but I don't like any of the parameterizations. The problem is that spindles are all over the map as to their response to changes in the control variable. For some, the control variable represents a target speed directly, and smarts in the spindle electronics translate that to time-dependent changes in voltage or current or waveforms necessary to hit that target speed, sometimes with feedback. For others, the control variable is, more or less, the power that is applied to the motor. It will change speed until the losses are in equilibrium with the power. When that equilibrium is reached, you can think of the control variable as correlating to the spindle speed. Initially the excess power of (new_speed - old_speed) accelerates the motor, but as losses increase, the acceleration drops off. So the speed curve probably looks more like (1 - exp(-t/t0)), similar to a capacitor charging. For the second kind, if you ramp up the control variable value instead of setting it instantly to the desired value, the spindle will probably take quite a lot longer to spin up than it otherwise would. During the first step of the ramp, the excess power relative to the previous power is 1/N times the excess power that would be applied during a single-step profile. So the acceleration is limited. Instead of a fast ramp, you get a sequence of shallow "capacitor charge curves". Based on this analysis, I am really concerned that fixed intervals will not give us a useful level of control. |
I have a working branch. The ramp is linear. I think that is what people expect and what VFDs do. People just pick a ramp length that yields the results they desire. it may not be the perfectly optimal profile, but it is easy to understand and tune. Let's tackle S curve on the axes before we do it on the spindle. I added ramping to an Inventables fork of Grbl in the past. The only reason we did it was because it looked cool and sounded better. The spindle hit a brief resonance that cause a vibration if you cut power and let the spindle free spin to a stop. A free spin stop took about 3 seconds, a ramp down of 5 seconds fixed it. In all cases were the user has control of some parameters, we need to test for problems in the init(). For example: if someone has a extremely low maxSpeed or spinup time, the ramp would be too coarse to work with. A maxSpeed of less than a few hundred is probably a typo anyway. I have it ramping on increases or decreases in speed. I have not tested overrides yet. isRateAdjusted() spindles are not allowed to use this. |
I pushed a branch LimitSpindleDelta where the parameters are _up_max_delta_dev_speed and _down_max_delta_dev_speed . They limit the step change in the final control parameter for the spindle. They default to 0, which means no limit. I think those parameters solve the problem as posed fairly directly. |
A solution to the original problem might not require limiting the down step - but ramp-down is indeed valuable in some cases. I had to limit it in hardware on my Consew spindle which could stop so fast - with servo braking - that the threaded tool holder would release from the spindle. |
Wow. On my 2.2kW VFD spindle, I have no break, but ramp down in about 6 seconds. If there is a power failure the spindle takes about 30 seconds to spin down. I heard that is a bad thing to do. I can look at it soon. Can you write a quick draft blurb that would go in the wiki. I want to see how it is presented to the user. |
Do you mean instructions for the rate limit variables? |
Yes |
Is the latest code merged to the branch. There are a couple of errors. I don't want to fix them and get out of sync. |
Tell me the errors and I will fix them. After having written the docs (next comment), I thought it best to use percent instead of dev speed, for consistency with speed_map. |
Spindle RampingWhen you ask for a change in spindle speed, FluidNC changes the value of some With default settings, if you ask FluidNC to change the speed from, say, If you need to limit the ramp-up or ramp-down rate of spindle changes, you
As a concrete example, suppose that spinup_max_percent is 20. If you The length of time for each step is automatically calculated from In most cases you will not need to use this; just leave spinup_max_percent |
I am good with the implementation Should this be done in PWM rather than Spindle? I think all of the spindles that can use it are based on PWM. It don't think it should be used on VFDs or On/Off spindles. |
The core routine spindleRamp is in Spindle so it could, in principle, be called from any spindle type, but it is currently only called from PWM. I could imagine calling it from DacSpindle too. |
I am am concerned with the config items being in spindles that can't use them. I assumed DAC was based on PWM, I agree that spindle could use ramping. |
I will see what I can do about the config item visibility. |
I think I have a working branch. You can test. Mitch is working on a different approach, so it may change. All you need to do is add use_ramp: true to your spindle. Can you share your config file? I can test. https://github.com/bdring/FluidNC/tree/BartsFixedIntervalRamp https://github.com/bdring/FluidNC/blob/BartsFixedIntervalRamp/FluidNC/src/Spindles/PWM_ramping.md |
Hello everybody,
we are experimenting an electronic board to move to FluidNC for our project The Ant.
Our CNC uses a brushless motor for the spindle driven by an ESC.
If this motor is accelerated or decelerated abruptly, it causes peaks of current in the supply lines, that could cause noise and, above all, damages to electronics.
To avoid this issue, in our current firmware, we implemented a ramp-up/ramp-down feature, that is just a way to accelerate and decelerate smoothly the spindle.
This modification was very effective and measuring with the oscilloscopes we noticed no undervoltage or overvoltage in the supply lines, like before.
Would it be possible to implement the same feature also in FluidNC?
We experimented and propose a very draft modification, to have a base to talk about a better implementation.