In the previous post I said that the oscillations that sometimes happens (in the end of the second image) was due to the integral term but I manage to zoom in other test I did and proved that it isn't true:

This is without the if(angulo == 0) showed in the last comment

Must admit I've not been following this thread that closely, or the code, but remarks:

1) My first thought looking at the above graph was 'insufficient Derivative gain". Add some.

2) The gains interact. If you just turn one off (Ki = 0, say) then turn it back on again (Ki = 0.4, say) you will have to adjust the others as well.

3) Your integrator will react a lot faster if you sample your error a lot faster. Faster sampling will, of course, have interesting effects on the gain values as well.

4) Provided the encoder is directly fixed to the motor shaft, position error is caused by load and/or friction (technically, friction is load). Motors specifically built _as_ servo motors have low-friction parts (for exactly this reason, and cost appropriately). Cheap'n'cheerful DC motors often do not.

This whole block seems to be a problem you want to use erro (why not spell it error???), NOT angulo in these conditionals...if the error is positive, go one way, If error is negative, go the other if the ERROR is zero, set the pwm to zero, NOT if the angle is zero set the pwm to zero. Since you apparently are aiming for zero angle, the result will be about the same, but you might want a different angle.

erro is error in my native language, like angulo is angle in my native language :)

I used the angulo variable because like you said, it makes no difference if the setpoint is zero and since I have no intentions of changing it... But I might change it anyway to be "future proof".

avrcandies wrote:

even better, recommend if the error is less than some +/-deadband, set the pwm to zero..it is very hard to have an exact match, always allow +/- count at least.

The angle variable only has certain values because of the resolution of the encoder. The encoder gives 408 pulses per rotation (after the gearbox) so 408/360º = 0.882. This means that the angle variable will have the following values: ...-1.764º, -0.882º, 0º, 0.882º, 1.764º...

So when in real life angle is -0.882º< angle < 0.882º for the microcontrollers this is always equal to 0º wich gives slightly less then 1.764 of deadband. And from the tests I did the system always reaches and stops at that deadband.

1) My first thought looking at the above graph was 'insufficient Derivative gain". Add some.

This is just a PI controller that's why it needs derivative gain.

Note that the graph that you quoted just shows the end of the system's response when only the integral part is actuating, the disturbance that I applied to make it move is not showm in the graph.

Scroungre wrote:

4) Provided the encoder is directly fixed to the motor shaft, position error is caused by load and/or friction (technically, friction is load). Motors specifically built _as_ servo motors have low-friction parts (for exactly this reason, and cost appropriately). Cheap'n'cheerful DC motors often do not.

I realized by now that with the amount of friction in this motor it will really hard to make it work properly. I am reading the article that I posted in post #49 and it is really confusing and I'm having a hard time trying to understand, mainly because of all different torques and inertia and frictions that the article talks about and that I have no idea on how to find those values.

If I want to buy a new motor is there anyway to know if I'll have this problem with that new motor, by the characteristics. Or maybe buying a motor from a good manufacturers.

Do you have any recommendations?

Because I can make the motor stop at the setpoint but the problem is make the integral part act smoothly.

Any motor will have friction, inertia, windage and so on. There are plenty of servo systems that operate quite nicely in spite of these real world problems. I'd suggest you get rid of the floating point - not only is it computationally slow, it introduces subtle problems as in 0 is not necessarily zero. As far as the calculations are concerned, it only needs encoder counts - these are integer. Convert to/from actual angle values when you need to.

As suggested earlier, you need to 'jump over' the dead band due to the motor friction. If the computed pwm value is >0 but <dead zone, then pwm = dead zone. Obviously, this is done as a signed value.

You also need to consider your loop frequency. It is of little use to compute the error faster than what the motor can move. If you do this, you get 'wind up'. Based on the maximum RPM of the motor and encoder counts, how far can the motor move between calculations?

The textbook method of tuning PID relies on knowing the 'plant' function. For this you need to know the motor's mechanical and electrical specs. Once you get a gearbox and real loads, these values change so usually the only way is to measure them. The empirical method of tuning is usually giving the system a large step and measuring the response. Once you get a good large step response, then tweak for small step response.

Posted by avrcandies: Fri. Aug 11, 2017 - 12:38 AM

1

2

3

4

5

Total votes: 0

One test you can do is run it fwd at 100% pwm (full on), say for 2 sec then stop, maybe 1/2 sec (so as not to overload driver/supply) the do same in reverse...then you give at least an indication of the fastest possible motion response...if this moves too slowly for you, no amount of software can fiddling can help.

problems as in 0 is not necessarily zero

It's more likely that something supposed to be zero is not (e.g., test for exactly zero, but you have 0.00000123) a=5.0; a=a-15.6/4.7; a=a+15.6/4.7; a-5.0 equals zero, probably not

Kartman is correct - A good servo system should overcome most of this, at a small cost in performance. That said...

1) Position gain P without derivative gain D is a recipe for oscillation. It'll never be stable with any reasonable step function.

2) "Wind-Up" is definitely a problem with integrators. An easy (if partly-baked) solution is to zero the integrator term whenever the D term is large (motor moving) or the P term is large (far away from setpoint) or possibly both. Define 'large' to taste. This will also let you use a larger Ki term.

2a) I don't feel sampling too fast is going to wind up either of the others with suitable coefficients. I like to sample far faster than motor response time, and my servos are stable. Sampling too slow is a much larger problem.

3) I agree with the idea that floating point (FP) math is not required. The encoder is an integer device, and fancy multiplication and division can be readily approximated.

4) I disagree that it has to be signed math. If you define 'set point' as, say, 1000 0000 0000 0000 (or 0x8000) in a sixteen-bit integer, all the math can be unsigned. Define a maximum distance to travel, and any values outside that range (say, anything >0x9000 and <0x7000) declare a servo positioning error and turn power off.

5) Underdamped systems in a step situation (pull motor off setpoint, let it go) will get back to setpoint faster but will always overshoot some and then return to position. They may overshoot more than once (and continue to oscillate if very underdamped). Overdamped systems will take a long time to reach position, but won't overshoot. This is a design trade-off - There's no such thing as a perfectly damped system. The graph looks overdamped.

Posted by avrcandies: Sat. Aug 12, 2017 - 02:22 AM

1

2

3

4

5

Total votes: 0

A few tips:

You can read the encoder much faster than needed (say 5x or 8 x or 10x) & average the readings to help reduce noise effects...get a good solid reading. If read fast enough, an exponential weighting won't harm things,

say: sensor_value=(sensor_value+ newest_reading)/2 (pretty good) or sensor_value=(3*sensor_value+ newest_reading)/4 (just 2 shifts), or sensor_value=(sensor_value+ 3*newest_reading)/4 or sensor_value=(7*sensor_value+ newest_reading)/8

You can do a similar thing with the PWM value itself---filter the final control value to smooth its changes (but no too much). A faster update rate allows more aggressive smoothing.

The rate at which you read the sensor, does not have to be the same rate at which you update the PWM

Here is an interesting link with some ideas about windup and other things:

A deadbeat-response is often considered as an optimal closed-loop response, since it achieves minimum rise-time,

no steady-state error and no overshoot, in a minimum number of time-steps. From the authors’ experience in designing

second-order systems control, an important question is: how to achieve small or zero overshoot in the closed-loop step response

for the second-order systems?........This paper proposes a new control structure, which can be used to achieve fast closed-loop response with minimum

overshoot for underdamped second-order systems, based on the Posicast input-command shaping concept and PID control.

M_Luis wrote:Must admit I've not been following this thread that closely, or the code, but remarks:

1) My first thought looking at the above graph was 'insufficient Derivative gain". Add some.

2) The gains interact. If you just turn one off (Ki = 0, say) then turn it back on again (Ki = 0.4, say) you will have to adjust the others as well.

3) Your integrator will react a lot faster if you sample your error a lot faster. Faster sampling will, of course, have interesting effects on the gain values as well.

4) Provided the encoder is directly fixed to the motor shaft, position error is caused by load and/or friction (technically, friction is load). Motors specifically built _as_ servo motors have low-friction parts (for exactly this reason, and cost appropriately). Cheap'n'cheerful DC motors often do not.

Hope this helps.

S.- Log in or register to post comments

Topavrcandies wrote:erro is error in my native language, like angulo is angle in my native language :)

I used the angulo variable because like you said, it makes no difference if the setpoint is zero and since I have no intentions of changing it... But I might change it anyway to be "future proof".

avrcandies wrote:The angle variable only has certain values because of the resolution of the encoder. The encoder gives 408 pulses per rotation (after the gearbox) so 408/360º = 0.882. This means that the angle variable will have the following values: ...-1.764º, -0.882º, 0º, 0.882º, 1.764º...

So when in real life angle is -0.882º< angle < 0.882º for the microcontrollers this is always equal to 0º wich gives slightly less then 1.764 of deadband. And from the tests I did the system always reaches and stops at that deadband.

- Log in or register to post comments

TopScroungre wrote:This is just a PI controller that's why it needs derivative gain.

Note that the graph that you quoted just shows the end of the system's response when only the integral part is actuating, the disturbance that I applied to make it move is not showm in the graph.

Scroungre wrote:I realized by now that with the amount of friction in this motor it will really hard to make it work properly. I am reading the article that I posted in post #49 and it is really confusing and I'm having a hard time trying to understand, mainly because of all different torques and inertia and frictions that the article talks about and that I have no idea on how to find those values.

If I want to buy a new motor is there anyway to know if I'll have this problem with that new motor, by the characteristics. Or maybe buying a motor from a good manufacturers.

Do you have any recommendations?

Because I can make the motor stop at the setpoint but the problem is make the integral part act smoothly.

- Log in or register to post comments

TopAny motor will have friction, inertia, windage and so on. There are plenty of servo systems that operate quite nicely in spite of these real world problems. I'd suggest you get rid of the floating point - not only is it computationally slow, it introduces subtle problems as in 0 is not necessarily zero. As far as the calculations are concerned, it only needs encoder counts - these are integer. Convert to/from actual angle values when you need to.

As suggested earlier, you need to 'jump over' the dead band due to the motor friction. If the computed pwm value is >0 but <dead zone, then pwm = dead zone. Obviously, this is done as a signed value.

You also need to consider your loop frequency. It is of little use to compute the error faster than what the motor can move. If you do this, you get 'wind up'. Based on the maximum RPM of the motor and encoder counts, how far can the motor move between calculations?

The textbook method of tuning PID relies on knowing the 'plant' function. For this you need to know the motor's mechanical and electrical specs. Once you get a gearbox and real loads, these values change so usually the only way is to measure them. The empirical method of tuning is usually giving the system a large step and measuring the response. Once you get a good large step response, then tweak for small step response.

- Log in or register to post comments

TopOne test you can do is run it fwd at 100% pwm (full on), say for 2 sec then stop, maybe 1/2 sec (so as not to overload driver/supply) the do same in reverse...then you give at least an indication of the fastest possible motion response...if this moves too slowly for you, no amount of software can fiddling can help.

It's more likely that something supposed to be zero is not (e.g., test for exactly zero, but you have 0.00000123) a=5.0; a=a-15.6/4.7; a=a+15.6/4.7; a-5.0 equals zero, probably not

There are some nice links here for tuning a PID:

http://www.controleng.com/single-article/disturbance-rejection-vs-setpoint-tracking-controllers/f1e71c39ed5c34634687a985f9a5d53a.html

When in the dark remember-the future looks brighter than ever.

- Log in or register to post comments

TopKartman is correct - A good servo system should overcome most of this, at a small cost in performance. That said...

1) Position gain P without derivative gain D is a recipe for oscillation. It'll never be stable with any reasonable step function.

2) "Wind-Up" is definitely a problem with integrators. An easy (if partly-baked) solution is to zero the integrator term whenever the D term is large (motor moving) or the P term is large (far away from setpoint) or possibly both. Define 'large' to taste. This will also let you use a larger Ki term.

2a) I don't feel sampling too fast is going to wind up either of the others with suitable coefficients. I like to sample far faster than motor response time, and my servos are stable. Sampling too slow is a much larger problem.

3) I agree with the idea that floating point (FP) math is not required. The encoder is an integer device, and fancy multiplication and division can be readily approximated.

4) I disagree that it has to be signed math. If you define 'set point' as, say, 1000 0000 0000 0000 (or 0x8000) in a sixteen-bit integer, all the math can be unsigned. Define a maximum distance to travel, and any values outside that range (say, anything >0x9000 and <0x7000) declare a servo positioning error and turn power off.

5) Underdamped systems in a step situation (pull motor off setpoint, let it go) will get back to setpoint faster but will always overshoot some and then return to position. They may overshoot more than once (and continue to oscillate if very underdamped). Overdamped systems will take a long time to reach position, but won't overshoot. This is a design trade-off - There's no such thing as a perfectly damped system. The graph looks overdamped.

Gotta go - Hope this helps.

S.- Log in or register to post comments

TopA few tips:

You can read the encoder much faster than needed (say 5x or 8 x or 10x) & average the readings to help reduce noise effects...get a good solid reading. If read fast enough, an exponential weighting won't harm things,

say: sensor_value=(sensor_value+ newest_reading)/2 (pretty good) or sensor_value=(3*sensor_value+ newest_reading)/4 (just 2 shifts), or sensor_value=(sensor_value+ 3*newest_reading)/4 or sensor_value=(7*sensor_value+ newest_reading)/8

You can do a similar thing with the PWM value itself---filter the final control value to smooth its changes (but no too much). A faster update rate allows more aggressive smoothing.

The rate at which you read the sensor, does not

haveto be the same rate at which you update the PWMHere is an interesting link with some ideas about windup and other things:

A deadbeat-response is often considered as an optimal closed-loop response, since it achieves minimum rise-time,no steady-state error and no overshoot, in a minimum number of time-steps. From the authors’ experience in designingsecond-order systems control, an important question is: how to achieve small or zero overshoot in the closed-loop step responsefor the second-order systems?........This paper proposes a new control structure, which can be used to achieve fast closed-loop response with minimumovershoot for underdamped second-order systems, based on the Posicast input-command shaping concept and PID control.http://ac.els-cdn.com/S1474667016310783/1-s2.0-S1474667016310783-main.pdf?_tid=581d341e-7f02-11e7-9a6c-00000aacb360&acdnat=1502503550_0bf3d57785bce9f17ff18c471062c029

When in the dark remember-the future looks brighter than ever.

- Log in or register to post comments

Top## Pages