Maker Pro
Maker Pro

fixed point digital low pass filters

J

Jamie Morken

Jan 1, 1970
0
Hi,

This digital filter design tool:
http://www-users.cs.york.ac.uk/~fisher/mkfilter/


#define NZEROS 1
#define NPOLES 1
#define GAIN 1.324919696e+00

static float xv[NZEROS+1], yv[NPOLES+1];

static void filterloop()
{ for (;;)
{ xv[0] = xv[1];
xv[1] = next input value / GAIN;
yv[0] = yv[1];
yv[1] = (xv[0] + xv[1])
+ ( -0.5095254495 * yv[0]);
next output value = yv[1];
}
}
 
M

MooseFET

Jan 1, 1970
0
Hi,

This digital filter design tool:http://www-users.cs.york.ac.uk/~fisher/mkfilter/

#define NZEROS 1
#define NPOLES 1
#define GAIN 1.324919696e+00

Is 256/193 close enough for you gain?
static float xv[NZEROS+1], yv[NPOLES+1];

static void filterloop()
{ for (;;)
{ xv[0] = xv[1];

How many bits are in xv?
xv[1] = next input value / GAIN;
yv[0] = yv[1];
yv[1] = (xv[0] + xv[1])
+ ( -0.5095254495 * yv[0]);

Is 130/256 good enough here?
next output value = yv[1];
}
}


The fact that you are adding the two values from xv[] makes the gain
at Nyquist hit zero. The rest of it doesn't do that much what is the
exact purpose of the filter? You may be able to do it in a way that
is much easier to code in a micro controller. Ideally, you'd like to
completely avoid multiply and divide operations other than simple
binary shifts.
 
J

John Larkin

Jan 1, 1970
0
Hi,

This digital filter design tool:
http://www-users.cs.york.ac.uk/~fisher/mkfilter/


#define NZEROS 1
#define NPOLES 1
#define GAIN 1.324919696e+00

static float xv[NZEROS+1], yv[NPOLES+1];

static void filterloop()
{ for (;;)
{ xv[0] = xv[1];
xv[1] = next input value / GAIN;
yv[0] = yv[1];
yv[1] = (xv[0] + xv[1])
+ ( -0.5095254495 * yv[0]);
next output value = yv[1];
}
}


I like

out = out + (in-out)/K

where the divide-by-K is an arithmetic shift right. That makes a
single-pole lowpass with a gain of 1. But I'd prefer a decent clock to
cutoff ratio, 4-8 at least. The integer variables must be able to
handle the adc data bits plus the right-shift thing.

John
 
V

Vladimir Vassilevsky

Jan 1, 1970
0
John said:
#define NZEROS 1
#define NPOLES 1
#define GAIN 1.324919696e+00

static float xv[NZEROS+1], yv[NPOLES+1];

static void filterloop()
{ for (;;)
{ xv[0] = xv[1];
xv[1] = next input value / GAIN;
yv[0] = yv[1];
yv[1] = (xv[0] + xv[1])
+ ( -0.5095254495 * yv[0]);
next output value = yv[1];
}
}



I like

out = out + (in-out)/K

where the divide-by-K is an arithmetic shift right. That makes a
single-pole lowpass with a gain of 1.

John, you are quick at learning... but you did a mistake here :)

As it was pointed by Moose, the action of the foregoing filter is mainly
because of zero, not because of the pole. The zero at Nyquist is
produced by (xv[0] + xv[1]).

So, for the Fsa = 250kHz Fc = 100kHz the best solution could be a FIR
filter. With the FIR filter, it is also simpler to get by shifts instead
of multiplication.


Vladimir Vassilevsky
DSP and Mixed Signal Design Consultant
http://www.abvolt.com
 
J

John Larkin

Jan 1, 1970
0
John said:
#define NZEROS 1
#define NPOLES 1
#define GAIN 1.324919696e+00

static float xv[NZEROS+1], yv[NPOLES+1];

static void filterloop()
{ for (;;)
{ xv[0] = xv[1];
xv[1] = next input value / GAIN;
yv[0] = yv[1];
yv[1] = (xv[0] + xv[1])
+ ( -0.5095254495 * yv[0]);
next output value = yv[1];
}
}



I like

out = out + (in-out)/K

where the divide-by-K is an arithmetic shift right. That makes a
single-pole lowpass with a gain of 1.

John, you are quick at learning... but you did a mistake here :)

As it was pointed by Moose, the action of the foregoing filter is mainly
because of zero, not because of the pole. The zero at Nyquist is
produced by (xv[0] + xv[1]).

So, for the Fsa = 250kHz Fc = 100kHz the best solution could be a FIR
filter. With the FIR filter, it is also simpler to get by shifts instead
of multiplication.


Vladimir Vassilevsky
DSP and Mixed Signal Design Consultant
http://www.abvolt.com


Well, a Butterworth doesn't have a finite zero!

This works, but as I noted I'd prefer a higher clock to cutoff
frequency ratio. Given how little computing is required - this filter
is just a few machine instructions on a 68k-class machine - more
frequent execution is affordable.

Aliasing will be a problem for any sampled filter, and 100 KHz cutoff
with a 250 KHz sample rate will get interesting. So a simpler
algorithm run at a higher rate might be better.

All this depends on the reality of the application.

John
 
V

Vladimir Vassilevsky

Jan 1, 1970
0
John Larkin wrote:

As it was pointed by Moose, the action of the foregoing filter is mainly
because of zero, not because of the pole. The zero at Nyquist is
produced by (xv[0] + xv[1]).
Well, a Butterworth doesn't have a finite zero!

There is also no such thing as Butterworth of the first order.

They designed the digital filter from the analog function by bilinear
transform, hence the zero at infinity is mapped to zero at Nyquist.
Aliasing will be a problem for any sampled filter, and 100 KHz cutoff
with a 250 KHz sample rate will get interesting.

In my practice, such requirement (80%) is not very unusual. Making a
steep LPF with the cutoff higher then 90% of Nyquist could be problematic.
So a simpler
algorithm run at a higher rate might be better.

With FPGA, you trade off complexity for speed. With DSP, you trade off
speed for complexity.


Vladimir Vassilevsky
DSP and Mixed Signal Design Consultant
http://www.abvolt.com
 
J

Jamie Morken

Jan 1, 1970
0
John said:
Well, a Butterworth doesn't have a finite zero!

This works, but as I noted I'd prefer a higher clock to cutoff
frequency ratio. Given how little computing is required - this filter
is just a few machine instructions on a 68k-class machine - more
frequent execution is affordable.

Aliasing will be a problem for any sampled filter, and 100 KHz cutoff
with a 250 KHz sample rate will get interesting. So a simpler
algorithm run at a higher rate might be better.

All this depends on the reality of the application.

Hi,

Its for a SMPS I'm working on, I decided to risk the path to madness
that MooseFet once warned about, and try software control of the
inverter section as I couldn't find an easy way to do it with a PWM
controller IC as it is an AC output that is generated from two +-DC
rails.

I think digital filtering might be complicated by having to synchronize
the ADC sampling with the 100kHz switching, since the dutycycles are
variable each cycle the sampling won't have the same intervals, so this
may not work well with digital filtering I am not sure. Maybe the
best way is to grab 5 or so samples over the on or off time, and then
average them each cycle, for calculating the next ontime, or just use
1 sample per dutycycle and hope for the best? :)

cheers,
Jamie
 
Top