AVR Studio, Rechnen mit Fließkommazahlen

#1687962
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?
Gast #1687979
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
Gast #1687992
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
#1692225
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?
#1692415
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.
Persönliche Seite #1692518
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%
#1692530
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.
#1692817
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.
#1692928
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.
Gast #1693044
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren