|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
| Thread Tools | Rate Thread | Display Modes |
|
#31
|
||||
|
||||
|
Re: Speed PID Function
Quote:
Show your code to your mentor and ask him. |
|
#32
|
|
I just saw what you meant you are right. My bad.
|
|
#33
|
|
|
My mentor sent me this.
Quote:
|
|
#34
|
||||
|
||||
|
Re: Speed PID Function
Quote:
Another option is to use an IIR filter instead of FIR. It's simpler and it's tunable: Code:
public void getSpeed(){
filtered_count = a*filtered_count + (1-a)*Shooter_En.getRaw();
Shooter_En.reset();
Rate = filtered_count /0.48;
}
Quote:
Last edited by Ether : 01-02-2012 at 21:39. |
|
#35
|
|
Re: Speed PID Function
Am I stupid.
Or is the CAN Jaguar functions built to do all of this for me. |
|
#36
|
||||
|
||||
|
Re: Speed PID Function
If you use CAN to communicate with the Jag, then you can plug the encoder directly in to the Jag and access the Jag's built-in PID (built-in to the Jag's firmware) to control speed. There are several threads on CD discussing the pros and cons of doing this.
I don't know what kind of noise filtering, if any, the Jag does on the encoder signal. Others on this forum have studied the Jag firmware source code (freely available) and may be able to answer. |
|
#37
|
|||
|
|||
|
Re: Speed PID Function
Quote:
avg(n) = avg(n) + (sample(n) -sample(n-L))/L where L is the length of the average. Essentially before you overwrite the oldest sample, you calculate the difference and then overwrite and compute the new average. |
|
#38
|
||||
|
||||
|
Re: Speed PID Function
Quote:
Although the bigger question here is, do they really need a filter at all? If they're reading the encoder delta counts every execution cycle and dividing by the cycle period, there's already a whole lotta averagin' goin' on (except at very low speeds). |
|
#39
|
|||
|
|||
|
Re: Speed PID Function
Quote:
![]() For our team, we plan to bypass getRate() and derive encoder rate by (encoder – encoder_last)/T where T is the loop update time. Our typical wheel speed is 2000 rpm or 33.3 rps . The encoder has 250cnts per rev so there are about 8333 cnts/sec. With a 20 ms loop, there are 167 cnts per cycle. If 1 pulse is missed, it is less than .6% error. The code wheel slit phase errors are being averaged over half of the wheel so much of the high frequency phase variations that would affect getRate() are averaged out. |
|
#40
|
|||
|
|||
|
Re: Speed PID Function
Our team was also getting wild fluctuations with velocity, with an error range of upwards of 300 RPM and spikes that extend well past 1000 RPM beyond our setpoint. This was unacceptable for our PID control loop, so our mentor suggested we implement a moving average/median filter to smooth out the graph and get rid of those nasty rate spikes. We also changed the encoder rate to k1X instead of k4X (default).
We are working with the command-subsystem in Java, so this should might help those that are working with PIDSubsystems (which our Shooter class is). We only changed the returnPIDInput() method. The result was an incredibly smooth graph, fluctuating within an acceptable range that can be tuned with the P constant (and maybe D depending on how close to the value we get). Here is a picture of repeated tests. In the above picture, there were 5 tests separated by the deep drops to zero (First 4 were set to 1000RPM, the last set to 2000RPM0. You can see how much smoother the fluctuation of RPM is (the fluctuation that still persists is a result of a much-needed PID constant tuning). As stated earlier, we went from a 300-1000 RPM spike/fluctuation to one less than 100 RPM. We also played around with the sampling size, and we chose 20. It did not affect cRIO CPU usage very much at all. 100 sampling size provided no advantage from what we saw compared to 20. Here is our implementation of the returnPIDInput() Code:
private double[] samplingValues = new double[HW.SAMPLING_SIZE];
//MOVING MEDIAN/AVERAGE FILTER BASED ON A SAMPLING SIZE OF "N" VALUES (ex. 20)
protected double returnPIDInput() {
//LOOP THROUGH AND SHIFT ALL VALUES TO THE RIGHT BY ONE, REMOVING THE LAST VALUE
for(int i = samplingValues.length-1; i > 0; i--){
samplingValues[i] = samplingValues[i-1];
}
//PUSH IN A NEW VALUE BASED ON RATE (we are using RPS*60 = RPM)
samplingValues[0] = shooter_encoder.getRate()*60;
//TEMP ARRAY FOR PERFORMING MEDIAN OPERATION
double[] median = Arrays.copy(samplingValues, 0, HW.SAMPLING_SIZE, 0, HW.SAMPLING_SIZE);
Arrays.sort(median);
//RETURNS THE MIDDLE OF THE SORTED MEDIAN ARRAY
return median[median.length/2];
}
Hope this helps, David K. Team Spectrum FRC#3847 |
|
#41
|
||||
|
||||
|
Re: Speed PID Function
David,
If I am reading this correctly, you are doing the following: 1) Using GetRate() to grab the "instantaneous" (consecutive-count) rate from the FPGA, and then Have you tried any of the suggestions in earlier posts in this thread, such as: a) Instead of using GetRate(), read the encoder counts instead, and divide by the sampling time (as explained in post39), or |
|
#42
|
|||
|
|||
|
Re: Speed PID Function
Here is a note on precalculating PID gains without a simulation. The note has the full derivation.Excerpt:
Note: Precomputing PID gains for a velocity shooter using pole/zero placement I wanted to post some formula’s for deriving P and I gains for a velocity PID control loop such as a shooter used in the 2012 Rebound Rumble game. Assumptions: a) motor L/R time constant is small relative to motor control frequencies. b) The motor first order time constant tau_m is known. c) The input speeds are normalized to the maximum motor speed, w_max. w_max = 12v/ke*60/2pi rpm which is approx w_free of the motor. d) The desired motor response time constant, tau_d, is smaller than the motor tau_m by a factor of r. Then the integral gain KI is given by KI = 1/tau_d and the proportional gain KP is given by KP = r = tau_m/tau_d ; If the integral computation of the PID loop doesn’t contain a dt factor (i.e it is just an error accumulation) as is typical of the WPILIB PIDcontroller then the KI must be multiplied by the PID update period. KI_WPILIB = T/tau_d where T is the PID period. If you are feeding back RPM then the gains must be divided by w_max. Example: The 599 shooter wheel has an open loop time constant tau_m = .68 sec We want to have a tau_d = .33 sec which means the error should be around 1% of the target by 1 second (three time constants). During autonomous this would be the delay before we can shoot. KI = 1/tau_d = 3. KP = tau_m/tau_d = 3*.68 = 2.04 ; For WPILIB we want KI_WPILIB = T*KI = .05*3 = .15 ; KP remains the same. The shooter has a w_max = 5614 rpm so if the feedbacks are not normalized then KP and KI must be divided by w_max. or KP = 2.04/5614 = 3.63 e-4 ; KI_WPILIB = .15/5614 = 2.49e-5 ; Thats it. The main factor limiting the value of KP is the magnitude of the noise on the RPM feedback signal. Typically after filtering this can get down to 1% of the RPM. KP multiplies the noise so to keep the noise below 5% then the max KP would be 5. Last edited by vamfun : 22-02-2012 at 15:49. |
|
#43
|
||||
|
||||
|
Re: Speed PID Function
I wanted to sum this information up for some of the team members (since a couple of the kids on my team didn't understand a lot of things in this post).
First - the getrate implementation (at least in labview) oscillates because it has a very short time period. To obtain a more stable rate, you canput the calculation function in periodic tasks and run it at its own loop speed. This function should be: (current encoder count - past encoder count) / loop time = count rate To smooth this rate further, you can average the samples over several loops, or you can extend the time (calculate the count over 2 or three loops and the time over 2 or three loops). Both may give you somewhat delayed results, depending on your loop rate. Next, a speed PID varies mainly in that you need to send the setpoint from the last speed loop into the new loop and modify THAT value. This prevents wheel reversal. The derivation from Jared on team 341 can be found here: http://www.chiefdelphi.com/forums/sh...7&postcount=13 It shows the derivation and implementation of a velocity PID loop. |
|
#44
|
||||
|
||||
|
Re: Speed PID Function
Can you address this in a bit more detail?
Are there some fairly simple tests that a team could do to obtain this number? Or do you recommend calculating, and if so it might be helpful to do a blog entry on that or post some example calculations here. |
|
#45
|
||||
|
||||
|
Re: Speed PID Function
Quote:
Quote:
Quote:
|
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|