Forum: PC-Programmierung Messwerteglätung


von Johannes T. (johannes_t600)


Angehängte Dateien:

Lesenswert?

Hallo Liebe Community,

für unser Maschinenbaustudium (Fernstudium) muss ich mich mit C++ 
rumschlagen und auch mir Sisy AVR. Leider ist das gar nicht meine Welt, 
sonst hätte ich was in die Richtung studiert.

Es gibt da eine Aufgabe bei der ich kein Millimeter weiter komme und 
hoffe das ihr mich dabei unterstützen könnt.

Wir müssen ein Code schreiben mit dem eingehen Messwerte (valuet) 
exponentiel geglättet werden. Nach der Formel:
 y´(t)=faktor*y(t)+(1-faktor)*y(t-1)

das ganze soll dann als smoothValuet wieder zurückgegeben werden.

Es gibt auch ein Beispiel wie so was mit Mittelwert funktioniert 
(Bild.3) nur leider werde ich da auch nicht viel schlauer. In unserem 
Studienheft wir mal hin und wieder was in C++ programmiert und ein paar 
werte vertaucht oder mal ne quadratische Gleichung berechnen aber das 
was den auch. Keine einzige Aufgabe über Messwerte und wie man sowas 
macht. Auf die Frage an den Tutor zu Hilfestellung bekommt man nur den 
verweis auf google.de oder Bibliothek.
Ich habe im Anhang 3 Bilder Aufgabestellung, Messwerte ungeglättet und 
Beispiellösung mit Mittelwert

Ich hoffe Ihr könnt mir etwas weiter Helfen.

Grüße
Johannes

von Peter M. (r2d3)


Lesenswert?

Vor 25 Jahren habe ich das erste und letzte Mal in C++ programmiert. Ich 
habe damals das Konzept überhaupt nicht verstanden, das ging mir erst 
später auf.

Wenn Dir jemand eine Reihe von Messwerten auf ein Blatt Papier schreibt 
und Dir einen Glättungsfaktor vorgibt, kannst Du dann die exponentiell 
geglätteten Messwerte darunter schreiben?
Ist das Verfahren klar?

Übrigens, man schreibt die Messwerteglättung mit zwei t.

: Bearbeitet durch User
von johannes_t600 (Gast)


Lesenswert?

Mathematisch kann ich es auf dem Papier ohne Probleme ausrechnen. Mir 
fehlt das nötige Verständnis um es in C zu schreiben. Mit den ganzen 
pointer variablen Funktionen und sonst was man da braucht.

von Dampf Stampf (Gast)


Lesenswert?


von Peter M. (r2d3)


Lesenswert?

Jetzt sprichst Du auf einmal von C und nicht mehr von C++.
Das sind aber zwei verschiedene Dinge.

Aus der Aufgabenstellung heraus muss man feststellen können, welchen Weg 
die Eingangsdaten, also die Messreihe nimmt.

Gibt es da irgendeine Funktion, bzw. Methode, mit der man Messwerte 
"ziehen" kann, ähnlich wie ein Zufallsgenerator, der einem bei jedem 
Aufruf einen neuen Wert liefert?

Oder liegen die ganzen Daten mundgerecht in einem Feld?

Dürfen die "Quelldaten" verändert werden oder muss die geglättete Reihe 
neben der Quellreihe vorliegen?

Wenn das nicht festgelegt ist, spricht nichts dagegen, die Aufgabe auf 
die für Dich einfachste Art und Weise zu lösen, vermutlich mit Hilfes 
ein oder zweier Felder, auch wenn das nicht der eleganteste Weg ist.

Im übrigen scheint die Mittelwertbildung im Code logisch nicht zu dem 
von Dir darunter kopierten Bild zu passen.

von johannes_t600 (Gast)


Lesenswert?

Die Eingangswerte vault werden von Sisy generiert und vorgegeben ca. 100 
pro minute.
Für mich macht es wenig unterschied c oder c++. War uns nur gesagt der 
einzige unterschied ist das man in c++ objektorientiert programmieren 
kann. Rest ist ziemlich gleich.
Das Bild ist nicht kopiert sondern das gibt sisy als Ergebnis raus für 
Mittelwert (Muster Lösung vom Dozent) wenn da was nicht passt kann ich 
nicht erklären.

von johannes_t600 (Gast)


Lesenswert?

Dampf Stampf schrieb:
> Etwas im Sinne von :
> http://www.ibrtses.com/embedded/exponential.html

Das scheint so was zu sein.

von Balou (Gast)


Lesenswert?

Das Ganze soll wohl nur jeweils 1x laufen, wie es aussieht. Vielleicht 
ungefähr so?

1
double MainWnd::smoothing(double value)
2
{
3
  const double factor = 0.2;
4
  static bool firstCall = true;
5
  static double smoothValue;
6
7
  if (firstCall)
8
  {
9
    smoothValue = value;
10
    firstCall = false;
11
  }
12
  else
13
  {
14
    smoothValue = factor * value + (1 - factor) * smoothValue;
15
  }
16
  
17
  return smoothValue;
18
}

von Johannes T. (johannes_t600)


Angehängte Dateien:

Lesenswert?

Balou schrieb:
> Das Ganze soll wohl nur jeweils 1x laufen, wie es aussieht. Vielleicht
> ungefähr so?



Bekomme eine Fehlermeldung.  Code habe ich 1:1 übernommen . Aber Ich 
glaub die Zeile double MainWnd::smoothing(double value) muss weg.

und das gibt so ein kleiner Rahmen wen man Sisy startet.
1
double smoothValue=.0; 
2
3
// vorerst ungeglättet
4
smoothValue=value;

da soll das Code rein. Ich Probiere es mal umzuschreiben.

von Johannes T. (johannes_t600)


Angehängte Dateien:

Lesenswert?

Hier das Ergebnis was ich mit Balou Code erhalten habe. Würde es sinn 
machen die
1
else 
2
{
3
4
smoothValue = factor*value+(1-factor)*smoothValue;
5
6
}

in eine schleife zu packen damit es mehrmals durchläuft?

von nicht"Gast" (Gast)


Lesenswert?

Johannes T. schrieb:
> in eine schleife zu packen damit es mehrmals durchläuft?

Nein,

um die Glättung zu erhöhen machst du den Faktor kleiner.

von Balou (Gast)


Lesenswert?

Johannes T. schrieb:
> Hier das Ergebnis was ich mit Balou Code erhalten habe. Würde es sinn
> machen die
> else
> {
> smoothValue = factor*value+(1-factor)*smoothValue;
> }
> in eine schleife zu packen damit es mehrmals durchläuft?

Nein (außerdem ist doch in der Aufgabenstellung vorgegeben, was du 
machen sollst; ich sehe da nur etwas von exponentieller Glättung erster 
Ordnung). Du könntest/solltest aber mal mit dem Faktor experimentieren.

von johannes_t600 (Gast)


Lesenswert?

Hab ich bei 0.1 wird besser aber auch kleiner irgent wie bei 0 totale 
glättung gibts eine gerade. Aber ansonsten sieht es doch gut aus oder?

von Balou (Gast)


Lesenswert?

johannes_t600 schrieb:
> Hab ich bei 0.1 wird besser aber auch kleiner irgent wie bei 0 totale
> glättung gibts eine gerade.

Das ist normal bei dieser Methode.

> Aber ansonsten sieht es doch gut aus oder?

Ja; nimm für diese Beispieldaten einfach einen Faktor (z.B. 0.16, 
ausprobieren), bei dem die Glättung akzeptabel ist, aber die Amplitude 
nicht zu klein wird. Das dürfte dann passen, denke ich.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Johannes T. schrieb:
> Leider ist das gar nicht meine Welt,
> sonst hätte ich was in die Richtung studiert.

Heutzutage werden in jeder technischen Disziplin zumindest rudimentäre 
Programmierkenntnisse erwartet, da man sie auch im beruflichen Alltag 
sehr häufig benötigt bzw. sie die Arbeit deutlich vereinfahren. 
Insbesondere bei einem Hochschulstudium darf man zwingend erwarten, dass 
der Student auch die fachfremden Fachgebiete aus eigener Leistung 
abdecken kann. Die jeweiligen Anforderungen an Nebenfächler sind schon 
deutlich reduziert gegenüber Hauptfächlern.

Gerade ein Maschinenbauingenieur muss auch in der Lage sein, für einen 
kleinen Versuchsaufbau z.B. eine SPS zu programmieren oder zumindest 
nachvollziehen zu können, worauf man in der Automatisierungstechnik 
achten muss. Grundlagen in C oder C++ lassen sich durchaus auch in 
SPS-Programmiersprachen wie ST/SCL übertragen.

Bei einem Maschinenbauprojekt hatten wir zusammen mit den Konstrukteuren 
(davon einer der Projektleiter) genau die Positionen von Lichtschranken 
festgelegt. Diese Lichtschranken dienten dazu, den Materialtransport zu 
erfassen und nachfolgende Antriebe usw. in Abhängigkeit vom 
eintreffenden Material zu steuern. Im fertigen Antriebssystem stellte 
sich heraus, dass der Konstrukteur die Positionen der Lichtschranken 
"nur" um wenige Zentimeter verschoben hatte. Vorher befanden sich sich 
unmittelbar vor den Antriebsrollen, aber er fand, dass sie sich 
wesentlich besser zwischen den Antriebsrollen anbringen ließen. Dadurch, 
dass derjenige so wirklich gar keinen Schimmer von Softwareentwicklung 
("Doch, damals im Studium mussten wir auch mal etwas programmieren.") 
hatte, war ihm die entsprechende Denkweise überhaupt nicht klar. Es 
kostete schon ziemliche Mühe, ihm klarzumachen, dass man im SPS-Programm 
nicht einfach schreiben kann: "Sensor 103 befindet sich 3,2cm hinter 
Antrieb 217.", sondern das Kausalitätsprinzip eingehalten werden muss.

Letztendlich wurden dann fast alle Antriebe einfach eingeschaltet, 
sobald durch ein externes Ereignis die Materialzufuhr angekündigt wurde. 
Die Sensoren dienten dann nur noch dazu, im Nachhinein festzustellen, ob 
wirklich Material vorbeigekommen war. Damit konnten wir wenigstens einen 
Materialstau feststellen. Naja, immerhin etwas, um die Unmengen an 
Sensoren, armdicken Kabelsträngen mit Sensorleitungen und teuere 
SPS-Erweiterungsmodule nicht völlig ungenutzt zu lassen.

Und die Bediener der Anlage freuen sich, bei den doch recht häufigen 
Materialstaus die ganze Anlage anhalten zu müssen, statt wie geplant 
eine reibungslosen Transportvorgang durch gezielt angesteuerte Antriebe 
erleben zu dürfen.

Das passiert, wenn Konstrukteure keine geeignete Denkweise entwickelt 
haben. Und um diese zu entwickeln, müssen viele Leute erst einmal selbst 
ein paar einfache Steuerungen selbst realisiert haben. Die eingesetzte 
Programmiersprache ist hierbei völlig nachrangig.

Ein absoluter Klassiker für eine ebenfalls unterentwickelte Denkweise 
ist auch der schon tausendfach als Programmierübung implementierte 
Getränkeautomat. In typischen Anfängerprogrammen wird z.B. nur zu festen 
Zeitpunkten auf den Geldeinwurf oder einen Tastendruck gewartet. Das ist 
natürlich Unsinn. Der Bediener kann zu beliebigen Zeitpunkten Geld 
einwerfen und auf der Tasten herumdrücken. Der Einbruchmeldesensor kann 
ebenfalls jederzeit betätigt werden. Uns all das muss man eben in 
geschickt formulierten Zustandsautomaten unterbringen. Blockierende 
Zugriffe auf Ressourcen (z.B. scanf()) haben das nichts zu suchen.

von johannes_t600 (Gast)


Lesenswert?

Andreas Schweigstill Danke für deine Mühe für erklären für was ein 
Maschinenbauer C++ braucht. Aber bevor man so viel schreibt sollte man 
sich etwas Gedanken über die hintergründe machen. Wie ich schon gesagt 
habe studiere ich Nebenberuflich (Fernstudium). Das bedeutet ich Arbeite 
schon irgendwo. Und ich Arbeite genau in der Konstruktion( ja das geht 
auch ohne Ing.). Habe auch eine gewisse Erfahrung in maschinenbau. Ich 
habe vor vielen Jahren angefangen als normaler Schlosser und Schweißer, 
danach gings in die Montage, Endmontage, Auslandmontage (35 Länder 
weltweit) Kundenbetreuung. Nach einiger Zeit habe ich mein 
Maschinenbaumeister ( Handwerk) gemacht. Paar Jahre als Montageleiter 
gearbeitet. Dadurch kommt ja auch arbeiten mit CAD Software. Nach ne 
zeit habe ich Maschinenbautechniker gemacht. Und Arbeite seit ein paar 
Jahren in der Konstruktion.
Ich denke ich habe da schon eine oder andere Erfahrung im Maschinenbau 
und kann genau nachvollziehen wenn unsere Programmierer "Fixpunkte" für 
die Messtechnik haben. Ich kann auch durchaus was mit SPS anfangen (für 
unsere Anlagen). Genau so wie mit MatLab. Und nicht jeder Programierer 
kann damit was anfangen. Auch wen das einer der wichtigsten Tools im 
Maschinenbau ist für die Berechnung und Simulation fast aller Elemente.
ZU den Aufgaben die ich erledige gehören viele Berechnungen( Fundament, 
Laufschienen , Träger, Rollenverschleiß...) Und ich habe noch nie und 
nirgends C/C++ gebraucht(außer bissl bei MatLab) und schon gar nicht 
Mikrokontroller. Und ich denke diese Diskussion hier im Forum weiter zu 
führen ist unnötig.

Ich finde es sehr Nett das der Balou mir gleich die Lösung 
hingeschrieben hat, auch wenn ich damit nicht gerechnet habe. Ich dachte 
bei meinem Post eher an ein paar Hilfestellungen. Dennoch bemühe ich 
mich zu verstehen wie es Funktioniert.

Vielen Dank
Johannes

von Peter M. (r2d3)


Lesenswert?

Johannes,

der Code von Balou macht genau das, was Du tun würdest, wenn Du von Hand 
rechnest.

Die Methode erwartet, die Messwerte in chronologischer Reihenfolge zu 
bekommen und liefert Stück für Stück einen geglätteten Messwert zurück.

Der entscheidende Punkt ist, dass die Verfahrensweise beim ersten 
Messwert anders ist: Hier gibt es keinen Vorgänger. Der Ausgangsmesswert 
muss ohne Änderungen übernommen werden.

Um diesen Fall des ersten Messwertes von allen anderen zu unterscheiden
nutzt Balou einen Wahrheitswert. Diese Variable muss auch bei Beendigung 
der Funktion weiter bestehen, deswegen wird sie als "static" deklariert.
Ihr Ausgangswert wird gleichzeitig auf WAHR gesetzt.

static bool firstCall = true;

Das ist aber nicht die einzige Variable, die dauerhaft gespeichert sein 
muss. Wenn die Methode immer nur den aktuellsten Messwert übergeben 
bekommt, muss sie auch den letzten Messwert kennen, um die 
Glättungsformel anwenden zu können.
Deswegen gibt es eine weitere dauerhafte Variable "smoothValue", die 
beim nächsten Aufruf der Funktion immer noch vorhanden ist.

Bei jedem Aufruf wird die Variable smoothValue zurückgegeben.

Beim ersten Aufruf ist firstCall WAHR.
In diesem Fall entspricht der Rückgabewert der Methode dem Eingabewert 
der Methode. smoothValue wird auf "value" gesetzt, weil smoothValue eine 
dauerhafte Variable ist und beim nächsten Funktionsaufruf mit dem alten 
Wert immer noch zur Verfügung steht. Rein inhaltlich-logisch wurde der 
erste Wert gar nicht geglättet.


Danach wird der Status von firstCall auf FALSE gesetzt, damit die 
Funktion weiß, dass sie beim nächsten Aufruf schon einmal aufgerufen 
worden ist.

Das führt dazu, dass der Block hinter "if" nur genau einmal, und zwar zu 
Anfang aufgerufen wird. Bei Folgeaufrufen ist firstcall FALSCH und es 
werden immer nur die Zeilen hinter "else" ausgeführt.

Da bei jedem Folgeaufruf der vorherige geglättete Messwert "smoothValue" 
noch vorhanden ist, kann die Methode aus dem neuen "value" und dem alten 
"smoothValue" den neuesten geglätten Messwert berechnen, der unter dem 
Namen "smoothValue" für den nächsten Aufruf zur Verfügung steht.

Hier noch einmal der Code von Balou:
========================================================================
double MainWnd::smoothing(double value)
{
  const double factor = 0.2;
  static bool firstCall = true;
  static double smoothValue;

  if (firstCall)
  {
    smoothValue = value;
    firstCall = false;
  }
  else
  {
    smoothValue = factor * value + (1 - factor) * smoothValue;
  }

  return smoothValue;
}

von johannes_t600 (Gast)


Lesenswert?

Danke Peter,

ich war auch schon dabei zu entziffern die ganzen befehle wie static. 
Ich schwer irgend was zu schreiben wenn man nicht weist welche befehle 
und Funktionen einem zur Verfügung stehen.

Aber jetzt verstehe ich langsam wie ich mit meine werten und Variablen 
in dem Programm umgehen soll. Und wie dich abgespeichert werden. das 
Befehl "static" wird bei mir im Buch zb. nur einem Zweizeiler erwähnt.

Ich denke heute oder Abend werde ich mir das noch genauer anschauen und 
mich wieder melden. auch wen das für euch ein klacks ist für mich ist es 
ein Meilenstein.

von J.R.B. (Gast)


Lesenswert?

ich denk mal es war ganau das Ziel des Dozenten, dass so ein 
studierender Student sich mit den zur Verfügung stehenden Befehlen beim 
Lösen der Aufgabenstellung auseinandersetzt... Studenten (v. lat.: 
studens „strebend (nach), sich interessierend (für), sich bemühend um“, 
im Plural studentes)

LOL

von Andreas T. (Firma: KSASicherheitstechnik) (ksatechnik01)


Lesenswert?

Guten Tag!
War denn der Lösungsansatz bezüglich dem C Code nun richtig oder gab es 
noch einen anderen zielführenden Lösungsweg?

von Purzel H. (hacky)


Lesenswert?

Welchen wuerdest du denn vorschlagen ? Hast du ihn ausprobiert ?

von max123 (Gast)


Lesenswert?

hallo,
wenn ich mir das Ausgangssignal anschaue, würde ich die Störspitzen 
nicht
mit schleifenden Mittelwert behandeln. Bei diesem gehen die Spitzen zu 
stark ein. Ein schleifender Medianwert ist, nach meiner Einschätzung, 
schon
fast die  perfekte Lösung.

von Andreas T. (Firma: KSASicherheitstechnik) (ksatechnik01)


Lesenswert?

Hab ihn ausprobiert.
Funktioniert nicht.
Das kann aber auch an mir liegen.

von max123 (Gast)


Lesenswert?

Schick doch die Ausgangsdaten in Excelformat ins Forum. Das Programm,
das nicht funktioniert ist keine Schande, die man verstecken muss.

von Andreas T. (Firma: KSASicherheitstechnik) (ksatechnik01)


Lesenswert?

Hier meine Lösungsansätze, welche mich aber einfach nicht weiter 
bringen.:

#include <stdio.h>
//#pragma warning(disable : 4996)
//------------------------------Glätten-------------------------------
double getAlpha(double alpha) {
  scanf("%lf", &alpha);  //Sucht, Eingabe
  if (alpha > 1 || alpha < 0) {
    printf("Falsche Eingabe, Wert muss zwischen 0 und 1 liegen!");
  }
  return alpha;
}

int main() {
  static double Data[] = { 1.5, 3.1,1.7,1.8 };    //Datensatz, welchen 
wir glätten wollen
  static double alpha = 0.5;  //Glättungsfaktor
  alpha = getAlpha(alpha); //Setze alpha auf gewünschten Wert
  for (int i = 1; i < sizeof(Data) / sizeof(double); i++) { 
//Schleife, in welcher die Werte geglättet werden
    Data[i] = alpha * Data[i] + (1 - alpha) * Data[i - 1];  //Funktion, 
wie in Aufgabe (Wir fangen beim 2. Wert an und nutzen,
  }
  //Ausgabe
  for (int j = 0; j < sizeof(Data) / sizeof(double); j++) {
    printf("Summe: %.3f\n", Data[j]);
  }
  return 0;
}

von Andreas T. (Firma: KSASicherheitstechnik) (ksatechnik01)


Lesenswert?

Nächster Lösungsansatz:

#include <stdio.h>
#pragma warning(disable : 4996) //unwichtig(Visual Studio, mag im C++ 
System nicht unbedingt C-Methoden, Topic:Speichersicherheit, etc.)
//---------------------------------------Eingabe------------------------ 
----------\\
float getAlpha(float alpha) {
scanf("%f", &alpha); //Sucht, Eingabe
if (alpha > 1 || alpha < 0) {       //Wir wollen keinen Faktor n<0 oder 
n>1
printf("Falsche Eingabe, Wert muss zwischen 0 und 1 liegen!");
}
return alpha;
}
//---------------------------------------Main-Funktion------------------ 
----------------\\
int main() {
static float Data[] = { 1.5, 3.1,1.7,1.8 }; //Datensatz, welchen wir 
glätten wollen
static float alpha = .5; //Glättungsfaktor
alpha = getAlpha(alpha); //Setze alpha auf gewünschten Wert
for (int i = 1; i < sizeof(Data)/sizeof(float); i++) { //Schleife, in 
welcher die Werte geglättet werden
Data[i] = alpha * Data[i] + (1 - alpha) * Data[i - 1]; //Glättfunktion
}
//---------------------------------------Ausgabe------------------------ 
----------\\
for (int j = 0; j < sizeof(Data) / sizeof(float); j++) {      //Ausgabe 
(kann weggespart werden)
printf("Summe: %.3f\n", Data[j]);
}
return 0;
}

von Andreas T. (Firma: KSASicherheitstechnik) (ksatechnik01)


Lesenswert?

Lösung, mit Array:

  for (int i = 1; i < sizeof(Data)/sizeof(float); i++) {    //Schleife, 
in welcher die Werte geglättet werden
    Data[i] = alpha * Data[i] + (1 - alpha) * Data[i - 1];  //Formel, 
unter einsatz von Arrays
}


Formel, ohne Array: Glattwert=Faktor*y+(1-Faktor)* y-1


Mache ich vielleicht etwas falsch bei der Einbindung in die Aufgabe mit 
der Glättung in SiSy? Ich bearbeite gerade die selbe Einsendeaufgabe mit 
der Messwertglättung. Ich bekomme die gleichen Fehlermeldungen wie 
weiter oben im Text beschrieben.

von Andreas T. (Firma: KSASicherheitstechnik) (ksatechnik01)


Lesenswert?

Eine Lösung mit Array ist wahrscheinlich auch generell nicht richtig, da 
die Glättungsfunktion y´(t)=faktor*y(t)+(1-faktor)*y(t-1) direkt 
verwendet werden soll.

von Andreas T. (Firma: KSASicherheitstechnik) (ksatechnik01)


Lesenswert?

Also wenn hier zufällig jemand mit SiSy arbeitet und die entsprechende 
Aufgabenstellung mit der Glättung aufrufen kann, vielleicht auch Lust 
hat mir meine Fehler aufzuzeigen, dann wäre mir das eine große Hilfe. 
Ich vermute mal es bringt nichts einfach eine C-Code zu schreiben, 
sondern dieser muss auch entsprechend in die Aufgabe eingebunden werden.

von Jonas B. (jibi)


Lesenswert?

>Eine Lösung mit Array ist wahrscheinlich auch generell nicht richtig...
Was ein Satz...

>Also wenn hier zufällig jemand mit SiSy arbeitet und die entsprechende
>Aufgabenstellung mit der Glättung aufrufen kann, vielleicht auch Lust
>hat mir meine Fehler aufzuzeigen, dann wäre mir das eine große Hilfe.

Ich höre hier nur eine Sissy jammern...

von max123 (Gast)


Lesenswert?

Das Array mit 4 Daten  ist zu kurz um eine Messwertglättung beurteilen 
zu können.
In den Bildern war doch ein Sinus-Kurve mit Störrzacken. ca. 400 
Messwerte.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.