Hallo Leute,
schön langsam bekomme ich einen Knopf im Gehirn :-/ hab bis jetzt ALLE
Beiträge zu "Mittelwert-Berechnung" durch - komme aber trotzdem nicht
auf mein geplantes Ergebnis. vlt kann mir hier ja wer weiterhelfen.
Rand-Infos:
PIC18F2550; einlesen von Sensor-Daten mittels ADC und Umrechnung dann in
Pascal-Werte; diese Sensor-Daten werden kontinuierlich eingelesen - über
10 Messungen soll dann ein Mittelwert berechnet werden u falls dieser
dann in (voreingestellten) Grenzen "ausfährt" soll ein Alarm ausgegeben
werden.
Ausgabe erfolgt auf einem LCD-Display (über RS232)
Ausschnitte von meinem Code:
printf(" %lu Pa ",act_pressure_values[1]);//0x94 CR line 1 delay_ms(100);
was ich nun zur Mittelwertberechnung gefunden habe, ist folgendes:
1
SummeMessungen+=Ergebnis;
2
AnzahlMessungen++;
3
4
if(AnzahlMessungen==10){
5
Ergebnis=SummeMessungen/AnzahlMessungen;
6
7
if(Ergebnis>=limits)
8
printf("\f***ALARM***);
9
10
SummeMessungen = 0;
11
AnzahlMessungen = 0;
wo ich nun schon seit Tagen hänge - u auch durch probieren auf keinen
gemeinsamen Nenner komme, ist die "Variablen-Zuweisung". :-/
vlt kann mir da kurz jemand weiterhelfen, damit ich ENDLICH meine
Diplomarbeit abschließen kann.
DANKE schon mal im vorhinein (u sorry, dass schon wieder eine Frage
bezüglich "Mittelwert" aufgetaucht ist)
Ich weiss nicht, wieviel Rechenleistung du zur Verfügung hast, aber
meist ist es sinnvoll, den Mittelwert zu machen, bevor du die Umrechnung
in deine Ergebnisse machst, also bildest du den Mittelwert aus den rohen
ADC Werten.
Du machst dir z.B. einen Fifo mit 10 Plätzen auf, in dem du den ältesten
Wert rauswirfst und den neusten einfügst. Alle Werte im Fifo addieren
und durch 10 teilen, dann auf die Umrechnung schicken. 'sensor_data'
wird so zu einem Array von 10, plus einem Pointer auf den neusten Wert.
Alleridngs wundert mich schon, wie du es so bis zur Diplomarbeit
geschafft hast.
Ich wuerd diese Fifo Mittelwert Geschichte durch den exponentiellen
Mittelwert ersetzen, der benotigt viel weniger Resourcen, (eine
Speicherstelle & Schieben-Summieren) und man hat immer einen aktuell
gemittelten Wert am Ausgang. Der grad gemessene Wert verliert
exponentiell an Bedeutung.
Siehe http://www.ibrtses.com/embedded/exponential.html
Und. Ja. Den ADC Wert mitteln, die Skalierungen kommen allenfalls fuer
das Userinterface, waehrend man sinnvollerweise mit dem ADC Wert
weiterrechnet. Im fuer den Prozess sinnvollen Takt.
Floating point wuerde ich vermeiden. Ich rechne jeweils mit Integer 32
bit.
kathleen schrieb:> Diplomarbeit> pa_value = ((float)sensor_data-429)*62/389;
Aber holla, dafür würde ich Punkte abziehen (und das delay_us sehr
kritisch hinterfragen!!!). Denn auf einem uC rechnet man so lang wie
möglich in Integer. Und bestenfalls zur Ausgabe kommt dann ein Float ins
Spiel...
kathleen schrieb:> Ausschnitte von meinem Code
Ein paar Zeilen über dem Eingabefenster steht da was:
1
Wichtige Regeln - erst lesen, dann posten!
2
3
Formatierung
4
[c]C-Code[/c]
kathleen schrieb:> über 10 Messungen soll dann ein Mittelwert berechnet werden
Also musst du die letzten zehn Messungen speichern. Das machst du in
einem Ringpuffer, in dem immer der älteste Wert überschrieben wird. Und
danach wird die Summe dieses Puffers gebildet und durch 10 geteilt:
Matthias Sch. schrieb:> Alleridngs wundert mich schon, wie du es so bis zur Diplomarbeit> geschafft hast.
---> ? was soll diese Bemerkung? ich glaube, OHNE Hintergrundwissen zu
meiner Person kannst du dir dies sparen!
(ich komme aus einem GANZ anderen Metier - habe Koch gelernt - u bin nun
innerhalb von 2 Jahren auf einen technischen Beruf umgesattelt - u
innerhalb von 2 Jahren dann noch den gesamten Bereich von
Mikrokontroller, Elektrotechnik usw. NACHzulernen u nebenbei beruflich
in Schichtarbeit tätig zu sein ist SICHER nicht einfach! da kann man vor
mir schon den hut ziehen, dass ich es überhaupt so weit geschafft habe!)
Lothar Miller schrieb:>> Diplomarbeit>> pa_value = ((float)sensor_data-429)*62/389;> Aber holla, dafür würde ich Punkte abziehen (und das delay_us sehr> kritisch hinterfragen!!!). Denn auf einem uC rechnet man so lang wie> möglich in Integer. Und bestenfalls zur Ausgabe kommt dann ein Float ins> Spiel...
---> dasselbige gilt für dich!
ich dachte hier wird einem NETT geholfen, aber nicht kritisch
hinterfragt, warum wieso weshalb es diese Person soweit geschafft hat!?
ansonst - DANKE für eure Antworten - werde mich weiter damit
beschäftigen.
kathleen schrieb:> DANKE für eure Antworten - werde mich weiter damit beschäftigen.
Keine Ursache.
> ich dachte hier wird einem NETT geholfen, aber nicht kritisch> hinterfragt
Jede Angabe muss kritisch hinterfragt werden. Oft kommt einer und sagt:
ich WILL es genau so oder so machen. Mit einer kleinen Rückfrage stellt
sich raus, dass derjenige es eben nicht besser weiß und es deshalb
genauso eigenartig und umständlich machen WILL. Und es könnte sein, dass
deine Forderung "über 10 Messungen soll dann ein Mittelwert berechnet
werden" eben diesen Hintergrund hat.
> da kann man vor mir schon den hut ziehen, dass ich es überhaupt so weit> geschafft habe!
Im Ernst: das interessiert eigentlich Keinen (oder nur dann, wenn du es
gewinnbringend verkaufen kannst: "Durchaltevermögen, Zielstrebigkeit,
Belastbarkeit, blabla").
Das mit dem Punkteabzug habe ich wirklich so gemeint. Es ist bei der
Diplomarbeit nämlich schnurzpiepegal, was man vorher gemacht hat. DU
wollstest doch E-Techniker werden. Dann musst DU dich mit der
E-Technik-Latte messen lassen. Und die liegt nun mal ein wenig höher...
Und noch ein Wort zur Praxis, die du nach deiner Diplomarbeit in gut
einem viertel Jahr auch betreten willst:
Ich verwende kein delay und keine floats in einem uC-Programm
(höchstens es geht nicht anders!). Und als Filter verwende ich möglichst
speichersparende Strukturen. Etwa so wie das angeführte PT1-Glied. Vor
Allem achte ich aber darauf, dass ich das Programm so schreibe, dass der
uC in seiner dualen Welt arbeiten kann...
> werde mich weiter damit beschäftigen.
Tu das.
>> da kann man vor mir schon den hut ziehen, dass ich es überhaupt so weit> geschafft habe!
Ja. Machen wir. Wir ziehen den Hut. Meine Gratulation. Ich hab vorher
uebrigens auch was anderes gemacht.
Nun geht's aber weiter.
Servus,
ich kann dir auch den Ringspeicher empfehlen (siehe Kommentar von Lothar
Miller), du musst aber auf ein paar Dinge achten.
1. sinnvolle Initialisierung des Ringspeichers (alle Werte auf Null?)
2. Ringspeichergröße -> µC immer 8, 16, 32, 64,... was halt sinnvoll ist
3. während des schreibens auf den Ringspeicher mögliche Interrupts
sperren
der folgende Schritt ist kein muss
4. lieber einen kleinen feinen Funktionsautomaten (FSM) verwenden, der
dann timer getriggert die aufgaben erledigt :)
Beispiel:
1
staticintringcounter=0;
2
// state musst dir selber basteln am besten mit typedef enum im entsprechenden *.h-File
3
4
5
switch(state)
6
{
7
first_state:
8
ring[ringcounter]=adc_read_value();
9
state=second_state;
10
timer_start_us(50);
11
break;
12
13
second_state:
14
...
15
16
third_state:
17
...
18
19
last_state:
20
...
21
if(ringcounter>=16)
22
{
23
ringcounter=0;
24
}
25
}
wobei die Schritte "neuen Status zuweisen" und "timer starten" bei jedem
Schritt ausgeführt werden müssen, aja das ganze natürlich in eine
Funktion packen.
Am besten du malst es dir mal auf!
beste grüße
public
kathleen schrieb:> da kann man vor> mir schon den hut ziehen, dass ich es überhaupt so weit geschafft habe!)
Hut schreibt man u.a. groß, da es sich um ein Substantiv handelt. Ebenso
Wörter am Satzanfang...
SCNR :)
Zum Thema: Verwende einen Tiefpass. Hat sich in der Praxis bewährt.
Die Methoden
a) gleitender Mittelwert (= FIR-Filter),
b) exponentieller Mittelwert (= IIR-Filter) und
c) Durchschnitt von n Werten (= ich weiß nicht was)
sind doch unterschiedliche Tiefpassfilter mit recht unterschiedlichem
Verhalten (Frequenzgang, Phasengang bzw. Impuls/Sprungantwort) die je
nach Anforderung an die Filtereigenschaften der Applikation zu wählen
sind. Bei den Überlegungen haben m.M.n. Aspekte der "leichten" oder
"eleganten" Implementierbarkeit nix mitzureden.
Wie dann der ausgewählte Filter (am günstigsten) implementiert wird ist
nachrangig.
public schrieb:> der folgende Schritt ist kein muss> 4. lieber einen kleinen feinen Funktionsautomaten (FSM) verwenden
So ein Zustandsautomat könnte aber eine ganz hübsche Herausforderung
sein, insbesondere, wenn man diesen Programmierstil nicht kennt...
Ich würde auf jeden Fall nach jedem Einlesen des ADC den Wert neu
berechnen, weil sonst ja unnötige Latenz bis zum Ergebnis auftriit. Also
keinesfalls "10 Werte einlesen, dann den Mittelwert berechnen, dann
wieder 10 Werte einlesen, dann den Mittelwert berechnen, usf..."
> 3. während des schreibens auf den Ringspeicher .. Interrupts sperren
Warum?
Die Interrupts müssen nur gesperrt werden, wenn in einem Interrupt
ebenfalls auf den Ringspeicher zugegriffen wird. Dann gibt es nämlich
das allseits bekannte Semaphorenproblem...
Ralf D. schrieb:> Bei den Überlegungen haben m.M.n. Aspekte der "leichten" oder> "eleganten" Implementierbarkeit nix mitzureden.
Doch, durchaus. Solange nämlich nicht bekannt ist, warum denn UNBEDINGT
GENAU der gleitende Mittelwert genommen werden MUSS, solange frage ich
da auf jeden Fall nach. Denn eines ist klar: ein Grundschüler wird zur
Multiplikation eine forgesetzte Addition nehmen, weil er es nicht besser
KANN. Wenn man ihm dann aber zeigt, dass man 6*7 auch einfacher rechnen
kann als 6+6+6+6+6+6+6, dann kann er dieses "neue" Verfahren anwenden.
Und in der elektrotechnischen "Grundschule" lernt man nun mal
zuallererst den gleitenden Mittelwert.
Ralf D. schrieb:> Die Methoden> a) gleitender Mittelwert (= FIR-Filter),> b) exponentieller Mittelwert (= IIR-Filter) und> c) Durchschnitt von n Werten (= ich weiß nicht was)
d) die Werte sortieren und den "mittleren" Wert verwenden (Medianfilter)
Das ist ein tolles Verfahren bei verrauschten Signalen. siehe dort etwa
in der Mitte:
http://de.wikipedia.org/wiki/Rangordnungsfilter
@Kathleen: du hättest doch einfach sagen können, dass du das Diplom in
Österreich an einer HTL machst, dann wären die Kommentare evtl. ein
wenig weniger bissig ausgefallen. So mussten wir annehmen, du hättest an
einer (deutschen) Hochschule schon 4 Jahre Studium hinter dir...
Ralf D. schrieb:
> Bei den Überlegungen haben m.M.n. Aspekte der "leichten" oder> "eleganten" Implementierbarkeit nix mitzureden.
Nix da. Auf alle Faelle, darum geht es genau. Nun lassen wir mal die
Faelle aussen vor wo Leute den Zwang verspueren einen Raspi einseten
muessen, wo auch ein Mega 8 reicht.
Als Physiker lernt man mit Ungenauigkeiten zu leben. Eigentlich sind sie
das Leben. Also, wenn die Anwendung, resp die Idee davon, per Mathe eine
Division durch 1000 moechte, schau ich erst ob zB 2% Fehler drinliegt.
Dann teile ich durch 1024. In sehr vielen Anwendungen ist das naemlich
egal.
Das erscheint in den Spezifikationen unter "Absolute Genauigkeit 2%",
mit trotzdem "Stabilitaet 0.01%". Die Meisten Anwendungen verlangen hohe
Reproduzierbarkeit, und nicht absolute Werte.
Float fuer eine Benutzerausgabe alle 300ms, aber nicht haeufiger, ist
tragbar, sonst aber nicht. Sonst wird konsequent mit Integern
gearbeitet.
Falls nun eine Skalierung doch etwas praeziser sein soll...
zB ein Faktor 1.05 oder in der Naehe sein muss, an liebsten
Benutzer-Einstellbar, verwende ich zb * 68812 / 65536, wobei die erste
Zahl als Variable auftaucht. Die zweite Zahl bedeutet die hinteren zwei
byte entfernen. Das ist nicht etwa Mehrarbeit, sondern geht gratis mit.
Jetzt Nicht schrieb:> zB ein Faktor 1.05 oder in der Naehe sein muss, an liebsten> Benutzer-Einstellbar, verwende ich zb * 68812 / 65536, wobei die erste> Zahl als Variable auftaucht.
Genau dieses simple Verfahren ist den meisten schleierhaft.
Wie kann ich einen Integer ohne Division durch 3 teilen?
Klar: mit *0.33333
Und wie geht das jetzt ohne Float?
Ganz einfach: mit *21845/65536
Ja, ruft gleich einer: da ist doch eine Division drin!
Aber das Lustige ist jetzt: es ist eine Division durch die Zweierpotenz
2^16 und das bedeutet, dass der Compiler diese beiden unteren Bytes
einfach "vergessen darf". Fertig ist die Division...
(bei signed-Divisionen muss man beim Abschneiden ein wenig aufpassen
oder mit dem +-1 Fehler leben, aber das ist ein fortgeschrittenes
Thema...)
Hey es geht doch um eine Diplomarbeit, und die liegt auch noch kurz vor
Fertigstellung. Bei mir hat in entsprechender Phase die Verschönigung
eingesetzt, Code kürzer/kleiner/schneller/effizienter...
Ein Automat macht es sehr übersichtlich, aber natürlich nicht einfacher.
Interrupts natürlich nur sperren wenn denn dann noch etwas anderes mit
dem entsprechenden Buffer passiert, davon bin ich mal ausgegangen
(wollte hier nur einen Hinweis) ;)
Ich würde den Mittelwert nicht die ganze Zeit berechnen, sondern nur
wenn der Wert interessant wird. Wenn das natürlich die gesamte Zeit ist
ein sofortiges Update evtl. wichtig.
beste grüße
public
Lehrer Specht schrieb:> Hut schreibt man u.a. groß, da es sich um ein Substantiv handelt. Ebenso> Wörter am Satzanfang...
Bitte entschuldige, dass mir hier die Shift-Taste nicht genommen wurde.
Lothar Miller schrieb:> @Kathleen: du hättest doch einfach sagen können, dass du das Diplom in> Österreich an einer HTL machst, dann wären die Kommentare evtl. ein> wenig weniger bissig ausgefallen. So mussten wir annehmen, du hättest an> einer (deutschen) Hochschule schon 4 Jahre Studium hinter dir...
-> JA, es betrifft hier die Abendschule an einer Höheren technischen
Lehranstalt in Österreich.
Falls ich wirklich schon 4 Jahre Studium hinter mir hätte, dann hätte
ich bestimmt keine Fragen (zumind. nicht solch "primitive" Fragen, wie
diese hier) in ein Forum gestellt.
aber nun möchte ich hiermit diesen Beitrag schließen (oder von einem
Admin schließen lassen) - da es nun immer weiter in die Materie
hineingeht.
Vielen Dank nochmal an alle.
kathleen schrieb:> aber nun möchte ich hiermit diesen Beitrag schließen (oder von einem> Admin schließen lassen) - da es nun immer weiter in die Materie> hineingeht.
Heyho Frustrationsgrenze runterschrauben und helfen lassen, auch wenn es
nicht immer "freundlich" zugeht.
> Vielen Dank nochmal an alle.
Bitte, gerne wieder ;)
kathleen schrieb:> aber nun möchte ich hiermit diesen Beitrag schließen
Beiträge werden hier idR. nicht geschlossen. Du kannst deinen Beitrag im
Juni nochmal rauskramen und schreiben, wie die Lösung zum Schluss
ausgesehen hat. Das rundet so eine Sache dann immmer hübsch ab, aber
leider tun das nur wenige...