-
Notifications
You must be signed in to change notification settings - Fork 908
Quadrature encoder example: too many ticks? #416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
ping @pmarques-dev who contributed this code in #126 |
Sometimes the encoder counts are specified in terms of "full steps", but the PIO code will count a step on any transition, so it ends up counting 4 steps per count. Note that is doesn't mean that any small noise will produce spurious counts, as a noise in one of the phases will just make the count increment and immediately decrement, as the PIO code implements the proper state machine that can count bidirectionally on every step. I would leave the max rate parameter at zero, to let the PIO run at full speed to make sure there are no aliasing issues. The only advantage of setting it to a lower value is to save some power, especially on battery powered devices. From your numbers, 41500 steps per output shaft revolution -> 41500 / 34 = 1220 steps per motor revolution, which would correspond to a 300 counts per turn encoder attached to the motor. If it's a high quality motor, that is not an unusual. The kind of cheap DC motors with gears we use in low cost robotics kits will have 11 counts per turn or similar. Also, at max speed of 240 RPM, that would give around 166.000 steps per second, which the PIO code should be able to handle just fine. If you still can't get that to work, I would suggest trying a couple of things:
|
I found the motor info here. The manufacturer claims that the encoder yields 360 counts per revolution, whilst I measured ~305 CPR by hand. Your PIO code information and estimates check out, thanks! The deltas do work in my controller. I'm not familiar dealing with two's complement arithmetics, is there any "risk" of dividing the transition values by 4, just for the sake of steps-to-counts conversion? |
As long as you take the full delta and then divide by 4, you should be alright. Just don't divide the output of the PIO code by 4 before taking the delta, as that would mess up the computation. Note that by doing that you're losing some resolution, which is probably ok in your case since you have plenty of that, although you don't really need to. But in general, especially with low cost encoders, you'll want every step possible, since otherwise at low speeds you'll get a larger quantization error in the speed (or position) estimate. I have even submitted a new pull request with a new version that uses not only the steps but the timing of the transitions to get a good speed estimate even at very low "steps per sample" regimes. In any case, my advice would be to not bother dividing by 4 and instead compute the floating point constant that converts from steps into whatever unit you're going to work with in the end and just multiply the delta by that. For instance, say you want the output of your system to be in rpm: one turn 360 * 4 * 34 = 48960, so if you get a count of 48960 in one minute you have 1 rpm. Since you are measuring once a second, you the count to be 1/60 of that per sample to be at 1 rpm, so 48960 / 60 = 816 steps per sample is 1 rpm. So if you multiply the delta you get by (1.0f / 816) you get a floating point number in rpm directly from the step delta. The compiler will do that computation at compile time for you. You can even write (1.0f / ((360 * 4 * 34) / 60)) if you want to document how you arrived at the number in the code. Something like: float speed_rpm = delta * (1.0f / ((360 * 4 * 34) / 60)); That is just one floating point multiplication to get you from the PIO output to the unit you want. Note that this will work for any other unit you want: radians per second, meters per second (e.g. this is a wheel of a robot), etc. |
Thanks so much for your advice and effort. I want to compute radians per second, 10 times per second, and chose
|
I would actually write that expression like this: |
Thanks much for those additional compile time and precision details I was not aware of, really appreciate it. The only risk I see to this approach, is to change PID loop time interval, and forget to change the denominator :) |
just define it as a constant and use it both to set the timer and in the expression. Something like:
or even:
in case you're not a big fan of pre-processor defines. This is still all resolved at compile time anyway. |
I'm getting what I believe is way too many encoder ticks from my DC motors. I'm referring to my RPi forum thread, which understandably has vaned off in attention.
TLDR: I hooked up my DC motor encoders to the Pico, and turned one revolution by hand. It consistently yields 41,500 ticks for one output shaft revolution. Motor data: max 240 RPM, gear ratio 1:34.
https://forums.raspberrypi.com/viewtopic.php?t=355234
The text was updated successfully, but these errors were encountered: