www.mikrocontroller.net

Forum: Projekte & Code SINUS - COSINUS / KOSINUS - BEISPIEL (Assembler) ATmega8


Autor: Bernhard S. (bernhard)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ein kleines Beispiel einer 8 Bit SINUS- und COSINUS (KOSINUS)

Berechnung in Assembler.



Berechnungsverfahren:

In einer Tabelle wurden 91 Sinus-Werte (0-90°) hinterlegt.

Alle Sinus und Cosinus-Werte (0...65535°) werden durch Spiegelung aus
diesen Tabellen-Werten berechnet.

Das Ergebnis ist ein 8Bit -Wert (-100...+100)


Anmerkung:

Für andere µC muss ggf. folgendes geändert werden:

- inc-Datei
- Interrupt-Vektoren
- STACK-Initialisierung


Bernhard

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

Bewertung
0 lesenswert
nicht lesenswert
kleiner Tip.
Wenn du Konstanten addieren musst, kannst du das,
indem die negatiev Konstante subtrahiert wird.

zb. hier
  ldi temp3, low(90)
  ldi temp4,high(90)
  ; 90° ADDIEREN
  add temp1,temp3
  adc temp2,temp4

-------------------------------
wird zu:
        ; 90° ADDIEREN
        subi   temp1, low( -90 )
        sbci   temp2, high( -90 )

Aus irgendwelchen unerfindlichen Gründen hat Atmel
dem µC kein add_immediate spendiert.

die subi und sbci Befehle können auch an anderen Stellen
im Code nutzbringend eingesetzt werden.

Autor: Bernhard S. (bernhard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl Heinz Buchegger,

Danke für Deinen Tipp, den subi und sbci - Befehl zu verwenden.

Bernhard

Autor: pencho (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Karl Heinz Buchegger
Laut Wikipedia http://de.wikipedia.org/wiki/Atmel_AVR ist diser Befehl
entwernt worden um Chipfläche zu sparen und so "Addition mit direktem
16-Bit-Parameter" zu realisieren.

Autor: Bernhard S. (bernhard)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@alle

Ein Beispiel für z.B. einen ATmega1284p / ATmega1284.

Winkel:          0...360 GRD, in 0,1 GRD-Schritten
Wertebereich: -127...+127

Vorteil: wenig Prozessor-Takte

Nachteil: sehr speicherintensiv


Bernhard

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei Antriebssteuerungen u.ä. werden Winkel oft nicht in Grad, sondern in
Einheiten von 360°/2^(8·n) dargestellt, d.h. der Vollkreis wird in 2^8,
2^16 oder 2^32 Teile unterteilt. Das hat mehrere Vorteile:

- Der Wertebereich eines uint8_t, uint16_t bzw. uint32_t wird voll
  genutzt, wodurch man bei gegebener Variablengröße die höchste
  Winkelauflösung erreicht.

- Bei der Berechnung von Winkeln werden die Ergebnisse automatisch
  normiert, d.h. auf den Bereich [0°,360°) reduziert.

- Die Berechnung von Winkeländerungen liefert ohne Fallunterscheidungen
  auch dann die erwarteten Ergebnisse, wenn zwischen dem Vorher- und dem
  Nachherwinkel ein 360°-Sprung liegt.

- Der Quadrant, in welchem ein Winkel liegt, kann mit einfachen
  Bitoperationen bestimmt werden.

Hier sind Sinus-/Cosinus-Routinen für 8-Bit-Argumente und -Ergebnisse:
zl  = 30
zh  = 31

cos:
  subi zl,-0x100/4
sin:
  push zh
  bst zl,7
  sbrc zl,6
  neg zl
  andi zl,0x7f
  ldi zh,hi8(sintab)
  lpm zl,Z
  brtc 1f
  neg zl
1:
  pop zh
  ret

.p2align 8
sintab:
  .byte   0,   3,   6,   9,  12,  16,  19,  22,  25,  28,  31,  34,  37
  .byte  40,  43,  46,  49,  51,  54,  57,  60,  63,  65,  68,  71,  73
  .byte  76,  78,  81,  83,  85,  88,  90,  92,  94,  96,  98, 100, 102
  .byte 104, 106, 107, 109, 111, 112, 113, 115, 116, 117, 118, 120, 121
  .byte 122, 122, 123, 124, 125, 125, 126, 126, 126, 127, 127, 127, 127

Argument und Ergebnis werden beide in R30 übergeben. Ein Winkelschritt
entspricht dabei 360°/256 ≈ 1,4°. Die Sinustabelle enthält 65 Einträge,
d.h. für die Argumente 0° (0x00) bis einschließlich 90° (0x40). Die
Ergebnisse liegen im Bereich [-127,+127]. Die Ausführungsdauer (ohne
CALL und RET) beträgt 14 Zyklen für den Sinus und 15 Zyklen für den
Cosinus.

Die Sinus-Tabelle wird an eine durch 256 teilbare Adresse gelegt, was
die Adressbestimmung aus dem Index vereinfacht.

Die verwendete Syntax ist die des GNU-Assemblers. Für den
Atmel-Assembler müsste man ein paar DInge anpassen.

Eine entsprechende Routine könnte man auch für 16-Bit-Argumente und
-Ergebnisse schreiben. Da die Tabelle dann aber 16385 16-Bit-Werte
enthält, wird sie über 32-KiB groß. Deswegen ist hier eine kleinere
Tabelle und eine lineare Interpolation zwischen einzelnen Stützstellen
sinnvoll. Die Stützstellen wählt man am besten äquidistant mit einem
Abstand von 2^n, so dass man sich eine aufwendige Division spart. Dann
laufen die 16-Bit-Routinen – gemessen an der erreichten Genauigkeit –
ebenfalls recht fix.

Autor: Bernhard S. (bernhard)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Yalu für die sehr wertvollen Hinweise :-)

Gruß Bernhard

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Interessant wäre es, diesen Algortithmus in Assembler umzusetzen:
Beitrag "Re: minimalistische Berechnung einer Sinusschwingung"
um zu sehen, wie schnell er auf einem AVR läuft.

Autor: Possetitjel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Yalu X. schrieb:

> Bei Antriebssteuerungen u.ä. werden Winkel oft nicht in Grad,
> sondern in Einheiten von 360°/2^(8·n) dargestellt, d.h. der
> Vollkreis wird in 2^8, 2^16 oder 2^32 Teile unterteilt. Das
> hat mehrere Vorteile: [...]

Stimmt alles. Hat aber den Schönheitsfehler, dass kleine Winkel
(z.b. 1°) nicht exakt darstellbar sind.
Um dem bei 16Bit-Darstellung abzuhelfen, könnte man 20" als
Einheit wählen; der Vollkreis würde dann in 64800 Teile geteilt.
Der Zahlbereich wird dann zu 98.87% ausgenutzt. Die Rechnerei
wird jedoch durch die 736 unbenutzten Digit komplizierter.

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Possetitjel schrieb:
> Stimmt alles. Hat aber den Schönheitsfehler, dass kleine Winkel
> (z.b. 1°) nicht exakt darstellbar sind.
> Um dem bei 16Bit-Darstellung abzuhelfen, könnte man 20" als
> Einheit wählen;

Warum muss 1° oder ein ganzzahliger Bruchteil davon exakt darstellbar
sein? Die Unterteilung des Vollkreises in 360 Teile ist doch ziemlich
willkürlich festgelegt worden.

Meistens muss sowieso irgendo skaliert werden, um bspw. Drehgeber- oder
Schrittmotorauflösungen oder Getriebeübersetzungen zu berücksichtigen.
Deswegen ist man in der Wahl der internen Winkeldarstellung recht frei,
solange die Auflösung hoch genug ist. So nimmt man praktischerweise
diejenige Darstellung, mit der am leichtesten zu rechnen ist.

Autor: Possetitjel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Yalu X. schrieb:

> Possetitjel schrieb:
>> Stimmt alles. Hat aber den Schönheitsfehler, dass kleine Winkel
>> (z.b. 1°) nicht exakt darstellbar sind.
>> Um dem bei 16Bit-Darstellung abzuhelfen, könnte man 20" als
>> Einheit wählen;
>
> Warum muss 1° oder ein ganzzahliger Bruchteil davon exakt
> darstellbar sein?

"Muss" überhaupt nicht.

Das war nur eine eher anekdotische Randbemerkung. - Vor längerer
Zeit gab's hier mal eine Diskussion über Winkeldarstellung und
Winkelfunktionen mit ganzen Zahlen bzw. Festkommazahlen.
Hintergrund war eine Roboter-Anwendung, bei der schnell und
ohne Fließkomma gerechnet werden sollte.

Da mich das interessiert hat, habe ich vor Monaten mal gesucht,
ob sich das klassische Grad-Minute-Sekunde-System irgendwie
kompatibel in übliche Ganzzahlen abbilden lässt. Resultat war
die bereits geschilderte Unterteilung des Vollkreises in
360*60*3 = 64800 Teile, was ideal in 16bit passt.

> Die Unterteilung des Vollkreises in 360 Teile ist doch ziemlich
> willkürlich festgelegt worden.

Zweifellos. - Dennoch ist mir ganz recht, dass am Preisschild
in der Kaufhalle nicht "0x3E7" dransteht, sondern "9.99 Euro",
auch wenn das Zehnersystem letztlich genauso willkürlich ist.

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.