View Single Post
  #15   Spotlight this post!  
Unread 10-09-2008, 16:35
Kevin Sevcik's Avatar
Kevin Sevcik Kevin Sevcik is offline
(Insert witty comment here)
FRC #0057 (The Leopards)
Team Role: Mentor
 
Join Date: Jun 2001
Rookie Year: 1998
Location: Houston, Texas
Posts: 3,721
Kevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond repute
Send a message via AIM to Kevin Sevcik Send a message via Yahoo to Kevin Sevcik
Re: Servo 'smoothing'

Erik,

Translating your IIR to fixed point doesn't seem entirely straightforward to me. Or, at least, we should remind the audience of the wonderful effects known as truncation and loss of precision. You'd need to process your new value and carry your old value as scaled integers, or you'd lose everything behind the decimal point and get weird jumps in your values. So it'd look something like:

Code:
#define SCL 4  //4 gives you 1/2^4th (1/16th) adjustments in tau
tau = 12;  //This is the tuning variable
old_sensor_in = tau*(sensor_in<<SCL) + ((1<<SCL)-tau)*old_sensor_in;
old_sensor_in >>= SCL;
pwm_out = old_sensor_in >> SCL;
With typecasting as appropriate and always remembering that MPLAB doesn't support signed shifting, so this only works for unsigned numbers.

To 0705920,

I've always shied from the brute force style of moving averages, as your processing time increases quadratically with the number of samples you want to take, and that doesn't really sit well with me. Plus attempts to increase your number of samples quickly get out of hand. My preference is something like:
Code:
#define AVG_SAMPLES 8

static int temp[AVG_SAMPLES] = 0;
static int accumulator = 0;
static char count = 0;
static int smooth = 0;

accumulator -= temp[count];
temp[count] = Get_Analog_Value(ana_in_yy);
accumulator += temp[count];
smooth = accumulator / AVG_SAMPLES;
count += 1;
count = (count >= AVG_SAMPLES) ? 0 : count;
With the caveat that you must always make certain that accumulator and the temp array start out with zero values and that they don't get out of sync. If you clear the accumulator without clearing the array, you subtract old values from zero and basically start measuring the difference between the average when you cleared the accumulator and your current average. (Not a bad way of canceling an offset, though.) Clearing the array and not the accumulator gives the opposite problem.

And of course if you're sticking with strict powers of 2, there's several optimizations you can make to speed things up. (Hint: Division is evil, and XOR is, in fact, useful for math occasionally) But I think your main benefit comes from not adding 32, 64, or 128 numbers in every cycle.
__________________
The difficult we do today; the impossible we do tomorrow. Miracles by appointment only.

Lone Star Regional Troubleshooter