with 300 cycles per revolution / 1200 pulses per revolution. I have it hooked up to an AVR microcontroller (atmega168) using two external interrupt pins for the A and B channel (there is no index channel). This is working and I have a variable that keeps track of the encoder pulses and uses a 4state machine to check the rotation direction, so the variable goes + for forward rotation and - for reverse rotation.
I am now trying to get an averaged rotation rate for the last 1ms, 10ms,
100ms, 1s and 10s. I have an interrupt that runs every 1ms for this but the code only updates the rotation rate variables once per period, ie. once per second for the 1s variable, instead of giving a continuously updated value from the last second.
Any ideas on how to fix this? I was thinking about using a digital lowpass filter:
formatting link
for each rotation rate variable but am not sure if that is the best way to do it.
What is best depends entirely on just what you want to do with the information, and what your memory resources are. The IIR filters that you'll get from that page will certainly give you effective averaging at low phase delay and low memory requirements, but they won't give exact moving averages, if that's what you really need.
--
Tim Wescott
Wescott Design Services
http://www.wescottdesign.com
Posting from Google? See http://cfaj.freeshell.org/google/
"Applied Control Theory for Embedded Systems" came out in April.
See details at http://www.wescottdesign.com/actfes/actfes.html
You need to store the values for each interrupt period in a circular array and do the sum on the entire array. If you have 1ms interrupts you will need to store 1000 values in the array. This is a lot of memory so you'll probably want to store values only every 10 or 100ms.
Strictly speaking it is a digital filter, only much simpler than Chebychev & al.
This does not look doable, especially the longer times. So the question becomes why do you need these values and what are you doing with them? And, is there another way of accomplishing that?
I can see how to do this in four circular buffers of 10 values each, and an accumulator (or two) for each circular buffer.
Requoting more of the OP:
What will be the maximum RPM of this thing? This will tell you the number of bytes to allocate for each value at each stage.
Presuming fix means rewrite:
Use a circular buffer of the last 10 1ms values. You could brute-force sum all ten values every 1ms, which may be feasible and is simpler programming, but you can find the sum much faster (presuming they start out zero when the code starts, which they really should) by using an accumulator. Subtract the 10th value from the accumulator, put the new value into the circular buffer (erasing the old 10th value you just subtracted), and add this value to the accumulator. Thus the accumulator will always have the sum of the most recent 10 values in the circular buffer. The usual caveats apply, be sure everything has enough bits for the maximum value it can hold. If you need an actual average, divide the accumulator value by 10 (and store in yet another varuable, and use THAT as the input to the next, uh, paragraph), but if you have enough bits to hold all the sums or need higher resolution on the longer averages, just continue using sums, and only use division to get the actual average values to send off somewhere. Use a circular array of the last 10 10ms values you got from the previous paragraph, and do likewise with it to get a 100ms sum or average. Continue for 100ms and 1s, giving 1s and 10s averages/sums respectively. Total operations each 1mS (not counting division to get actual averages and whatever code to send these values somewhere) is four subtracts, four adds, and eight buffer operations. The brute-force option changes that to 40 adds and and eight buffer operations. To get actual averages instead of sums, you also need to do four divides each
1mS, each by a fixed power of 10.
This is a FIR filter with 10 coeficients of value 1 each (or 0.1 if you want the output automatically divided by 10). But you don't need to know that. ;-)
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.