However, I couldn't think of a way to implement this equation.
Pulses per revolution is 256 for my encoder.
I don't know how to determine a fixed period. I mean every time I have a rising edge from one of the encoder channels, I have one increment or decrement.
By the way, encoder also has the Index pin,which shows a rising edge at one full revolution of the encoder. Not sure if this comes in handy
Appreciate if you can share your ideas on how to get the velocity from encoder.
Pick one of the quadratures and every 16th (or some other power of 2) ISR grab the milliseconds and calculate the rate. I say power of 2 as that math can be done very fast in the ISR.
(current_millis - last_millis) >> 4;
You may have to declare the last_mills as volatile so it is available in the ISR.
w1jp:
Pick one of the quadratures and every 16th (or some other power of 2) ISR grab the milliseconds and calculate the rate. I say power of 2 as that math can be done very fast in the ISR.
(current_millis - last_millis) >> 4;
You may have to declare the last_mills as volatile so it is available in the ISR.
Why do you shift it by 4 to left ?
And why 16 or why power of 2.
Binary math's are Much faster than int and floating types. Try to remember that binary is native to the 'bare metal'.. Other types aren't, as they require conversion to binary, first.
I knew that, I know that. But yeah, I guess for all intents and purposes I may as well not have : - I just went with the code as is.
This good point means that I either don't know what w1jp is doing and it's legit, he/she has also made the same error, he/she made another error that I don't see and/or we both don't know what we're talking about but it's somehow works anyway.
But yes, if you follow my logic from the previous post - it should be:
I knew that, I know that. But yeah, I guess for all intents and purposes I may as well not have : - I just went with the code as is.
This good point means that I either don't know what w1jp is doing and it's legit, he/she has also made the same error, he/she made another error that I don't see and/or we both don't know what we're talking about but it's somehow works anyway.
But yes, if you follow my logic from the previous post - it should be:
(current_millis - last_millis) >> 2;
I think w1jp has nothing to do with unit pulse.
I mean he was just trying to count the pulses in a certain amount of time. Choosing 16 was just an arbitrary choice and since it is power of 2, it makes it easier to do the division with binary operation, i.e. shifting by 4 in the case of division by 16.
That's what I get.
However, I am still confused.
If the time elapsed between first and 16th count is smaller, meaning the motor spins faster, then the
(current_millis - last_millis) >> 4;
formula would give me a small number.
But if my motor spins slow and time elapsed between first and 16th count is larger, then I would get a bigger result.
You can measure the number of transitions in a fixed unit of time, this gives frequency/velocity
directly, but not much accuracy at low speeds.
You can time transistions, and get the period directly, but then you have to take a reciprocal
somewhere to get velocity/frequency. The accuracy is best at low speeds, but you have the
problem that if motions stops, you only have the period for the last time it moved, which might be
a lot shorter than the time since the last transition, so you have to check for this.
2^4 is 16. 256/16 gives you enough pulses to calculate a rate and still have the rate calculated 16 times per revolution. If you don't want the rate that dynamic try >>5 or 6 (32 or 64) which will calculate the rate 8 & 4 times per revolution respectively. I am also trying to find something that will keep the math easy.
If the time elapsed between first and 16th count is smaller, meaning the motor spins faster, then the
(current_millis - last_millis) >> 4;
formula would give me a small number.
But if my motor spins slow and time elapsed between first and 16th count is larger, then I would get a bigger result.
Ain't something wrong here ?
That is just the time.
avg_time = (current_millis - last_millis) / 16;
rate = 22.5º / avg_time;
22.5º is 1/16th of a revolution since we are sampling at 1/16th. Again I would probably do 22,500 millidegrees to leverage integer math. (since millidegrees per millisecond is the same as degrees per second).
I picked these numbers purely arbitrarily to show you an approach. I am not sure what speed range this motor is spinning at and what your area of interest in measurement is. You should sample at 10-25 times the rate measurement you want. Sampling at the Nyquist rate (2x) would require some shooting math. Let the physics smooth the number for us.
These numbers are targeted more at a hand-turned rotary encoder. To be honest, I did not read the electric motor piece. To pick real numbers, I'd need to know. Motor max speed, useful measurement range, and application.
A FAR better way to determine speed is to use one of the hardware timers to do the timing for you. It can give you a very accurate measurement of the time between two edges on the encoder. There are libraries out there to do this.
zoom:
Why do you shift it by 4 to left ?
And why 16 or why power of 2.
16 is between 10-50 (see below). Power of 2 because the integer math is efficient. You could pick 15.
In sampling theory, the slowest you can sample to identify individual pulses is 2X the pulse rate (called the "Nyquist rate"). Sampling close to the Nyquist rate is quite noisy and requires smoothing. To avoid the smoothing math, we just sample at a much slower rate (multiple pulses) and let the physics smooth the numbers for us. Ideal statistical samples in large populations (a spinning motor is a large population of pulses) is 25 for a 99% confidence level. So 10-25 samples of a 10-50 th the Nyquist rate gives us very good rates.
RayLivingston:
A FAR better way to determine speed is to use one of the hardware timers to do the timing for you. It can give you a very accurate measurement of the time between two edges on the encoder. There are libraries out there to do this.
I am not sure what a hardware timer would buy you here. Timing is easy. In the ISR, just call millis();
Having the precise time between edges will give you the precise period. You would need to collect 10-25 of these periods to get a decent average. Averaging 25 numbers is much harder than averaging a single time over 25 occurrences.