Hur göra minnessnål medelvärdesalgoritm, helst snabb

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
bearing
Inlägg: 11677
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Hur göra minnessnål medelvärdesalgoritm, helst snabb

Inlägg av bearing »

Nuvarande koden ser ut såhär:

Kod: Markera allt

while (oldsec==sec)
{
	....

	//Beräkna medel
	antalvarden++;
	utrymme=~summa;
	if (!full||utrymme>=hastigheten)//Kolla att summa har plats för hastigheten
	{
		summa+=hastigheten;
		medelv=summa/antalvarden;
	}
	else	//Om inte, byt algoritm
	{
		full=1;
		diff=hastigheten-medelvh;								
		if (hastigheten>=medelvh)
		{
			diff/=antalvarden;
			medelv+=diff;
		}
		else
		{
			diff=-diff;
			diff/=antalvarden;
			medelv-=diff;
		}
	}
	
	....
}
Jag använder 16-bitars unsigned-variabler. Medel beräknas under 1 sekund, datan kommer i mellan 3 och 50 Hz. Vid höga hastigheter och/eller frekvenser kommer summa fyllas långt innan sekunden är slut, därför byts då algoritmen till en "grövre".

Är inte nöjd, det blev mycket kod. Finns det standardalgoritmer/andra- som beräknar medel på ett enklare/bättre sätt?
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Akitektur ? (PIC, AVR eller något annat ?)

Sen finns det massor av "shortcuts" för att undvika divisioner (eller
ersätta dom med shifts) o.s.v. T.ex genom att välja antalet värden
till en jämn potens av 2.

Men då måste man vet mycket mer om dataintervall m.m m.m.

Det finns dessutom flera olika definitioner på "medelvärde", eller
riktigare hur man beräknar det.
bearing
Inlägg: 11677
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Inlägg av bearing »

Det är en PIC 16F628.

Mäter periodtiden på ett hjul och beräknar varvtalet med formeln
v=konstant/T

Om perioden är lång kommer det få värden under sekunden, och varvtalet är lågt, så summa i min kod fylls inte.
Men vid högt varvtal fylls summa snabbt p.g.a stora varvtalsvärden med hög frekvens.

Min kod körs nu varje gång det "kommer" (från ett interrupt) en ny period.

Är det detta som kallas FIR-filter?

Detta är inte så viktigt, koden jag har duger, men ett bättre sätt kan vara bra att veta om senare eftersom medelvärdesberäkning antagligen är vanligt.
danei
EF Sponsor
Inlägg: 27495
Blev medlem: 2 juni 2003, 14:21:34
Ort: Östergötland
Kontakt:

Inlägg av danei »

Är det inte bättre att mäta tiden för ett antal varv. Hur många kan du ju variera beroende på hastighet.
bearing
Inlägg: 11677
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Inlägg av bearing »

Det är en bra ide'. Det är det jag egentligen skulle vilja göra, men begränsas av att demoversionen av kompilatorn bara klarar 16-bitars-variabler. Om jag gör divisionen v=konstant/T, och sedan v=v*antalvarv, med ett stort T får v få värdesiffror.
Jag skulle vilja göra: v=antalvarv*konstant/T. Då blir det många fler värdesiffror kvar efter divisonen, men kräver större variabler.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Eller genom att ändra mätmetod helt så att du slipper divisionen.

Säg att du vill mäta upp till 3.000 rpm, och att det kommer en puls/varv.

3000 pulser/min = 50 pulser/sek. (= din övre gräns, eller hur ?)

Om du räknar pulser under 7.5 sekunder så får du 375 pulser (vid 3000 rpm)

Multiplikation med 8 (3 st snabba shift) så får du 3000 !

Så istället för ett antal multiplikationer och divisioner, så blev det bara 2 enkla shift.
bearing
Inlägg: 11677
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Inlägg av bearing »

Ja, egentligen skulle jag kunna göra så eftersom det inte krävs så stor upplösning. Men jag jag finner någon sorts tillfredställelse av att göra så hög upplösning som möjligt. Det skulle duga bra med en upplösning på 0,5 m/s, men metoden jag använder nu ger 1 cm/s.
Skriv svar