LowPassFW

  • 1
  • 2
  • Page 1 of 2
robertkc
 
Avatar
 
Subject:

LowPassFW

 · 
Posted: 04.10.2013 - 20:13  ·  #1
I ran across LowPassFW in the documentation, but all that is said about it is "T.B.D." Also, there is an example in the examples folder, but that doesn't tell me very much either.

Can anyone provide more details on how LowPassFW works?
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: LowPassFW

 · 
Posted: 04.10.2013 - 21:17  ·  #2
Hello Robert,

this filter function was provided by an user a very long time ago.
Here are the definitions in AVRco:

Code
TFiltData = record 
  value : word; 
  Err   : byte; 
end;

TFilterFreq = (ffdiv2,ffdiv4,ffdiv8,ffdiv16,ffdiv32,ffdiv64,ffdiv128,ffdiv256);

procedure LowPassFW(var FiltData : TFiltData; NewVal : word; FilterFreq : TFilterFreq);
var
  lw           : longword;
  LowWord[@lw] : word;
  UpWord[@lw+2]: word;
  ShiftCount   : byte;
  BitMask      : byte;
  LowByte[@lw] : byte;
begin
  ShiftCount     := ord(FilterFreq) + 1;
  BitMask        := %11111111 shr (8 - ShiftCount);  //Calculate ErrorBitMask
  UpWord         := 0;                               //Reset upper part of lw
  LowWord        := FiltData.Value;                  //Set Lower part of lw with old FilterOutput
  lw             := (lw shl ShiftCount) - lw;        //Equal to lw := lw * (2^ShiftCount - 1)
  lw             := lw + LongWord(NewVal + word(FiltData.Err)); //Add NewVal and Old Error
  FiltData.Err   := LowByte AND BitMask;             //Save Modulo of 2^n division
  lw             := lw shr ShiftCount;               //Perform 2^n division
  FiltData.Value := LowWord;                         //Store ResultValue of Filter
end;

But don't ask me what it does, no idea... :binky:

rolf
robertkc
 
Avatar
 
Subject:

Re: LowPassFW

 · 
Posted: 05.10.2013 - 19:16  ·  #3
Thank you for the reply.

I guess I'll have to play around with it to learn more. :)

Quote by rh

Hello Robert,

this filter function was provided by an user a very long time ago.
Here are the definitions in AVRco:
[...]
But don't ask me what it does, no idea... :binky:

rolf
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: LowPassFW

 · 
Posted: 08.10.2013 - 18:14  ·  #4
@all,
the very first appearance of this Filter in AVRco was Oct.2005 :color:
Of course this is a lowpass filter, but does anyone exactly know what
it does? Maybe Avra?
It would be fine if I can get a good explanation for our compiler manual... :unknown:

rolf
Avra
Schreiberling
Avatar
Gender:
Location: Belgrade, Serbia
Age: 53
Homepage: rs.linkedin.com/in…
Posts: 653
Registered: 07 / 2002
Subject:

Re: LowPassFW

 · 
Posted: 10.10.2013 - 15:52  ·  #5
Quote by rh
Maybe Avra?


It provides inertion to changing filter value, with inertion resistance as TFilterFreq parameter. Higher parameter value gives higher resistance to changing fiter value. First picture explains everything. Code exploits shifting bits in a word for fast division, and takes just between 354 cycles (ffDiv2) and 423 cycles (ffDiv256) to provide result quickly. I guess that W in LowPassFW name stands that it is a word parameter based version. Longword, byte, or a positive fixed point number version could be also made of it.

Now I will try to explain how it works. For example, if you start with FiltData.Value = 0 and want to apply NewValue = 1000 once using ffDiv2, then after first LowPassFW call FiltData.Value will have half of a difference between FiltData.Value and NewValue which is (1000-0)/2=500. Then in next call to LowPassFW difference between FiltData.Value and NewValue is (1000-500)/2=250 and FiltData.Value will be 500+250=750. After next call FiltData.Value will be 750+125=875, next 875+62=937, and so on and so on (if NewValue is still 1000, of course). So, ffDiv2 will adjust on each call for half of a difference, ffDiv4 will adjust for one fourth of a difference, ffDiv8 one eight of a difference, etc. You get the picture. Therefore ffDiv2 allows filter value to change with much higher frequency then with ffDiv256, which is much, much slower. So, choosing higher TFilterFreq allows us to filter more peaks in analog signal data acquisition and smoother trending data without instant jumps.

Here is some simple test code for better understanding:
Code
program LowPassFilterTest;

{$NOSHADOW}
{ $WG}                     {global Warnings off}

Device = mega88, VCC=5;
{ $BOOTRST $00C00}         {Reset Jump to $00C00}

Import SysTick, SerPort, LCDport;

From System Import LongWord, LongInt, Float;


Define
  ProcClock      = 16000000;       {Hertz}
  SysTick        = 10;             {msec}
  StackSize      = $0032, iData;
  FrameSize      = $0032, iData;
  SerPort        = 9600, Stop1;    {Baud, StopBits|Parity}
  RxBuffer       = 8, iData;
  TxBuffer       = 8, iData;
  LCDport        = PortB;
  LCDtype        = 44780;
  LCDrows        = 2;              {rows}
  LCDcolumns     = 40;             {columns per line}

Implementation

{$IDATA}

{--------------------------------------------------------------}
{ Type Declarations }

type
  TFiltData = record
    Value : word;
    Err   : byte;
  end;


{--------------------------------------------------------------}
{ Const Declarations }

{--------------------------------------------------------------}
{ Var Declarations }
{$IDATA}


{--------------------------------------------------------------}
{ functions }

TFilterFreq = (ffdiv2,ffdiv4,ffdiv8,ffdiv16,ffdiv32,ffdiv64,ffdiv128,ffdiv256);

procedure LowPassFW(var FiltData : TFiltData; NewVal : word; FilterFreq : TFilterFreq);
var
  lw           : longword;
  LowWord[@lw] : word;
  UpWord[@lw+2]: word;
  ShiftCount   : byte;
  BitMask      : byte;
  LowByte[@lw] : byte;
begin
  ShiftCount     := ord(FilterFreq) + 1;
  BitMask        := %11111111 shr (8 - ShiftCount);  //Calculate ErrorBitMask
  UpWord         := 0;                               //Reset upper part of lw
  LowWord        := FiltData.Value;                  //Set Lower part of lw with old FilterOutput
  lw             := (lw shl ShiftCount) - lw;        //Equal to lw := lw * (2^ShiftCount - 1)
  lw             := lw + LongWord(NewVal + word(FiltData.Err)); //Add NewVal and Old Error
  FiltData.Err   := LowByte AND BitMask;             //Save Modulo of 2^n division
  lw             := lw shr ShiftCount;               //Perform 2^n division
  FiltData.Value := LowWord;                         //Store ResultValue of Filter
end;


{--------------------------------------------------------------}
{ Main Program }
{$IDATA}

var
  FiltData: TFiltData;
  FilterFreq: TFilterFreq;
  Pass, NewValue: word;
  i: byte;
begin
  FiltData.Value := 0;
  NewValue := 1000;
  Pass := 0;
  LCDclr;                                  { clear display }
  LCDcursor(false, false);                 { display on, cursor off & no blink }
  LCDhome;                                 { cursor home }
  EnableInts;
  loop
    Inc(Pass);
    LCDxy(0, 0);
    Write(LCDout, 'Pass=' + IntToStr(Pass) + ', ');
    Write(LCDout, 'NewValue=' + IntToStr(NewValue) + '      ');
    LCDxy(0, 1);
    LowPassFW(FiltData, NewValue, ffDiv2);
    Write(LCDout, IntToStr(FiltData.Value) + ', ');
  endloop;
end LowPassFilterTest.
Attachments
Trend
Filename: LowPassFW Trend.png
Filesize: 6.88 KB
Title: Trend
Information: LowPassFW Trend
Download counter: 155
Data
Filename: LowPassFW Data.png
Filesize: 9.41 KB
Title: Data
Information: LowPassFW Data
Download counter: 129
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: LowPassFW

 · 
Posted: 13.10.2013 - 17:05  ·  #6
Hello Avra,
thank you very much. :angel13:
Is it possible to have an opposite function in a similar way to get a HighPass filter?

rolf
Avra
Schreiberling
Avatar
Gender:
Location: Belgrade, Serbia
Age: 53
Homepage: rs.linkedin.com/in…
Posts: 653
Registered: 07 / 2002
Subject:

Re: LowPassFW

 · 
Posted: 10.11.2013 - 14:37  ·  #7
Merlin
Administrator
Avatar
Gender:
Age: 24
Posts: 1408
Registered: 03 / 2005
Subject:

Re: LowPassFW

 · 
Posted: 11.11.2013 - 13:30  ·  #8
Mmmm.

Quote
No, it must be done "the regular way", with an array of data recordings.


I don't doubt you for a minute Avra, but this feels counter-intuitive. If you have a low pass filter f(S(t)) on a signal S(t) it removes high frequencies as you explained. Does not S(t) - f(S(t)) leave you with what was removed, i.e. the high frequencies, and is this not a high pass filter? I acknowledge that it is crude, but then so is the function S(t).

Just a thought...
  • 1
  • 2
  • Page 1 of 2
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 16 · Cache Hits: 15   132   147 · Page-Gen-Time: 0.036335s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI