Building an Inverted Pendulum System The Ups and Downs of Defying Gravity…

March 6, 2010

Direction of motion matters

Filed under: Software — Bruce Ammons @ 10:12 pm

I experimented with a sinusoidal inputs to see how the system responds.  I started with a sinusoidal PWM, going full range in a 2 second cycle.  I discovered that the cart slowly traveled to the left while cycling.  At the time, I assumed it was due to the cable carrier.

My next test was using PID onboard the FPGA to control the current.  I used a sinusoidal current setpoint.  The cart cycled very nicely, but I discovered it traveled to the right while cycling and did it fairly quickly.  After about 10 cycles, it traveled the entire length of the rack.

To investigate further, I propped up the cart so it wouldn’t move while cycling.  I discovered that the travel had nothing to do with the cable carrier and the motor behaved almost exactly the same when it wasn’t moving the cart.  I figured out that the direction of travel is a significant variable that I will need to deal with.  It may end up being a simple proportional thing, where I use a multiplication factor to make both directions equal.

My plan is to collect a good amount of data while cycling the motor at different rates, then building a table that relates acceleration to speed and current.  I haven’t figured out exactly how I am going to do it yet, but I am working on it.  Once I have the table, I am hoping it will enlighten me on how to model the motor and cart.  If all else fails, the table could be used as the model.

February 16, 2010

Pendulum position and speed

Filed under: Software — Bruce Ammons @ 2:49 pm

I wired up the encoder for the pendulum and ran a few tests.  It was a major pain to solder the wires into the connector.  The connector is so small and light that it slides all over the place while I am trying to heat up the solder cup and insert the wire.  I melted a big section of the plastic connector base while chasing the connector around.  I ended up plugging the connector into the 9411 module to give it more bulk and managed to complete the job.  It is pretty messy, though.  I decided I need to buy a small vise to hold the parts while I am soldering.  This will make it much easier.  I found a few in the $20 range that look pretty good.

Once I wired it up, I tried out a copy of the position and speed measurement routines that I used for the cart.  I quickly found a major bug in the algorithm – I was storing the space measurements as signed values, and when it was changing direction I was averaging large positive and negative numbers, which gives numbers close to zero.  After division, I was getting very large speeds instead of close to zero like I should.  I separated the signs from the magnitudes and everything was good.  I tweaked a few other parts of the algorithm to get very accurate measurements.  I found the pendulum encoder still has a pattern that repeats every four pulses, but it isn’t nearly as bad as the position encoder.  At higher speeds averaging four spaces works very well to give a smooth speed measurement.  At very low speeds, it is better to use single measurement to minimize the delay of the speed measurement.

Once I was satisfied with the measurements for the pendulum, I copied the changes back to the cart routines.  They probably still need a little tweaking since the cart behaves differently than the pendulum, but it should still be an improvement since I eliminated some major bugs.

February 15, 2010

Current PID first look

Filed under: Software — Bruce Ammons @ 2:31 pm

I added PID control for the current to the program.  I used the standard NI PID routine that comes with the FPGA toolkit.  All I have to do is feed in my PID coefficients, setpoint and control variable and it takes care of the rest.  I just added it to the output of my current measurement routine so it updates the PWM value once per cycle.  I also added a switch so I can change between PWM control and current control.

The initial tests are promising.  I made the setpoint alternate between small positive and negative currents and watched the current values as it cycled.  I managed to come up with PID coefficients that quickly reach the setpoint values without going unstable.  The values were small enough that nothing moved.  There is still a lot of testing to go, but the PID control of current looks pretty good at first glance.

February 13, 2010

Measuring position and speed

Filed under: Software — Bruce Ammons @ 11:24 am

I wired up the encoder to the 9505 module so I can measure position and speed of the cart.  It is a standard quadrature encoder with 1000 pulses per rev.  Looking at the transition edges, we get 4000 edges per rev.

I started with a LabVIEW example to read the position of the encoder.  This works fine and was very easy to set up.  I also want to measure speed, though, and that gets a little more challenging.  I decided to look at instantaneous speed by measuring the space between consecutive edges.  I started with a routine that outputs the max of either the last space measured (space-1) or the current space being measured.  Including the current measurement helps when the system is slowing down.  I ran the motor at low speed and took a look at the space measurements.  I found out that the pulse edges on the encoder I am using are not equally spaced.  The graph below shows alternating long and short spaces.  The long spaces were about twice the length of the short spaces.  This would make the speed measurements very wild and inaccurate.

Speed - One Pulse

Speed - One Pulse

My second approach was to always average the last two space measurements.  I averaged space-1 and max (space-2, current) to get a smoothed measurement of the spacing.  This worked pretty well and reduced the variation significantly.  The graph below shows there is still a small variation that repeated every four spaces, though.  I realized that the widths of the on and off portions of the A and B pulses were not perfectly spaced either.  I am guessing the on portion is slightly longer or shorter than the off portion of each signal.

Speed - Two Pulses

Speed - Two Pulses

My third approach was to average the last four space measurements.  I averaged space-1, space-2, space-3, and max (space-4, current) to get a very nice, clean space measurement.  This removed all the cyclical variation from the measurements and gave me a nice smooth curve, which you can see in the graph below.  My only concern was that at low speeds with deceleration the delay for measuring true speed could be significant.  The measured speed is always a couple of counts behind when averaging four values.  I decided that when the current space measurement exceeds 40,000 (1/1000 of a second), I will only use the last two spaces.  This trades a little variation for quicker response.  I may adjust this cutoff level later.

Speed - Four Pulses

Speed - Four Pulses

Now that I had a very accurate measurement of the spacing between the pulses, I had to convert it to speed.  I ended up using the new high throughput division available in LabVIEW 2009.  I was able to divide 40,000,000 (total counts per second) by the spacing to get pulses per second.  One nice thing is that the high throughput math works inside a single cycle timed loop.  There is a delay of 29 cycles between inputting the numbers and getting the answer, but that is a very short amount of time when each cycle is 25 ns.  Good enough for me!!!

Now I feel I have very accurate measurements of current, position, and speed.  The next step will be adding PID control of the current.

On a side note, there is no noticeable noise in the encoder signals.  Apparently the combination of shielding and differential encoder inputs is enough to eliminate any noise issues.  This means I can run all the cables in the same track when I get some cable carrier, which will save me a little money.  If there was too much noise, I was considering using two cable carriers in opposite directions – one for the encoders and one for the motor cable.  I need to order the carrier soon, because the cables would get very tangled if the cart moves around much, and I am very close to moving the cart.

February 9, 2010

Even more current analysis

Filed under: Software — Bruce Ammons @ 7:04 pm

I thought my plans for scaling the current and calculating the overall current would work well.  The exact factor of two was appealing – until I ran the motor in the other direction.  In that direction, the factor looked closer to 1.8, which totally confused me.  I was frustrated and decided to take a break for while.  In the meanwhile, I continued discussing my issues measuring current on the NI discussion forum.  Yesterday Eric from NI answered all my questions very clearly (see How is NI-9505 current sense measured? for details).  He explained that there are two resistors used to measure the current.  During the On cycle, the resistor that the current passes through depends on the direction of rotation.  During the Off cycle the current goes through both resistors, which makes the measured current twice the actual current and totally explains why the Off cycle was measuring about twice the On cycle.  The different factor for each direction of rotation is because the two resistors have slightly different values.  Once I realized this, I compared the waveforms and found out that for CW my 9505 module has an Off/On ratio of about 2.05, and for CCW the ratio is about 1.95.  Once these correction factors are applied, the On and Off cycles are almost exactly equal for both directions.  Therefore, my current measurement scheme will be:

  • Measure at the center of the Off cycle if the PWM < 30% (to avoid spike effects in small pulse widths) and leave the value as is.
  • Measure at the center of the On cycle if the PWM > 30%, and multiply it by the appropriate scaling factor (CW = 2.05, CCW = 1.95) to get it to match the Off cycle.

This will give me an accurate current measurement at any PWM and either direction.  The scaling factor for the current measurement will be 3.1 mA/count since I will have twice as many counts during the On cycle.

I believe this resolves my issues measuring current, so I can move on to the next step – reading the encoders to determine position, velocity, and acceleration.  I can also start programming a PID loop to control the current.

January 30, 2010

More current analysis

Filed under: Software — Bruce Ammons @ 9:49 am

It looks like I jumped the gun on the inductor curves.  I started looking at the curves as the current increases by preventing the motor from rotating.  I found out that the curve did NOT stay the same shape as it shifted up.  For some reason, the Off current is roughly twice as much as the On current.  The shape of the curve also gradually changes, which makes the inductor oscillations unusable.

Current waveform, 25% duty cycle, no rotation, 470 uH inductor
Current waveform, 25% duty cycle, no rotation, 470 uH inductor

I decided the inductor wasn’t going to be useful, so I went back to just the motor and took a look at the currents at the higher loads.  I get the graph below, which shows a very smooth curve and the Off cycle is almost exactly twice the On cycle.  I recorded the curve at many different duty cycles and this looks pretty repeatable.

Current waveform, 25% duty cycle, no rotation, no inductor

Current waveform, 25% duty cycle, no rotation, no inductor

From my observations, I came up with an algorithm for measuring current.  I measure the current at 140 counts in whichever part of the cycle is longer, then estimate the other part of the cycle by multiplying or dividing by two.  I multiply each value by its percentage of the total cycle time, add together, and divide by total cycle time to get average current.  For all my recorded graphs the value was very close to the mean value of the entire graph.  I think this will be accurate enough to control the motor.  I will code it into the FPGA and see how well it works.  The next step will be writing a PID control loop for the current.

January 28, 2010

Current spikes with inductors

Filed under: Software — Bruce Ammons @ 11:58 pm

I ended up ordering a 220 uH inductor and a 470 uH inductor.  They arrived today so I tried them out.  I tried each inductor separately, then combined them to get 690 uH.  I saved graphs at 5, 25, 50, and 75%.  I plotted the original curve (white), a smoothed curve (red) and the mean value (green).  The graph for the 470 uH inductor at 25% duty cycle is shown below.  For those that are interested in seeing all the graphs, here are the Current Waveform Inductor Results (zipped).

Current waveform, 25% duty cycle, 470 uH inductor

Current waveform, 25% duty cycle, 470 uH inductor

The graphs still look nothing like the behavior that was predicted on the NI discussion forums.  The folks at NI predicted a rising current when it was on and a dropping current when it was off, creating a sawtooth waveform.  They figured sampling in the middle of the on portion of the cycle would give you a good estimate of the average current.  Obviously, that wouldn’t work in this case.  From the different graphs, I was able to make a number of useful observations.

  • There is still a spike at the beginning of the on cycle.  It isn’t as large, but it still makes the first 100 counts of data unusable.  This region should always be avoided when measuring current.
  • The high frequency oscillation is due to the rotation of the motor.  I assume the resistance varies as the motor rotates.  As the inductance increases, the amplitude of these oscillations decreases.  At 5% duty cycle, the motor did not rotate and the graphs are very smooth.
  • The inductors introduced a large amplitude oscillation in the current.  As the inductance increases, the amplitude decreases and the frequency decreases.  With a very large inductance, the oscillations would go away.
  • Ignoring the motor oscillations, these graphs are very repeatable.  They shift up and down as the load is changed but do not change shape at all, indicating that selecting a point where the smoothed curve crosses the mean should always give the correct current value.

With the 220 uH inductor, the graphs seem more uneven and erratic.  With the two larger inductances, I get very similar results.  For now, I plan on going with the 470 uH inductor.  I haven’t examined the motor performance yet, but I suspect it will work just fine.  It seems just as zippy as ever, so any effects should be minor.

Since I can’t easily predict when the best time to read the current is, I plan on building a lookup table that tells me when to sample based on the pulse width.  To create the table, I can locate the intersection between the smooth curve and the mean curve for each pulse width.  It shouldn’t be too difficult to automate the process.  For small pulse widths, I plan on preventing rotation to eliminate the small pulses until the current gets too high.  For larger pulse widths, the smoothing works very well.

January 25, 2010

Current spikes with resistors

Filed under: Software — Bruce Ammons @ 12:48 pm

I decided to try another experiment.  I removed the motor from the 9505 controller and replaced it with a 1000 ohm resistor.  I still get a spike whenever the voltage switches, and it has the classical RC circuit decay.  The initial value is about 60 counts (6.2 mA per count) and it decays to a steady state value of 4 counts (24 mA), which is the expected current with the resistor.  I can’t explain why the second peak is positive instead of negative.

Current waveform, 25% duty cycle, 1000 ohm resistor

Current waveform, 25% duty cycle, 1000 ohm resistor

Next I removed the resistor and tried it with nothing connected as a load.  The curve looked almost identical to the previous curve, but it goes to a steady state value of zero, which is no surprise.

Current waveform, 25% duty cycle, open circuit

Current waveform, 25% duty cycle, open circuit

My final test for the day was to use a 150 ohm resistor to get a larger steady state current.  In this case, I noticed the peak still starts at 60 counts but decays to the expected steady state value.  It does weird things when it switches back to zero volts that I can’t explain.

Current waveform, 25% duty cycle, 150 ohm resistor

Current waveform, 25% duty cycle, 150 ohm resistor

It appears for resistive loads the current always starts at 60 counts and decays to the expected steady state value.  I do wonder what would happen if the steady state value was greater than 60 counts.  From the decay curves, I figured out that the time constant for the decay is about 1000 ns or 1 us.  I also noticed a third small spike just before 2000 counts.  It looks to me like the circuit disconnects from one source about 30 counts before connecting to the other source.

I noticed in the 9505 manual that the minimum inductance is 500 uH.  I assume my motor’s inductance is much lower than this.  My current plan is to buy a 500 uH inductor and put it in series with the motor.  It will smooth out the current to a triangular waveform that can be measured predictably.  The only negative effect I foresee is that it will also filter changes in voltage and delay the response of the motor.  The delay may not be large enough to worry about, though.  I might also get a smaller inductor, about 250 uH, to try out as an intermediate step – less smoothing but less delay.

« Newer PostsOlder Posts »

Powered by WordPress