www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Modulo Addition


Autor: Frank Mayer (frankm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Kollegen,

ich hänge an einem Problem fest, welches sich so darstellt:
Ich muß zu einem laufenden Winkel (Sägezahn 0...2PI) einen Offset hinzu 
addieren. Das Ergebniss muß dann wieder auf 0...2PI begrenzt sein 
(Winkelüberlauf).
Bis jetzt habe ich die "Begrenzung" so gelöst:

if (winkel > PI2) winkel = winkel - PI2
if (winkel < 0.0) winkel = winkel + PI2

was rein mathematisch funktioniert.

Jedoch:
Wenn der Ursprungs-Sägezahn auf Null springt, dann bekomme ich für einen 
Zyklus eine umgekehrte Spitze in mein Ergebniss.


Ich habe schon viel versucht, jedoch kommt hier das klassische Brett 
vorm Kopf zum Tragen & ich brauche Unterstützung...

Vielen Dank für Eure Ideen!


Gruss & frohe Ostern!

Frank

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verstehe noch nicht so ganz, was der Winkeloffset mit einem Sägezahn 
zu tun haben soll.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welche Programmiersprache?
Welche Datentypen?
Welcher Prozessor?

Und evtl. wäre eine Skizze/Foto/Bild nicht schlecht...

Autor: Frank Mayer (frankm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Kollegen,

ich verwende einen TriCore 1796, programmiere in C und verwende Float 
als Datentyp.

@Simon:

Wenn Du Dir einen Sägezahn mit einer Phasenlage vorstellst und Du aber 
zum weiteren rechnen soll dieser Sägezahn aber eine andere Phasenlage 
besitzen. Dazu addiert man einen Offset und man erhält eine neuen 
Sägezahn jedoch mit einer Phasenverschiebung.


Gruss


Frank

Autor: noname (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Offset addieren. Wenn Ergebnis größer als 2PI, dann 2PI abziehen.

Autor: HolgerT (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Frank,

Frank Mayer schrieb:
> if (winkel > PI2) winkel = winkel - PI2
> if (winkel < 0.0) winkel = winkel + PI2

Ich nehme an, vorher machst Du die Addition von Winkel und Offset. Dann 
verstehe ich die zweite Zeile nicht - der Winkel (Sägezahn), kann nicht 
negativ werden. Aber vielleicht habe ich das Problem noch nicht richtig 
verstanden.

Ich würde es so machen (Pseudocode):
winkel := winkel + Offset
wenn (winkel > PI2) dann winkel = winkel - PI2

oder, falls Offset > PI2 sein kann:
winkel := winkel + Offset
solange (winkel > PI2) mache
  winkel = winkel - PI2

Gruß
HolgerT

Autor: Helmut -dc3yc (dc3yc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für solche Fragestellungen gibts in C den Modulo-Operator. Als 
Wertebereich des Ergebnisses würde dann z.b. 0<=winkel<PI2 herauskommen.

Autor: Frank Mayer (frankm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Kollegen,

wenn ich die Modulo Funktion verwende, die Helmut angesprochen hat:

(als Pseudo-Code)

winkel = winkel + Offset;

winkel = modulo(winkel,PI2);

Wie sieht das den in C aus?


Danke!


Gruss


Frank

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kann es sein dass PI2  0,5 Pi entspricht?

Sieht ähnlich in der cmath Lib aus (glaub ich):
PI_2 ist da Pi halbe

Schreib mal 2*PI hin, damit die Schreibweise eindeutig ist.

Autor: Georg (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank Mayer schrieb:
> Wie sieht das den in C aus?

Zwei Varianten:

1.
winkel = winkel + Offset;
winkel = (winkel < PI2) : winkel ? winkel - PI2;

2.
winkel = winkel + Offset;
if(winkel > PI2)
  winkel -= PI2;

Autor: Frank Mayer (frankm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Flo,

ich kann auch 6.28 oder die Zahl X einführen, was ja dem Rechengang 
nichts abnimmt.


Gruss,


Frank

Autor: Georg (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sry, bei der ersten Variante gehoeren ':' und '?' vertauscht

Autor: stokes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Geht das nicht einfacher mit dem Modulo Operator welcher in C 
normalerweise Verwendung findet?

so in etwa dann: winkel = winkel % (2*pi);
oder kurz winkel %= (2*pi);

Dann braucht man sich auch nicht drum kümmern wenn der Winkel ein 
Vielfaches von 2Pi größer ist.

Mfg

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Modulo Operator
Der ist in C nur für Integertypen definiert, nicht aber für 
Fliesskommazahlen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Jedoch:
> Wenn der Ursprungs-Sägezahn auf Null springt, dann bekomme ich für einen
> Zyklus eine umgekehrte Spitze in mein Ergebniss.

Jede Wette:
Dein Sägezahn mag zwar auf 0 springen, in deinem float steht aber keine 
0, sondern irgendwas in der Form -1E-12. Also eine sehr kleine negative 
Zahl. Und die ist nun mal kleiner als 0.

Willkommen in der realen Welt, in der naive Anwendung von float oder 
double sofort mit 'seltsamen Verhalten' bestraft wird. Natürlicht nicht 
sofort, sondern erst dann wenn der Kunde das erste mal zusieht.

Bei Fliesskommarechnungen immer ein Epsilon einplanen! Wer float so 
vergleicht

   if( irgendwas == wasanderes )

sollte sofort eine mit dem nassen Fetzen übergezogen bekommen

   if( fabs( irgendwas - wasanderes ) < epsilon )

ist die Art und Weise wie man Fliesskommazahlen miteinander auf 
Gleichheit vergleicht.
Ähnliches gilt auch für < und > Vergleiche.

Für Epsilon muss man sich überlegen, wie gross der Rechenfehler an der 
betreffenden Stelle sein kann und dementsprechend ein Epsilon auswählen.

Autor: stokes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay, sorry das wusste ich nicht.
Somit würde ich mich dan bzgl. der Lösung am 2ten Vorschlag von Georg 
anhalten und es um ne Schleife ergänzen, um sicherzustellen, dass der 
resultierende Winkel immer zwischen 0 und 2pi liegt.
Das könnte dann etwa so aussehen:

winkel = winkel + Offset;
while(winkel > 2*PI)  winkel -= 2*PI;

mfg

Autor: Frank Mayer (frankm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Kollegen,

um nun die erste Runde zusammenzufassen:

- modulo Operator gibt ist hierfür nicht (nur für int)
- man muß beide Richtungen abfragen(abfangen)

liege ich mit meinem:

if (winkel > 2*PI) winkel = winkel - 2*PI
if (winkel < 0.0)  winkel = winkel + 2*PI

so weit neben drann?

Zugegeben muß diese Schreibweise einen Fehler beinhalten. Jedenfalls für 
den Fall, daß der Referenz-Sägezahn gegen Null springt, sonst hätte ich 
diesen Rücksprung für diesen Zyklus nicht.

Ist es etwa die zweite Zeile?

Ich versuche es mit dem Vorschlag von stokes..


Vielen Dank für die vielfältige Hilfe!

Gruss,


Frank

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.