Open bcontino opened 8 years ago
EncoderMod has a built in speed function, but it can be noisy and inaccurate. On the average it works well, but if we are using rapid readings to quickly adjust speed control it may give us weird results
We can start with EncoderMod, but be looking for other ideas
Way may want to average the front and rear readings on each side, and start using the slowest readings after they deviate by some predetermined amount
We might want to time encoder ticks by polling in our program instead of timing between ever discrete encoder tick in the ISR. This is effectively averaging the velocity readings though
We could do a moving average of the last X number of readings to smooth out noise. It will give us a slower response but a slower response might be better than attempting to respond to noisy data
At a top speed of 1000mm/sec we will get a max interrupt speed from an encoder at 1000/0.644 = 1.5Khz. Our timing is being done using an elapsedmicros variable that automatically increments, as long as elapsed micros is precise to the microsecond as claimed then we should have plenty of precision and accuracy assuming a constant speed.
Even free running as quentin tested, the 10:1 motors are rated at 3000rpm on the output shaft. 3000 rpm / 60 = 50rev/sec. 50rev/sec * 10:1 * 12 count/rev = 6000ticks per second, which still gives us plenty of resolution with our microsecond timing. However, is it possible that motors did not have a constant free running speed and that is why you were not receiving a constant velocity?
I went over encoder_mod and the wrapper functions in encoding.cpp/h and found no significant problems, long story short, I do not think we will be able to improve on them enough to make a difference in our results. It is very tightly optimized. That being said, everything is contingent on elapsedMicros being accurate to a microsecond however I think it is safe to assume they are.
So that leaves an averaging algorithm. I think a moving average on each encoder would be ideal. Since our maximum expected steps/s is ~1.5KHz I think we should sample the velocity at that speed. The amount of values then that we average over should be determined by the maximum acceleration we expect to encounter and the maximum error we can tolerate in our calculated velocity. Collisions do not count as they are a case where we do not care how much we slowed down. However the math to figure that out is very long, I think it would be best to empirically decide through testing how many samples we choose to keep. The important part is that I think we should sample our velocity data at a rate of 1.5Khz or higher and keep a constant amount of samples in the moving average buffer. I think with this technique we would only need buffers of 50 samples. 1.5KHz/50 = 30Hz meaning that we will be getting completely new velocity data 30 times a second. Thus we will be able to register a worse case scenario instantaneous deceleration of 1m/s to 0m/s deceleration in 1/30 = 33mS. In many cases we will be able to do better.
In the case that we are not going very fast, say 0.5m/s we will only effectively be getting 25 samples/sec with this algorithm. However, if we were to delay our readings until we had a full 50 samples in the velocity buffer it would take twice as long to calculate our current velocity. I don't think we want to get in to the sub 20Hz velocity update range. Things change fast in the sumo bot arena.
Now that that's all been said, why do we need to know instantaneous velocity? Why can't a PID loop be tuned to filter out the noise and keep the wheel turning at the constant velocity requested by the logic code? The logic code would then never need to know the instantaneous velocity. It just asks the PID controller to get the robot moving at a desired speed.
Tl;dr I don think we can optimize encoder_mod with a reasonable amount of effort and that we should go for a moving average on the average each encoders wheels. Also why do we need to know instantaneous velocity in the first place?
Use the latest EncoderMod library from Quentin, the velocity is filtered with a moving average. The amount of time averaged over and the rate samples are taken can be set. This should be tuned for our setup when the time comes.
encoder_mod currently has a speed function. Good enough?