EDIT:
*
*
An ingenious way of shooter motor control, definitely. Seems like this should have been the first thing our team thought of, over the glamor of PID!
My only question would be the precision of the “Bang Bang” speed controller over a well-tuned PID loop (how close one is the target speed). That would obviously depend on the “small overshoot” Ether talks about due to execution cycles only being ran so fast. Does anyone have data about how precise this speed control method can be? How fast would you want this cycle to run?
I might be able to get some data on this precision with various execution cycle times by the end of the week on our practice robot.
Kudos to Martin for bringing this up. He reports +/- 15 RPM. I’ve been told of similar results using a Victor.
The key is getting a noise-free speed signal. The paper discusses how to do this for speeds typical of shooter wheels.
I might be able to get some data on this precision with various execution cycle times by the end of the week on our practice robot.
Excellent. Please do post any data you generate. If you’d like a second set of eyes to look at your code, PM me and I’d be more than happy to take a look and provide feedback.
I’ve created a LabView version of this control system. It is written to match what Ether has in his original document and revisions.
I won’t have the ability to actually test it for a couple of weeks.
With this version you can set the execution cycle time quite easily because it runs in Periodic Tasks.vi.
Without actually tessting, I think one key to making this work well is a large enough moment of inertia. Actual testing should reveal what “enough” is.
I’m writing this on a moblie device, so I can’t add my vi’s but will edit this later today and add them when I’m at home.
With our current PID loop, we’re achieving around +/- 5 RPM with Jaguars. It would be great to achieve that sort of precision with this method, but with a faster ramp-up after shots or when first starting up the shooter.
I’m also worried about adversely affecting the motors with this sort of harsh treatment (fast sequence of full and no voltage). I might tune the voltage ramp to prevent this occurrence primarily, as well as preventing the Jags from shutting down. This will be something I discuss with the mechanical side of my team.
I’m not a LabVIEW guru, so I can’t say for sure, but I think you’ve captured the main idea. I do have one suggestion though: read Team 358’s document Timing Is Everything. For a clean speed signal, consider replacing that Wait with a Timed Structure.
You do realize that with their PWM output, the Victors are applying full and no voltage at 150Hz to the motors all the time, right? …I wouldn’t worry about the motors.
But what about the controllers?
The switching in the Victors and the Jags is slightly different. The Jags short the motor leads during the OFF portion of the PWM cycle, whereas the Vics open the leads.
Since the Vic’s switching method involves applying full voltage during the ON portion of the PWM cycle, and opening the leads during the OFF portion of the cycle, it seems to stand to reason that they are designed to handle that treatment. So commanding full volts and 0 volts alternately at 50Hz shouldn’t be an issue. Anyone care to comment?
On the other hand, the Jags short the motor leads during the OFF portion of the duty cycle. The only time the leads are open (other than for a fleeting moment during the PWM cycle to prevent shoot-through current) is if they are in coast mode and a zero command is given. I am assuming the Jags are built to handle that condition repeatedly. Perhaps someone with intimate knowledge of the design could comment.
Because of the Jag’s switching method (shorting the leads during the OFF portion of the PWM cycle), using a voltage ramp (for decreasing voltage) creates a problem for the bang-bang control method. If the voltage is ramped down (instead of being allowed to be commanded immediately to zero), it may cause dynamic braking when the wheel speed (and thus the motor speed) is high and the voltage is low but not zero. For the bang-bang method, you do not want dynamic braking.
I might tune the voltage ramp to prevent this occurrence primarily, as well as preventing the Jags from shutting down.
Adding excessive voltage ramping may adversely affect the bang-bang’s dynamic response and accuracy.
This will be something I discuss with the mechanical side of my team.
I think it’s an electronic issue, not mechanical.
During the season we used PID (with a feed-forward and other modifications) to control our shooter, giving us our speed to +/- 20 RPM (out of around 4000 max). Yesterday I tried to implement the “bang-bang” controller in order to compare it to our PID loop. It seems our shooter does not have sufficient inertia to maintain a stable speed, as it oscillates uncontrollably.
The wheel we are using is a 4 inch diameter by 4 inch width wheel, made out of the hub of a plaction wheel and 4 inch diameter PVC pipe, so it should have significantly less inertia than the 6 or 8 inch wheels that many teams are using.
That doesn’t sound right at all. Something is amiss.
Would you mind posting the following additional information please:
-
what motor(s)
-
total gear ratio from motor to wheel.
-
Jag or Vic?
-
coast or brake mode?
-
voltage ramp rate?
-
what encoder model, and where mounted
-
what language
-
1x 2x or 4x decoding?
-
Counter or Encoder class?
-
to measure RPM, are you measuring the time between consecutive counts, or are you dividing the counts by the delta time?
-
if dividing counts by delta time (see above item), how are you computing the delta time
-
what execution cycle update rate?
-
what wheel rpm value were you trying to control
-
please elaborate a bit more on the nature of the oscillations: amplitude, frequency, etc
Ether,
Wow, THANK YOU! I am no LabView Guru either so I had no idea there was that much variation in the timing of “Wait” loops. It definitely explains much of the noise issues we saw this year while measuring our shooters rate.
So, based on the paper from 358 linked above, I modified my LabView version of the Bang-Bang control to use “Timed Structure”.
It has been refined to allow the enabling of a positive, adjustable, slew rate limiter. The limiter will maintain the same slew rate limit even if the loop timing is modified. It also has a tuneable IIR filter for the RPM reading, if necessary.
This thread will not allow me to attach the files, so you can get them here.
2 FP 0968-9015 motors. About a 3:1 reduction. Victors, coast. No voltage ramp (Does it need one?).
what encoder model, and where mounted
what language
1x 2x or 4x decoding?
Counter or Encoder class?
to measure RPM, are you measuring the time between consecutive counts, or are you dividing the counts by the delta time?
if dividing counts by delta time (see above item), how are you computing the delta time
what execution cycle update rate?
what wheel rpm value were you trying to control
please elaborate a bit more on the nature of the oscillations: amplitude, frequency, etc
This might be the problem. We are using a light sensor and a single strip of reflective tape to determine rate (one count per revolution). We used the Counter (labview) to determine rate by measuring time between counts. The execution rate was 20ms. I tried commanding wheel speeds between 2600 and 3600 rpm (the extremes of our shooter during competition). 20ms*(2600rpm * (1minute/60000ms)) = .867 rev/cycle. If the speed updates less often than the power command, would that throw it off? Thanks
This method is roughly equivalent to using a PID controller with Kp set to something very large (with Ki = Kd = 0) and the output limited to the range [0,1]. That might be the quickest way for many to implement this. We use a non-zero Ki and a feedforward term on our wheel, but then we have a very light shooter wheel assembly and don’t rely on the “flywheel” aspect as much as many teams.
I would be interested in hearing whether teams find that this method works better when running at a 200Hz loop rate (the maximum update frequency for Jags) than at the ~50Hz “xxxPeriodic()” loop rate. Intuitively, I would think it would make a big difference. The built-in WPIlib PIDController classes make this easy to implement.
We switched to this type of speed control (thanks for the post, Martin).
One thing that we found that is important: do NOT filter the encoder signal. Let it come in without any averaging or filtering. Here are some reasons why:
-
The inertia of the wheel and the on/off method of controlling the motor will filter out the noise naturally (mechanically), so why bother. Your control will be precise as long as the noise is zero-mean. If the noise isn’t zero-mean, then if you put in a filter your filter output will be offset by the noise mean anyway, so the filter doesn’t buy you anything.
-
The noise on the encoder signal serves to give you more resolution on your output and gives you more precise speed control. That sounds like it’s impossible, but it’s true. What you ideally want is as many on/off transitions as possible. The noise helps this to happen. The effect is similar to the theory behind sigma delta modulators.
-
Unless your filter and your mechanical system are phase matched, your shooter speed will oscillate, much like what was described by John a few posts above. We experienced this first hand when we first tried this approach. I noticed the oscillation and said “duh! I forgot to remove the filter.” We removed the filtering and voila - perfect speed control.
One important note: if you use your shooter speed as an input to some sort of shooting logic (for example: don’t allow the robot to shoot unless the speed is within a certain tolerance of the commanded speed), then you should definitely filter the signal going into the shooting logic. Just bypass the filter for your speed controller.
We started to look into this. After about an hour we came up with a few tests. We have an average of ± 18.2 rpm change from the target rpm.
Raw data is in this white paper:
http://www.chiefdelphi.com/media/papers/2667
Thank you for posting the data.
Would you mind posting the following additional information please?
-
what motor(s)
-
total gear ratio from motor to wheel(s).
-
what type and diameter wheel(s)?
-
Jag or Vic?
-
coast or brake mode?
-
voltage ramp rate? symmetric or up only?
-
what encoder model, and where mounted
-
what language
-
1x 2x or 4x decoding?
-
Counter or Encoder class?
-
to measure RPM, are you measuring the time between consecutive counts, or are you dividing the counts by the delta time?
-
if dividing counts by delta time (see above item), how are you computing the delta time
-
[strike]encoder signal not filtered[/strike]?
-
[strike]what execution cycle update rate?[/strike]
**PS: **You have some interesting noise on your sensor signal. Look at cells B57 & B58 for example.
Hi all, I was the programmer for 1771, and I played around with this method a lot. (Differing ramp rates, update times, etc.)
Our hardware set up was originally 1 FP motor in CIMulator to power the wheel.
The code didn’t run in the main tele-op loop, I had it run in its own task. It was set to read the encoder value and change the motor voltage every .05 seconds.
I had the CANJaguar voltage ramp rate set to 110 volts per second.
An important thing that I didn’t see mentioned, was WHERE the encoder got read.
We plugged the encoder directly into the Jaguar, and used the CANJaguar’s GetSpeed() function.
We believe that having it go directly to the Jaguar, NOT the cRIO’s FPGA, allowed it to be read faster. This may or may not have been true.
Of course all these values will change based on your shooter wheel.
As for the RPM consistancy-
When reading the values, we saw an average of 15 RPM difference from our set point for the RPM. If we had more time to dedicate to JUST tuning that, I feel we could have gotten a little bit more accuracy on that.
When reading the values, we saw an average of 15 RPM difference from our set point for the RPM. If we had more time to dedicate to JUST tuning that, I feel we could have gotten a little bit more accuracy on that.
You didn’t mention, but I assume you had the Jag set for coast mode, not brake, correct?
If you get a chance, try getting rid of the voltage ramp*****, and increase the update rate to 20ms instead of 50ms.
We believe that having it go directly to the Jaguar, NOT the cRIO’s FPGA, allowed it to be read faster.
I would think that reading the FPGA would be much faster than talking to the Jag via CAN bus. Does anyone have numbers for this?
*
*unless you need the voltage ramp to keep the Jag from shutting down at spinup. If so, try turning off the Jag’s voltage ramp and put a ramp in the cRIO instead, and make it active only in the increasing direction, and only for speeds below the necessary spinup speed.
*
*
Yes, it was coast mode, both on the jumper, and it is set to coast mode in our code.
When we didn’t have a ramp rate, we found that our RPM was less consistent, but I can try again. Although,from what we noticed, there was no ramp down, only ramping up.
As for the CAN vs FPGA, we aren’t sure. We used 2CAN, as we read that it its much faster than the serial form of CAN. And this shouldn’t matter but it was th last jaguar in our chain. (The sixth jaguar)
All of this was done with a single motor. At the north Carolina regional, we added a second motor and jag. We had the same code, and would justave the output to the new jaguar.
We found that it became less consistent, but after we tweaked the values, we got it tuned back. One thing we did try was having the second motor in brake mode, this worked and controlled the RPM nicely, but it got too hot for our liking.
As for the biggest loads being in the initial spin up, I made it where we always spun at a minimum of 500 RPM, so it would never have to pull too much current again.