I spent some time last night playing around with the velocity PID values, and I thought I was making real progress.
Tonight I spent some more time, and the graphed results look much improved, the original PID settings are in red and one of my test runs is in blue. Each spike you see is a change in the set rpm. At the left it starts as 2RPM and moves up to 16RPM on the right, the vertical axis is the error off of the desired RPM:
Sadly, while the analysis would suggest an improvement. Real world usage seems to suggest that I have gone backward. The sled seems more jerky in its movement. I think the issue is that real slow end down there at 2RPM is not very consistent. I have messed with it a lot, and I don’t think I can get that lower end any better.
Am I going about this wrong? I figured since the velocity PID was later in the control sequence I should start there.
Am I passing judgement too soon? Should i get the velocity PID as close to good as possible in a test case and then start the process on the position PID? Maybe since the reactivity of the position controller output has changed it can no longer be relied upon to work properly?
Any suggestions would be appreciated. I have tried numerous techniques (increasing this, halving that, taking 10 percent of this) but at least in the testing environment, I seemed to do the best just working up in order P->I->D going back to make only slight tweaks along the way.
I know exactly what you are talking about, and I’ve had the same experiences. Settings that look fantastic in theory often turn out to cause jerky movement in practice. I’ve found that the best way I was able to tune was exactly what you said, doing P->I->D in order while running a test shape. I’ve also found starting with the velocity controller to be simpler. I’m sorry I can’t give much in the way of advice, just the moral support that I’ve had the same issues.
Have you played with the PonM option in the new PID library you posted in the issue? I have a hope and a hunch that might give us some improvements right away. From the short (but excellent) article you linked in the issue notes it sounds like PonM might let us increase the P term without inducing overshoot, and increasing the P term would improve the low speed tracking, right?
I’m a little out on a limb here because I don’t know a lot about PonM, but I think your find that they added support for that to the new PID library is a really good one
I think the two PID loops are going to be interacting in your tests, so rather
than leaving one alone and trying to get perfection on the other, I think you
are going to need to alternate the two, tweak one a bit to try and get a little
better, and then tweak the other.
I also expect that moving the sled alone vs moving it while cutting is going to
be quite different, especially with an aggressive cut (say a 1/2" bit cutting
all the way through 3/4 wood)
Thank you for going through this focused tuning work.
Good point. I will see if I can update the PID library tonight. It sounds like enabling PonM means completely starting over with the tuning, so maybe I should try the update first if my current work may be discarded.
Ha, my knowledge of PID has gone from nothing to here in a week, so we are all fumbling in the dark a bit.
Well glad to hear I am not laughably lost, it seems like this is just hard.
I couldn’t agree with @dlang more. I can’t tell you how good it feels to have someone else taking a look at the PID tunings. I always feel so much better that I didn’t miss something obvous once someone else has taken a crack at something (yay open source!!!)
I second that its hard. My experience is that every time I go in to tune the values it takes longer and is more frustrating than I expect and a lot of the time I don’t really feel like I’m making forward progress, but the tuning does end up being a little better at the end.
Wikipedia has an extensive article on PID Control that’s worth checking out. There are books on tuning…
You might want to read up on automatic tuning, like that used for 3D printer temperature control. While actually implementing it may not be worth the effort there could be some useful advice.
I have a friend on another forum that spent a good part of his career tuning PID algorithms. A Tapatalk update bug has locked my mobile out if that forum (chrome and TaT both, sigh, if it works you need to break it) but I’ll try to remember to ask him for for references when I can
I have read through Wikipedia as well as numerous other sources.
Tonight I am going to upgrade our PID library and see how that goes. I think it will help the positional controller, but I am doubtful if will help the velocity controller.
For the velocity controller, I am pretty confident that the non-linearity between output and measured value is a real issue. Bar’s graph from a while ago does a good job showing the non-linearity.
In order to get my blue lines above, I had to use a lot of KI, but that causes too much damping down at the low end where we need a lot more KP.
The two options I have seen to deal with something like this are Gain Scheduling and Linearizing the Output. I am leaning toward gain scheduling which basically entails having more than one set of PID values and breaking up the values into input ranges. I suspect that two buckets would improve our results significantly. Sadly this also increases the complexity.
OK, I got the new PID library safely integrated. I tried the PonM feature on the velocity PID and that was a mess.
But good news, I think I achieved a modicum of success with the Velocity controller tonight. I struggled for a long time trying to get a reasonable output at very low RPMs. I was noticing that at times the motor was actually briefly running in reverse at the start of a command to turn slowly.
In short, I discovered and removed the running average from the speed feedback. That made a huge difference. I suspect that was causing other issues as well. The PID controller seems more than capable of handling the quantization noise.
As a result, I think I achieved some good results without any gain scheduling or other sophisticated solutions. I am using KP = 40 and KI = 3 with KD = 0. Be cautious, these settings may not work well without disabling that averaging function.
I also learned that the analytical approach is a good starting point, but you have to throw it out the window to get good working numbers. There are just too many sacrifices to be made for all of the scenarios (moving up, moving down, high tension, low tension) at some point I had to make a subjective call as to what values seemed to work the best. I hear what sounds like Integrator windup starting, but I haven’t seen it max out yet, but I will keep my eye out for it. I also still see some chain vibrations when moving the sled at the top 9 inches of the work surface in the center. Hopefully, tweaking of the positional PID will solve this.
Finally, disabling the PID calculations if the motors are off also seems to have made a big difference. The integrator term was maxing out if the machine was just sitting there since it never stops exactly on the point it is supposed to be on.
I may try to get some work on the positional PID tomorrow, but I have to entertain my mother-in-law in the afternoon so I won’t be able to work then.
Introduce her to Maslow watching
Thank you so much for working on this! Working on PID was on my todo list, as the jerkiness has kept me from doing much with my Maslow, but Hurricane Harvey came along and wrecked a few weeks of my plans (and so much more for others).
I’m looking forward to the library, and would be happy to test it out on a different machine, if needed.
That’s fantastic news! It sounds like you are really getting into the inner workings which is awesome.
Ok, I got back to it today.
I spent a large percentage of the day trying to “linearize” the voltage -> RPM relationship. I really thought it would help the velocity PID. Anyways, after many hours and a stupidly complicated looking function, I wasn’t able to discern any benefit and in fact it may have been worse. So I threw all that away. One other option I thought of was to have different PID settings for the positive and negative velocity controllers The voltages are obviously dramatically different for each direction.
I do think I learned that the accuracy of the velocity PID is less of an issue. I think its most important aspect is that it doesn’t oscillate at low RPMs. Oscillations at higher RPMs are much much less noticable. And the positional PID overcomes a lot of velocity errors.
So I finally moved on to the Position PID. I enabled the PonM feature. It operates completely different from a normal PID, you have to start with I then move on to P. Anyways, in order to make my pretty graphs, any honestly to even tune it (becuase the values are so different) I added a position testing function.
Below are a few of the graphs, the original PID is in blue my testing version is in red.
As you can see, the old design liked to settle on a point, but often times that point was over or under zero. The testing version never misses getting to zero and rarely if ever overshoots.
It seems to work very well in real life scenarios as well. But I still have a bit more testing to do. Irritatingly I did have an occurrence of integrator windup that happened similar to before when the zaxis was retracting. I am hopeful that dialing back the KI term in the velocity PID will solve it and not cause more issues.
I have continued to make progress and found a few other related changes that have really cut down on the jerkiness of the machine. The graphs continue to look good and a subjective test of a difficult cut in the middle at the very top of the work surface is noticeably less jerky.
I tried to test a real world situation by cutting an identical test pattern using the old and new tuning and comparing the sum of the reported positional error messages in the logs. However in total cumulative error the old system gets a 609 and the new one gets 1100. I think this is caused by the old system’s willingness to overshoot.
So I am digging into how we break up the segments to be cut. It seems like we calculated the loop cycle time as .0001575 min/loop or 9.45 milliseconds per loop. We break up the commands into segments of 9.45ms in length. So I have a few questions:
It seems weird that our PID loop runs on 10ms intervals, but our movement requests are sent on 9.45ms intervals. Maybe these should be the same? At some point we are sending a positional request that gets overwritten before it gets acted on by the PID.
How do systems like this normally work? If the machine could reach the requested position in the time requested, its movements would be very jerky. On the other hand, if the machine doesn’t reach the requested point in the allotted time, you get the error that I am seeing. I had been calibrating the machine for large movements at a time (2-22mm). But in reality at the maximum feed rate of 900mm/min the distance for each cycle of the loop would be .14175mm. So should I be calibrating things at distances 100 times small than I have been looking at?
I think my answer to question 2 is that I have damped the system too much. We need to accept some low level overshoot in order to decrease the rise time.
I think the idea is to get the rise time to be close to the 10ms threshold. Then the overshoot would generally only occur when stopping since a new position would be requested at the time that the overshoot would occur. Then, as others have suggested, we add in some acceleration profiles and we should be able to limit the overshoot when stopping too.
I do wonder if this means that PonM is the incorrect method for this then.
That sounds like some good progress.
If I remember correctly I found that recomputing both the PID and the movement requests more quickly resulted in smoother motion. The current limiting factor on how fast the position can be updated is the time to compute the new chain lengths, however the triangular kinematics system would reduce that computation time to almost zero, so it might be worth exploring the effects of running both those loops faster. I agree that it seems strange that they are not synchronized.
I don’t think theoretically there is any benefit to movement requests happening at a different frequency from PID calculations. The extra movement requests are sent into a black hole. There might be a benefit if our movement requests were closed loop, but they are blind to the details of the machine positioning.
Because of the current discrepancy there is a 5Hz beat of the PID receiving distance request of double the length of all other requests 9.45ms vs 10ms. I don’t know if this is detectable but it might be, I plan on changing the movement requests to 10ms tonight.
As for increasing the sample rate, I was actually playing with decreasing it. The issue is quantization at the current or higher frequency. With 8148 steps per revolution a velocity of 1 RPM results in 1.35 steps per PID loop (8148/60/100). If you increase the sample rate, I think you will just make the movement more unstable at low speeds. When I test things right now you can’t obtain velocity accuracy better than ±.5RPM. Making 1RPM somewhat tough right now. If the KI value is high enough, it starts to be affected by this constant oscillation of ±.5RPM and you quickly get windup. I think this is why we see this happen whenever a position is held for a period of time.
I haven’t yet seen a benefit to decreasing the sample rate, but I have had a lot of unexpected issues that arise everytime I try it so I don’t think it has been a valid test yet.
OK, I think I am ready to call this good.
I think I actually crossed the threshold into too fast tonight (it started to get jerky), so I tuned it back a bit.
I still see some shaking when cutting at the top edge in the center. I haven’t been able to change even when trying a number of different approaches. But otherwise this seems a lot smoother and you will notice that the motors get pretty quiet at times. I reran the “real world” test from last night and got a cumulative error of 510. So in theory this has 16% less error?? Not sure you can calculate it like that, but whatever.
If people could try out the branch below I would appreciate it:
BE AWARE. You should use the PID settings below. The original default ones will be a mess after the changes.
Kp Position = 650
Ki Position = 4000
Kd Position = 0
Kp Velocity = 52
Ki Velocity = 0
Kd Velocity = 0
When I went to test this firmware my machine didn’t move at all. Any guesses as to what I might be doing wrong? I remembered to change the PID values in Ground Control to the ones listed above, but other than that all I did was upload that version of the firmware to the board and launch GC
Well that is odd. I don’t have an answer at all. I am running that exact version. hrm