www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR Studio, Rechnen mit Fließkommazahlen


Autor: Multi Kulti (multikulti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Tag,
ich benutze das Avr Studio 4.14. Ich möchte mir ein paar Konstanten zur 
präprozessorzeit vom Assembler ausrechnen lassen. Jetzt habe ich aber 
festgestellt das dieser mir die Fließkommazahlen einfach hinter dem 
Komma abschneidet.
Hier mal das Beispiel:

.equ Drehzahl = 60
.equ MessInterval = 0.1
.equ CPUFrequenz = 8000000
.equ PWMFrequenz = CPUFrequenz/256
.equ DrehzahlFaktor = (((Drehzahl/60)/MessInterval)/1000)*500

Die Konstante "DrehzahlFaktor" soll nacher im Code an den entsprechenden 
stellen eingefügt werden. Damit ich den wert nicht jedesmal neu 
ausrechnen will, habe ich die Formel dazu Geschrieben und ich brauch nur 
die Drehzahl ganz oben zu ändern. Ist jetzt eigentlich auch nicht 
relevant, denn das eigentliche Problem ist, das der AVR Asembler mir bei 
der Konstante "MessInterval" die 1 hinter dem komma abschneidet. Das 
erzeugt dann natürlich die Fehlermeldung das nicht durch 0 geteilt 
werden kann.

Was kann ich tun?

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Und das überrascht dich?

Was geht ist (im Assembler2) z.B

.equ DrehzahlFaktor = Q7((((Drehzahl/60)/MessInterval)/1000)*500)

oder

.equ DrehzahlFaktor = Q15((((Drehzahl/60)/MessInterval)/1000)*500)

Das ergibt Werte, wie sie bei FMULxx verwendet werden. Also im Bereich 
-1<x<+1.

MfG Spess

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Was kann ich tun?

Der Preprozessor arbeitet mit 32-Bit-Ganzzahlen. Man sollte also die 
Konstanten ganzzahlig halten. Mit Festkommaarithmetik kommt man oft zum 
selben Ergebnis.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Nachtrag:

>denn das eigentliche Problem ist, das der AVR Asembler mir bei
>der Konstante "MessInterval" die 1 hinter dem komma abschneidet. Das
>erzeugt dann natürlich die Fehlermeldung das nicht durch 0 geteilt
>werden kann.

Dann nehm doch:

.equ DrehzahlFaktor = 1/(((Drehzahl/60)/MessInterval)...)

mit einer ensprechenden Skalierung 2^n und mache eine Multiplikation.

MfG Spess

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Probem Ganzzahlrechnung wird sich in allen deinen Berechnungen 
zeigen.

Gib doch MessInterval in Millisekunden statt in s an, d.h. verrechne es 
mit dem Faktor 1000

Ich würde die Formel auch umstellen insbesondere die Multiplikation mit 
500 am Anfang statt am Schluss machen.

.equ DrehzahlFaktor = (Drehzahl * 500) / (60 * ms_MessInterval)

Autor: Иван S. (ivan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oberlehrermodus á la Falk B.:
Du suchst eigentlich 
http://www.mikrocontroller.net/articles/Festkommaarithmetik

Autor: Multi Kulti (multikulti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also irgendwie ist mir das ganze noch immer Schleierhaft. Mit folgender 
Schreibweise hat es jetzt Funktioniert:

.equ Drehzahl = 100 ; Umdrehungen pro Minute
.equ MessInterval = 10 ; in Millisekunden
.equ DrehzahlFaktor = ((Drehzahl/60)*500)/(1000/MessInterval)
.equ CPUFrequenz = 8000000
.equ PWMFrequenz = CPUFrequenz/256

Während es mit folgender Schreibweise nicht funktionierte:

MessIntervall = 10 ; in Millisekunden
.equ DrehzahlFaktor = ((Drehzahl/60))/(1000/MessInterval)*500

In dem Fall wurde zwar keine Fehlermeldung produziert, aber die 
Konstante DrehzahlFaktor hat einfach den Wert 0.

Ich stehe aber schon wieder vor dem nächsten Problem: Ich brauche für 
einen P Regler einen Verstärkungsfaktor zwischen 1 und 2. Das heißt ich 
muss mit einer Kommazahl Multiplizieren. Das gedachte Komma ist nach dem 
6. Bit. Das heißt: 00,000000 Der Multiplikator wird dann nach dem 
bekannten Verfahren um 6 stellen nach links verschoben, multipliziert 
und wieder zurückgeschoben. Ich möchte den Wert für den 
Verstärkungsfaktor wieder per .equ Befehl vom Assembler errechnen 
lassen. Nur der kann ja nicht mit Kommazahlen umgehen und erst recht 
nicht mit welchen die ihre komastelle nach dem 6. bit haben. Hat jemand 
ne Idee?

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
C

Oliver

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Иван S. schrieb:
> Oberlehrermodus á la Falk B.:
> Du suchst eigentlich
> http://www.mikrocontroller.net/articles/Festkommaarithmetik

Nein, das sucht er eigentlich nicht. Das Prinzip ist zwar dasselbe, ihm 
geht es aber um den Preprozessor des AVR-Studios (also um Rechnen auf 
dem PC), während der Artikel vom Rechnen auf dem AVR ausgeht. Das sind 
zwei völlig verschiedene Baustellen.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Steffen P. schrieb:

> Mit folgender Schreibweise hat es jetzt Funktioniert:

Scheinbar...

> .equ Drehzahl = 100 ; Umdrehungen pro Minute
> .equ MessInterval = 10 ; in Millisekunden
> .equ DrehzahlFaktor = ((Drehzahl/60)*500)/(1000/MessInterval)
>
> Während es mit folgender Schreibweise nicht funktionierte:
> .equ Drehzahl = 100 ; Umdrehungen pro Minute
> .equ MessInterval = 10 ; in Millisekunden
> .equ DrehzahlFaktor = ((Drehzahl/60))/(1000/MessInterval)*500
>
> In dem Fall wurde zwar keine Fehlermeldung produziert, aber die
> Konstante DrehzahlFaktor hat einfach den Wert 0.

Fliesskommaergebnis:
(100/60)*500/(1000/10) = 8,33

Fall 1:
Teilausdruck 1a:
100/60 = 1,67 Ganzzahl: 1
*500   = 500

Teilausdruck 1b:
1000/10 = 100

Gesamtausdruck 1:
500 / 100 = 5
Fehler: -40%

Fall 2:
Teilausdruck 2a:
100/60 = 1,67 Ganzzahl: 1

Teilausdruck 2b:
1000/10 = 100

Gesamtausdruck 2:
1 / 100 = 0,01 Ganzzahl: 0
* 500   = 0
Fehler: -100%


Multipliziere früh mit 500
Beitrag "Re: AVR Studio, Rechnen mit Fließkommazahlen"

.equ DrehzahlFaktor = ((Drehzahl*500)/60)/(1000/MessInterval)

Fall 3:
Teilausdruck 3a:
100 * 500 = 50000
50000/60 = 833,33 Ganzzahl: 833

Teilausdruck 3b:
1000/10 = 100

Gesamtausdruck 3:
833 / 100 = 8,33 Ganzzahl: 8
Fehler: -4%

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

Bewertung
0 lesenswert
nicht lesenswert
Steffen P. schrieb:
> Also irgendwie ist mir das ganze noch immer Schleierhaft.

Weil du in guter alter Mathemanier davon ausgehst, dass dir auch bei 
Zwischenergebnissen alle Kommastellen erhalten bleiben. Besonders bei 
Divisionen ist das aber fatal, denn: Es gibt keine Kommastellen. Weder 
im Endergebnis noch in den Zwischenergebnissen.

  5 / 8        ergibt nun mal 0
und
  5 / 8 * 100  ergibt immer noch 0, denn 0 * 100 ist 0

aber
  5 * 100 / 8  ergibt 62, denn 500 / 8 ergibt 62

Fazit: Du willst Divisionen so spät wie möglich machen, weil dir dabei 
alle Kommastellen des Ergebnisses verlorengehen. Auch dann wenn mit dem 
Ergebnis der Division noch weiter gerechnet wird.

Autor: Multi Kulti (multikulti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, okay das ergibt Sinn.
Ich frag mich nur, warum das avr studio nicht einfach komazahlen 
unterstützt. Das würde vieles einfacher machen^^
Nur wie mache ich das jetzt wenn vom Assembler eine Kommazahl 
ausgerechnet werden soll die dann im programm eingefügt werden soll. Es 
soll eine Kommazahl mit gedachtem komma nach dem 6. Bit sein. Die 
rechenroutine ist fertig und funktioniert auch. Da ich den wert aber 
praktisch ermitteln muss (es handelt sich ja um einen motorregler) muss 
ich ihn oft ändern und jedesmal neu ausrechnen und eintippen. Es währe 
viel einfacher wenn ich einfach einen Verstärkungsfaktor in Dezimal mit 
der .equ direktive eintippen könnte und der assembler mir dann den Wert 
mit der gedachten kommastelle errechnet und ins Programm einfügt.

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

Bewertung
0 lesenswert
nicht lesenswert
Steffen P. schrieb:

> Ich frag mich nur, warum das avr studio nicht einfach komazahlen
> unterstützt. Das würde vieles einfacher machen^^

Mit welchem Floating Point Schema soll denn gerechnet werden? Auf 
wieviele Nachkommastellen?

Die Thematik 'Floating Point Rechnen' ist wesentlich komplexer als du 
dir im Moment auch nur vorstellen kannst.

Wenn du genaueres wissen willst, empfehle ich dir die Lektüre:
http://docs.sun.com/source/806-3568/ncg_goldberg.html

Naives Benutzen von Floating Point führt oft zu Problemen, an die man im 
Vorfeld nicht gedacht hat.

> ich ihn oft ändern und jedesmal neu ausrechnen und eintippen. Es währe
> viel einfacher wenn ich einfach einen Verstärkungsfaktor in Dezimal mit
> der .equ direktive eintippen könnte und der assembler mir dann den Wert
> mit der gedachten kommastelle errechnet und ins Programm einfügt.

Du musst die Berechnung, die du mit dem Taschenrechner machst, so 
formulieren, dass dich das Problem nicht beisst.

Ja, so ist das nun mal in der Programmierung. Das ist keine Schema F 
Arbeit.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

> Es währe viel einfacher wenn ich einfach einen Verstärkungsfaktor in
>Dezimal mit der .equ direktive eintippen könnte und der assembler mir dann
> den Wert mit der gedachten kommastelle errechnet und ins Programm einfügt.

So sollte es gehen:

.equ float  = ((INT(2.567))<<6) + ((Q7(FRAC(2.567)))>>1)

MfG Spess

Autor: Multi Kulti (multikulti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, das funktioniert tatsächlich. Aber ich denke der Assembler kann 
nicht mit kommazahlen umgehen. Wie ist das dann möglich?
Gibt es hier ein Tutorial zum Rechnen mit dem Assembler?

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Gibt es hier ein Tutorial zum Rechnen mit dem Assembler?

Nicht das ich wüsste. Aber in der AVR-Studio-Hilfe zum Assembler unter
'User's Guide->Expressions' findest die notwendigen Infos.

MfG Spess

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spess53 schrieb:
> Hi
>
>>Gibt es hier ein Tutorial zum Rechnen mit dem Assembler?
>
> Nicht das ich wüsste. Aber in der AVR-Studio-Hilfe zum Assembler unter
> 'User's Guide->Expressions' findest die notwendigen Infos.

Warum suchen viele Leute immer wieder Infos im Netz, die sie bereits auf 
der eigenen Festplatte haben?

>
> MfG Spess

Autor: Multi Kulti (multikulti)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf die seite in der hilfe bin ich durchaus schon gestoßen. Damit das 
richtig sitzt ist ein Tutor aber nicht schlecht.

Naja, danke für die viele Hilfe! Ihr habt mir gut weitergeholfen.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Damit das richtig sitzt ist ein Tutor aber nicht schlecht.

Braucht ihr denn für jeden Sch... ein Tutorial? Einfach mal hinsetzen 
und selbst ausprobieren.

MfG Spess

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.