Medelvärde av kontinuerlig samplad signal

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
arte
Inlägg: 317
Blev medlem: 13 januari 2006, 01:18:50

Medelvärde av kontinuerlig samplad signal

Inlägg av arte »

Hej,

Jag försöker lista ut hur man bäst räknar ut medelvärdet av en kontinuerligt samplad signal.
Det finns några begränsningar:
- Kan max spara 3-4 värden
- Shift är gratis men division går ej
- Addera är ok

Idealt så hade detta fungerat:

Kod: Markera allt

void newSample(int newValue)
{
totalValues++;
totalSum += newValue;
mean = totalValues / totalSum; 
}
Tyvärr så går inte ovanstående på grund av divisionen (overflow gör det också besvärligt).

Jag har tänkt mig något i still med:

Kod: Markera allt

void newSample(int newValue)
{
oldMean = newMean;
newMean = (newValue + oldMean*7) >> 3; 
}
Min matte är lite begränsad, vad är det igentligen som jag räknar ut här.
Påminner om ett lågpass filter :)

Någon som har någon kommentar om hur man brukar göra?


Tack
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av blueint »

Flytande fönster teknik kanske lämpar sig?

Kod: Markera allt

int meanSample(int newValue) {
static int samples[4];
static int sample_pos;
int mean;

sample_pos++;
sample_pos &= 0x3;

samples[ sample_pos ] = newValue;

mean = (samples[0] + samples[1] + samples[2] + samples[3]) / 4;

return mean;
}
Lite osäker angående om static behåller sitt värde mellan anropen. Sedan måste funktionen initialiseras. Det kan göras genom att t.ex anropa den 4 ggr med värdet 0.
Användarvisningsbild
Walle
Moderator
Inlägg: 7701
Blev medlem: 14 december 2004, 10:32:18
Ort: Stockholm

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av Walle »

blueint, du har en division på fjärde raden...
Användarvisningsbild
adent
Inlägg: 4245
Blev medlem: 27 november 2008, 22:56:23
Ort: Utanför Jönköping
Kontakt:

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av adent »

Static håller sitt värde mellan anropen ja.

Vad gäller den andra sättet, det motsvarar typ (V är mätvärdet):

Kod: Markera allt

S(n+1) = (S(n)*7 + V) / 8

==

S(n+1) =  S(n) * (7/8)   +   V * (1/8)
Ett slags löpande medelvärde. Nackdelen är att små förändringar på V inte slår igenom, för att vara mer exakt i fallet ovan så är V under 8 kommer den att viktas in som 0. Har experimenterat en del med detta just nu för att "lugna ner" mina AD-mätningar, men kom fram till att man med den metoden får ett fel som blir kvar. Har inte tänkt färdigt dock, kanske går det att jobba bort.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av blueint »

Samma kod utan division på ordinarie sätt:

Kod: Markera allt

int meanSample(int newValue) {
static int samples[4];
static int sample_pos;
int mean;

sample_pos++;
sample_pos &= 0x3;

samples[ sample_pos ] = newValue;

mean = (samples[0] + samples[1] + samples[2] + samples[3]) >> 2; // Förutsatt att det är unsigned

return mean;
}
Användarvisningsbild
Micke_s
EF Sponsor
Inlägg: 6741
Blev medlem: 15 december 2005, 21:31:34
Ort: Malmö

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av Micke_s »

Du kan köra iir filter annars.

Medelvärde med 8, tricket är att köra
Filtret med än längd 2^n

Value =( value•7 + new)>>3;
Findecanor
Inlägg: 1045
Blev medlem: 2 juli 2010, 23:04:07

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av Findecanor »

Obs att historiken får inte innehålla skräp för då blir beräkningen helt fel. Innan buffern är full så får du antingen vänta med att lämna ett svar, beräkna ett medelvärde på de få värden du har eller lämna en approximation. I det sistnämnda fallet tror jag det kan vara enklast att fylla upp buffern från sample_pos till slutet.
Ett sätt att dividera på vore annars att använda en lookup-table med inverserna av talen 1...MAX_SAMPLES i fixed-point och multiplicera med dem, men då vill man helst ha en microcontroller med en bra multiplikationsinstruktion där resultatet kan ha dubbelt så många bittar som varje int man stoppar in.
Förresten, shift funkar också för signed. Det blir olika processor-instruktioner för signed och unsigned.

Jag kan tänka mig också en variant som egentligen är ett slags lågpassfilter:

Kod: Markera allt

#define SHIFT       4
#define DIVISOR   (1 << SHIFT)

void newSample(int newValue) {
  static int sum = 0;
  static int num_values = 1;
  int mean;

  sum += newValue; // num_values är inte korrekt förrän efter denna sats
  if (num_values < DIVISOR) {
    // Hantera oifylld "buffer" genom att fylla upp resten med det senaste värdet.
    mean = (sum + newValue * (DIVISOR - num_values)) >> SHIFT; 
    ++num_values;
  } else {
    mean = sum >> SHIFT;
    sum -= mean; // Istället för att dra bort det äldsta värdet, dra bort medelvärdet
  }
  return mean;
}
Användarvisningsbild
stekern
Inlägg: 453
Blev medlem: 2 november 2008, 08:24:18
Ort: Esbo, Finland

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av stekern »

blueint skrev:mean = (samples[0] + samples[1] + samples[2] + samples[3]) / 4;
Walle skrev:blueint, du har en division på fjärde raden...
blueint skrev:mean = (samples[0] + samples[1] + samples[2] + samples[3]) >> 2; // Förutsatt att det är unsigned
Det är bara dumt att ändra den där divisionen till en shift om det egentligen är en division som avses.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av blueint »

Om man saknar hårdvarudivision och skall utföra en division med 2^n är det en rätt bra idé.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av sodjan »

Vilken kompilator som helst med fler en 2 hjärnceller
kommer att lösa den där divisionen med fyra med shifts...
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av blueint »

Fast nu stod det i kravspecifikationen att "Shift är gratis men division går ej".
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av sodjan »

Som sagt,
Vilken kompilator som helst med fler en 2 hjärnceller
kommer att lösa den där divisionen med fyra med shifts...

Att ge en lösning som multiplicerar eller dividerar med
hela multiplar av 2 bör knappast behöva kommenteras
alls och det är i linje med "kravspecen".

Blueint, det är inte *din* kod som det är problem med
utan Walle's kommentar till den. :-)
Användarvisningsbild
stekern
Inlägg: 453
Blev medlem: 2 november 2008, 08:24:18
Ort: Esbo, Finland

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av stekern »

Precis som Sodjan säger, det finns inte en kompilator värd att användas som inte kan lista ut den där optimiseringen på egen hand.
Handoptimeringar av den typen gör bara koden mer svårläst.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av blueint »

Eller så lägger någon till ett värde och använder 5 som nämnare vilket då blir pannkaka. Handoptimeringar kan användas för att hålla folk borta eller iaf få deras ändringar att fallera så totalt att de lär sig snabbt.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Medelvärde av kontinuerlig samplad signal

Inlägg av sodjan »

Tja, det är ju väldigt enkelt för denna hypotetiska "någon"
att ställa till precis vad som helst med koden. :-)
Skriv svar