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
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
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.
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.
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.
Dampf Stampf schrieb: > Etwas im Sinne von : > http://www.ibrtses.com/embedded/exponential.html Das scheint so was zu sein.
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 | } |
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.
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?
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.
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.
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?
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.
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.
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
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; }
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.
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
Guten Tag! War denn der Lösungsansatz bezüglich dem C Code nun richtig oder gab es noch einen anderen zielführenden Lösungsweg?
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.
Schick doch die Ausgangsdaten in Excelformat ins Forum. Das Programm, das nicht funktioniert ist keine Schande, die man verstecken muss.
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; }
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; }
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.
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.
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.
>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...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.