Showing posts with label Fader. Show all posts
Showing posts with label Fader. Show all posts

Saturday, July 23, 2016

PID implementation experiences - UPDATED

I have posted previously about my experiences trying to implement a PID controller.  I am controlling linear faders that are motor driven from a remote device.  Movement of a control on the remote device results in the physical linear fader following that movement and the remote device following the fader when moved locally.

I have learned a number of things along the way.  I am new to control loop implementation and while the algorithms are well known and documented along with plenty of example code, the first thing I learned is that none of that helps you when it comes to tuning the operation of the PID in the specific environment in which it runs.

There are those among us that can describe in glorious detail the math behind all of the theory and implement MatLab simulations of motor transfer functions.  That, unfortunately does not describe me.  While I have a PhD, it is only in the school of "hard knocks" as my experience is my instructor.

Tuning PID control systems is as much art as science.  For a given fader (in my case) one could come up with PID tuning parameters by experimentation that would perform acceptably.  However, with the wide variance in acceptable performance from the manufacturers, it is a challenge to replicate that experience across an arbitrary number of faders from the same vendor.  My vendor for example specifies that the force required to move the fader is .8 newton which in and of itself is fine, just that the expected acceptable variance from this specification is plus and minus .5 newton.  Using a fader with specifications such as these is typical, but results in extreme difficulty when designing to have consistent results across multiple batches of the same fader model.  The variation in performance resulted in what initially looked like a 70% failure rate in being able to calibrate them.  However, my initial design failed to take into account the fact that the initial batch had very low friction profiles.  Comparing the experience to the datasheet, led me to conclude a different design (velocity PID) was required.

A number of desirable design elements are useful when designing control loops for motorized faders.

  1. Smooth movement
  2. Accurate positioning
  3. Stable movement without oscillation
  4. Able to accommodate a wide variance in friction profiles
  5. Able to accommodate fairly noisy signals measuring position of the fader
  6. Able to accommodate accurate measurement of movement velocity
  7. Sufficient MIPS available to provide tightly coupled feedback loops

My original implementation utilized a PID to control positioning the fader to one of 1024 positions.  The PID implementation included most of the fixes for typical PID controller issues which I have previously described.  It did a good job of positioning the fader to a give set point, quickly and fairly accurately.

Where it lacked robustness however was in dealing with changes in position that are very small and at an irregular arrival rate and rate of change.  Think of moving a control very slowly and sampling it's position on a 100-200 ms basis and using that as the set point for your PID.  Goal #1 above suffered greatly.  Attempts to tune this with three different sets of tuning parameters achieved reasonable results, but goal #4 was impossible to achieve with a positional PID alone.

The only way to achieve all of these goals was with a control loop that would set the fader moving in the right direction according to a motion profile and tightly control the velocity of the fader movement.  The control loop could apply as much or little force as necessary to keep the movement on the velocity profile desired.

There are (at least) a couple of standard forms of PID algorithms, one that works to control the position of something and the other to control the rate of change of something.  I found that I could use the first form (so called analogue PID) to control either in this case.  In the positional PID, I measured the position of the fader by reading the DC voltage across the fader potentiometer using an ADC.  The input to the PID was the current ADC value read from the fader.  The PID would compute the necessary PWM output to drive the motor to the desired position.

In the case of the velocity PID, I kept a history of fader positions over a 5 ms period.  The position is calculated every 250 us.  The difference between the newest and the oldest position samples provided a velocity with sufficient granularity to be useful.  This velocity value (current velocity) was used as the input to the velocity PID.  The calculated PWM output value was use to drive the motor to adjust the movement to the desired velocity regardless of varying friction, voltages, etc.

A couple of traps in implementing the vPID (or for that matter, any PID).  When tuning, you should always start very non-aggressively and only change one thing at a time.  General tips:

  1. There are hundreds of white papers, publications, youtube videos and the like that describe the process of PID tuning in excruciating detail.  They are all useful.  Everyone's learning style is different, so use what works for you and toss the rest.
  2. The proportional gain (Kp) value should be chosen to quickly produce the necessary output PWM value to get you moving in the right direction.  Consider the approximate PWM value necessary to move the motor and the estimated maximum velocity error possible when choosing this value.  Best to experiment with a too high value and back it off appropriately.  The Kp value should kick your motor into action without creating oscillation.
  3. The correct direction to move is determined by the sign of the positional error.  (desired position - actual position).  If negative you move one direction, otherwise you move the other direction.
  4. The integral gain (Ki) value will want to accumulate errors in velocity fairly quickly and so it will likely be greater than Kp.  You want accumulating error to be made up in acceleration quickly.  Otherwise, your faders will lag both in acceleration and deceleration.  Dialing this value up too high will result in overshooting and oscillation.
  5. The derivative gain (Kd) value will likely be unused in a velocity PID.  The presence of noise on the ADC readings is greatly amplified by increasing the Kd value.  In my case there is about 30 mv of variance in position calculations for a fader that is not moving.  The fact that the fader is 100 mm long and has 1024 positions means that a change in position of one results in a 48 uV change.  So, changes in position of 10 or less will be lost in the noise.  Sounds like a lot, but 10 positions (out of 1024) on a 100 mm fader is a change in position of about 1 mm.  In my experience even with signal processing techniques applied to the ADC value, increasing the Kd value above 1.0 resulted in severe oscillation of the fader.  In the end, I set this term to 0.0 disabling it.  In a positional PID I found this term to be very useful for flattening out ringing around the positional set point.  For velocity, not so much.
One area that is not discussed as much in the various resources available is the importance of not only controlling the velocity, but having the decision about what the desired velocity is be able to change as appropriate.  For example, one could merely state that when faders move, they always move at a single constant velocity.  This is perhaps a too simple solution.  Single set point movements (from A to B) occurring infrequently, this may well be sufficient. Tiny incremental changes you end up with overshooting and backing up (overshooting again) etc.  What is necessary is a motion profile that will decide what the velocity should be for a given movement.  This can be as complex or simple as will meet your needs.

In my case, I allow the PID tuning to dictate how rapidly the fader is accelerated and the maximum velocity allowed is the set point for the vPID.  To determine that set point, I chose to use the distance to the positional set point to determine the velocity.  Basically, the further we have to travel, the faster we will go (up to a maximum limit) and then as we approach the set point, we slow down on that same profile.  It ends up looking something like this:


This represents three different deceleration profiles that were tried.  The blue line represents my original design where up at the top of the graph, we are cruising along at the maximum velocity.  As we get close to the target, we begin to decelerate at an initial rate and at the end we increase the rate of deceleration until we stop.

Due to the inherent delays involved in filtering the ADC values, I found that with this profile, I was consistently overshooting my set point position.  The amount of overshoot was proportional to the length of the move.  Flattening out the curve slightly as seen in the red line, improved the overshoot condition, but not sufficiently.  In the end, my profile looks like the yellow line where we begin decelerating a little sooner and decrease the velocity at a slower rate approaching the set point.  This has allowed me to accurately position faders and meet all of the requirements above.

There are other details that require attending to.  Most DC motor controller chips have the ability to apply a braking action to the motor movement.  When coming to a stop, you should definitely apply the braking action.  However, be careful that you do not release the brakes too soon.  There is a fair amount of inertia in the system and these motors don't stop on a dime.  The actual stopping time is a function of the velocity, mass and friction profile.  For the simple minded among us (me) this translates into something other than a brake tap.  I apply the brakes when in range of where I want to stop plus or minus some delta and then hold them, in my case for about 4 ms before releasing.  Without this action, overshooting is a very real problem.

So with a 250 us cycle of determining the position, keeping 5 ms of positional history to measure the velocity and applying the new PWM value to the motor resulted in very smooth and precise operation.  Reducing the fader update rate to 1 ms was also very nice with small steps in position being only slightly more apparent.

I have initially implemented this on a 120 MHz Cortex M4 processor that supports floating point hardware.  Now that I have the implementation details worked out, I will be experimenting with simplified fixed point implementations on Arduino hardware and will of course post my code for that as it develops.

Friday, December 25, 2015

More PID ramblings

First of all, Merry Christmas!

Since I cannot seem to turn my brain off on this topic I have been semi-immersed in for a number of weeks, I wanted to jot down a few thoughts on the topic of PID controllers.

My goals in using a PID controller with a mechanical fader that is driven by DC motor are simple, to wit:

  1. Instantaneous snapping to a new position once loaded into the controller.
  2. Positional accuracy and repeatability when the same position is loaded.
  3. Smooth movement of the fader control under PID control when set point changes are small and frequent.
  4. Tolerant of "stair-stepped" set point changes arriving at non-regular or varying intervals while still maintaining smooth movement.
So far, I have achieved the first two goals.  To date, I have been using a positional PID in an attempt to meet all these requirements.  A positional PID is one that takes a positional set point and a current position as input and produces the necessary output to drive the fader to its new position.  It takes care of acceleration and deceleration as necessary to arrive quickly at the new position.

However, when trying to achieve smooth movement that is quite slow, I find that a positional PID is insufficient for the task for the following reasons:
  1. A PID tuned to aggressively snap to a new position is a poor experience when trying to achieve slow but smooth changes to the position.  The fader tends to be very jerky and/or noisy.  The effect looks like a long-term crack user trying to be cool when the authorities arrive.  I have attempted to use multiple tuning settings where I reduce the gains of the P, I and D terms, but while it improves things, it is still unacceptable.
  2. I find that it takes approximately 30% of the motor speed range just to get the fader to move if it is already stopped.  Once it overcomes inertia and friction it will suddenly lunge forward and likely overshoot the desired set point if it is close at hand.
  3. Once the fader is in motion, it takes a lot less energy from the motor to keep it in motion, but there is still a fairly significant dead band in the motor speed range where the fader will stop again if the PID output drops too low.  Anytime the PID calculation must reverse direction in order to slow motion, it must necessarily pass through this dead band on both sides of zero.
What is needed for smooth motion out of a PID is to have the PID control the velocity of the motor, not just to move it to a new position.  I have attempted to simulate this using a positional PID by limiting the range of the output of the PID to something lower than the maximum speed of the motor when it is desired to be non-aggressive about positioning.  However, what I find to be true is that while it helps the overall effect, the results are not sufficiently predictable or repeatable from one fader to the next.  They all have their own friction profiles and while they are carefully manufactured, the motor movement transfer function from one fader to the next varies considerably.

So, to provide smooth movement for non-aggressive position changes, what is needed is a velocity PID that will control the speed of the motor according to a motion profile.  I will be implementing a trapezoidal motion profile where the motor will accelerate to a maximum speed, hold that speed and then decelerate to a stop at the desired position.

So, I think I need the following:
  1. ​Desired velocity - I will calculate desired velocity based off the current positional error.  When the desired position changes, we start moving in that direction according to a motion profile.
  2. Current velocity - I currently calculate this as the derivative term of positional PID.  The first derivative of position is velocity.
  3. A second PID to control motor velocity when being non-aggressive about positioning that will control motor speed according to a motion profile in a tight control loop.

We can visualize position, acceleration and motion profiles as follows:


To determine the desired velocity, I will calculate the positional PID error.  This is simply the difference between the current position and the desired position.  The further I have to go, the faster I will go up to a maximum limit.  As the fader moves, the error changes (approaches zero) as the fader approaches its target.  The fader loop will calculate the desired velocity as the current position changes towards the target.  As friction changes, voltage changes and other external disturbances affect the actual velocity, the PID will calculate the necessary correction in velocity to stay on the motion profile.

More to come...

Saturday, November 28, 2015

PID Controllers

Wow...  Where to begin.  I have had the pleasure of trying to get my head around implementing a fairly simple controller for a linear fader control that is also motor controlled.

This is an Alps fader which is basically a linear 10K potentiometer that has a small DC motor mounted on the back.  It has a 100mm travel length and the fader control is touch sensitive.  Mouser and other suppliers have them, though I cannot recommend hobbyists buying them through these channels as they are quite expensive.  I have seen them on eBay and other auction sites at significant savings.


The motor is mounted along the axis of the linear fader making a very low profile solution.  The motor drives a toothed belt to move the fader to any position desired remotely.  The motor is a simple DC motor that can be driven by up to 10 VDC.


So, one could envision simply putting a voltage across the pot and connecting the wiper to an Arduino analogue input.  Moving the pot would report a digital number from 0-1023 at any given instant in time representing the voltage across the pot at the wiper and therefore, the relative position of the fader control.

 However, if we wanted to simply tell the fader to position itself to any of its 1024 positions it is capable of, we would basically need to turn the motor on and drive it in the correct direction while reading the pot position until it attains the correct value.  This would be an appropriate application for a PID controller.

To control a DC motor, it is most convenient to use an H-Bridge circuit.  As can be seen by the circuit diagram below, turning on Q1 and Q4 will drive the motor in one direction whilst turning on Q3 and Q2 will drive the motor in the opposite direction.  As an addition feature turning on Q1 and Q2 or Q3 and Q4 will short out the power supply and allow for stress testing your circuit protection implementation...


In reality, there are nice single chip H-Bridge solutions that not only allow for controlling the motor direction, but also allow for PWM control of motor speed.  Most suppliers of robotics components will have typical examples of these controllers as well as places like Adafruit and Sparkfun.

In my next posting, I will get into the details of the hookup and programming of the PID controller for this fader.  More to come...