
Lågpassfilter i mjukvara!
Re: Lågpassfilter i mjukvara!
jag hoppades att snigelen skull tända på idén och presentera färdiga kurvor här så jag slipper 

Re: Lågpassfilter i mjukvara!
Nja z-plan och så var väl kanske inte nödvändigt att dra in, jag bara tänkte att det skulle bli ett lite bättre filter med min modifikation, men fortfarande enkelt. Annars är det med hjälp av Z-transformen man hamnar i z-planet, det är väl ungefär den tids-diskreta mosvarigheten till Laplace-transformen.
Lägger du till flera gamla insignaler så blir det väl fortfarande LP-filter, men det går mer och mer mot ett kam-filter (tror jag) som blockar flera jämnt utspridda frekvenser. Men då finns det väl bättre sätt att göra högre ordningens LP-filter. Men inte lika enkelt som detta...
Lägger du till flera gamla insignaler så blir det väl fortfarande LP-filter, men det går mer och mer mot ett kam-filter (tror jag) som blockar flera jämnt utspridda frekvenser. Men då finns det väl bättre sätt att göra högre ordningens LP-filter. Men inte lika enkelt som detta...
Re: Lågpassfilter i mjukvara!
Nu har jag lekt lite med detta rent praktisk och jag är mycket nöjd!
Det mynnade ut i denna fil:
/*----------------------*/
/* File: Low_Pass_100.h */
/* Date: 20110711 */
/* ---------------------*/
/* How to use this software low pass filter: */
/* - Incoming is the value to be filtered. */
/* - Intermediate is a static value, one location for each different value to filter */
/* - Return value is the normalized filtered value. */
/* - Shifts is the number of shifts to do, high number means slower rise */
/* - With a suitable randomness in the input signal extra bits can be extracted from the Intermediate-value */
int Low_Pass(int * Incoming, long * Intermediate, int Shifts)
{
*Intermediate = (*Intermediate - (*Intermediate >> Shifts)) + *Incoming;
return(*Intermediate >> Shifts);
}
Jag har testat att använda denna rutin till lite olika saker i ett projekt och jag fick lite bättre värden än med det förra sätt men det gick åt en del mindre programplats. Jag är mycket glad för att detta blev lagt in, tack Jesse.
Det mynnade ut i denna fil:
/*----------------------*/
/* File: Low_Pass_100.h */
/* Date: 20110711 */
/* ---------------------*/
/* How to use this software low pass filter: */
/* - Incoming is the value to be filtered. */
/* - Intermediate is a static value, one location for each different value to filter */
/* - Return value is the normalized filtered value. */
/* - Shifts is the number of shifts to do, high number means slower rise */
/* - With a suitable randomness in the input signal extra bits can be extracted from the Intermediate-value */
int Low_Pass(int * Incoming, long * Intermediate, int Shifts)
{
*Intermediate = (*Intermediate - (*Intermediate >> Shifts)) + *Incoming;
return(*Intermediate >> Shifts);
}
Jag har testat att använda denna rutin till lite olika saker i ett projekt och jag fick lite bättre värden än med det förra sätt men det gick åt en del mindre programplats. Jag är mycket glad för att detta blev lagt in, tack Jesse.
Re: Lågpassfilter i mjukvara!
Kul att nån har glädje av det!
>jag fick lite bättre värden än med det förra
hmm... är de inte identiska i funktionen, men att du använder pekare istället för vanliga variabler?
Originalkod:
Varför måste du skicka med intermediate som argument i varje anrop? kan du inte ha den som en statisk variabel inuti funktionen? Och Shifts kan ju (oftast) vara en kostant lagrad i en macro:

>jag fick lite bättre värden än med det förra
hmm... är de inte identiska i funktionen, men att du använder pekare istället för vanliga variabler?
Originalkod:
Kod: Markera allt
filter_reg = filter_reg - ( filter_reg >> FILTER_SHIFT) + filter_input ;
output = filter_reg >> FILTER_SHIFT
Kod: Markera allt
#define SHIFTS 8
int Low_Pass(int * Incoming)
{
static long Intermediate = START_VALUE;
Intermediate = (Intermediate - (Intermediate >> SHIFTS)) + *Incoming;
return(Intermediate >> SHIFTS);
}
Re: Lågpassfilter i mjukvara!
"Med det förra" var bristfälligt skrivit, det skulle nog stå "med det sätt jag gjorde förut" för att det skulle vara korrekt.
Och jag kan INTE ha Intermediate som en static i funktionen, jag använder samma filter på 8 kanaler fast med lite olika shift-steg, därav pekarna.
Jag använder samma rutin till att filtrera 7 kanaler direkt från AD-omvandlaren med relativt låga värden på shift, sedan använder jag den till att "rensa" lambda-värdet och då är det med ett ganska högt shift-värde vilket ger trögheten jag vill ha.
Och jag kan INTE ha Intermediate som en static i funktionen, jag använder samma filter på 8 kanaler fast med lite olika shift-steg, därav pekarna.
Jag använder samma rutin till att filtrera 7 kanaler direkt från AD-omvandlaren med relativt låga värden på shift, sedan använder jag den till att "rensa" lambda-värdet och då är det med ett ganska högt shift-värde vilket ger trögheten jag vill ha.
Re: Lågpassfilter i mjukvara!
>Och jag kan INTE ha Intermediate som en static i funktionen, jag använder samma filter på 8 kanaler fast med lite olika shift-steg, därav pekarna.
Ah, visst ja.
Själv kör jag samma filter på 96 ADC-kanaler parallellt, och då pekar pekarna direkt till en array. jag skickar bara ADC-kanalens nummer som argument, så hittar den själv indata, utdata och "intermediate"-data.
Ah, visst ja.

Själv kör jag samma filter på 96 ADC-kanaler parallellt, och då pekar pekarna direkt till en array. jag skickar bara ADC-kanalens nummer som argument, så hittar den själv indata, utdata och "intermediate"-data.
Re: Lågpassfilter i mjukvara!
Jag testade att ha funktionen direkt i AD-ISN'n innan jag lade ut den i egen fil och jag testade att kompilera båda versioner.
Det visade sig att versionen med pekare var programmet kännbart mindre, sannolikt för att den inte ska räkna index vid båda läsa o skriva - fler gångar. Med färre programsteg bör programmet gå lite snabbare också och det gillar jag!
Det visade sig att versionen med pekare var programmet kännbart mindre, sannolikt för att den inte ska räkna index vid båda läsa o skriva - fler gångar. Med färre programsteg bör programmet gå lite snabbare också och det gillar jag!
Re: Lågpassfilter i mjukvara!
Med bakgrund av mitt inlägg i Lågpassfilter i C-kod, tänkte jag att jag kan uppdatera den här tråden också.
Jag har kommit på att man kan göra filtret lite snabbare enbart genom att stuva om, samt deklarera en extra static:
Nu behövs bara en skiftoperation, istället för två.
(Har inte kompilerat koden)
Vet inte om det stod tidigare i tråden, men jag har iaf förstått hur såna här filter beter sig jämfört med ett vanligt RC-filter. Filtrets svar påverkas av hur ofta filterfunktionen körs, vilket kanske inte är helt självklart från början. Om man önskar att filtret ska motsvara ett RC-filter, samt vet hur ofta filterfunktionen körs, kan man räkna ut hur många skiftningar som behövs, med hjälp av log2. (Om din miniräknare saknar log2 kan du istället använda log10 eller naturliga logaritmen (ln), såhär:
//FILTER_SHIFTS = ln(RC_constant * calls_per_second) / ln(2)
Jag har kommit på att man kan göra filtret lite snabbare enbart genom att stuva om, samt deklarera en extra static:
Kod: Markera allt
//FILTER_SHIFTS = log2(RC_constant * calls_per_second)
#define FILTER_SHIFTS 10
uint16_t low_pass_filter(uint16_t input)
{
static uint16_t output;
static uint32_t intermediate;
intermediate -= output;
intermediate += input;
output = intermediate >> FILTER_SHIFTS;
return output;
}
(Har inte kompilerat koden)
Vet inte om det stod tidigare i tråden, men jag har iaf förstått hur såna här filter beter sig jämfört med ett vanligt RC-filter. Filtrets svar påverkas av hur ofta filterfunktionen körs, vilket kanske inte är helt självklart från början. Om man önskar att filtret ska motsvara ett RC-filter, samt vet hur ofta filterfunktionen körs, kan man räkna ut hur många skiftningar som behövs, med hjälp av log2. (Om din miniräknare saknar log2 kan du istället använda log10 eller naturliga logaritmen (ln), såhär:
//FILTER_SHIFTS = ln(RC_constant * calls_per_second) / ln(2)
Re: Lågpassfilter i mjukvara!
Mycket bra
Formeln var trevlig att få. Hade säkert kunnat räkna ut den själv, men det har aldrig blivit av.
Den kommer jag att ha nytta av!

Formeln var trevlig att få. Hade säkert kunnat räkna ut den själv, men det har aldrig blivit av.
Den kommer jag att ha nytta av!
Re: Lågpassfilter i mjukvara!
Intressant kod. Dock bör man väl initiera static variablerna.
Hur blir det eftersom man trunkerar intermediate när man tilldelar output. Kan det bli konstiga effekter att intermediate driver?
Ska se om jag har tid att testa för det är ju definitivt en kompakt och effektiv lösning.
Hur blir det eftersom man trunkerar intermediate när man tilldelar output. Kan det bli konstiga effekter att intermediate driver?
Ska se om jag har tid att testa för det är ju definitivt en kompakt och effektiv lösning.
Re: Lågpassfilter i mjukvara!
Ja, det kan man göra. Var inte menat som komplett kod. Jag brukar ibland deklarera intermediate utanför funktionen, och initiera till min första input << FILTER_SHIFTS. output borde man också initiera - till input, men det har jag inte tänkt på tidigare.
EDIT: angående att intermediate driver förstår jag inte riktigt vad du menar?
Om man ändrar till return intermediate; i slutet, för att få en förstärkning, kommer intermediate fastna på slumpvärdet ifall input och output är 0.
EDIT: angående att intermediate driver förstår jag inte riktigt vad du menar?
Om man ändrar till return intermediate; i slutet, för att få en förstärkning, kommer intermediate fastna på slumpvärdet ifall input och output är 0.