mikrocontroller.net

Forum: Compiler & IDEs 16-Bit Ergebnis aus 8-Bit-Variablen berechnen?


Autor: Erik H. (agutanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich möchte in einer Lüftersteuerung aus einer gemessenen Temperatur und 
diversen Variablen ein PWM-Wert für Lüfter berechnen.
Gerechnet werden soll ausschließlich mit positiven Integer-Werten und 
das Ergebnis soll, falls größer 255 auf 255 reduziert werden.

Während das Ergebnis und Zwischenwerte größer 255 werden können, sind 
alle Ausgangswerte 8-Bit-Variablen.
Wie sage ich dem Compiler, dass er die Rechnung als 16-Bit-Rechnung 
compilieren soll? Reicht es eine 16-Bit-Variable als Ergebnis anzugeben?

>>Informationen:
µC:  ATmega168
Compiler: AVR-GCC (AVR-Studio 4)
Varibalen:
eingelesene Temperatur (T), Einschalt-Temperatur (Tmin), Temperatur für 
volle Drehzahl (Tmax), an Lüfter übertragener PWM-Wert (PWM), minimal 
möglicher PWM-Wert (PWMmin), maximal gewollter PWM-Wert (PWMmax)
Rechenweg:
PWM = ( ((T-Tmin) * (PWMmax-PWMmin)) / (Tmax-Tmin) ) + PWMmin

Autor: Tec Nologic (tecnologic) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi,

das Problem lößt man mit den sog. casts dh.

PWM = (uint8_t)( ((uint16_t)(T-Tmin) * (PWMmax-PWMmin)) / (Tmax-Tmin) ) 
+ PWMmin

(typ)Variable

du schreibst in die Klammern den Typ mit dem der Compiler die Variable 
interpretieren soll. Bei deiner Rechnung heißt das das du (T-Tmin) als 
16 bit auswertest und das gesamte Ergebnis wieder als 8 bit der 
Variablen PWM zu weist.

ich hoffe das war halbwegs verständlich.

MfG

Tec

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

Bewertung
0 lesenswert
nicht lesenswert
Kanst du dir alles sparen:
Alte C-Regel:  gerechne twird mindestens im Datentyp int.
Auf dem AVR also mit 16 Bit

Autor: Erik H. (agutanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich kann mir nicht vorstellen, dass auf einem 8-Bit µC jede Berechnung 
mit 16-Bit erfolgt... das wäre nun doch recht ineffizient!
Aber ich werde es mal mit einem Cast vor der gesamten Rechnung 
probieren.
Ohne Casts kommt recht Schnell ziemlicher Mist raus!

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

Bewertung
0 lesenswert
nicht lesenswert
Erik H. schrieb:
> ich kann mir nicht vorstellen, dass auf einem 8-Bit µC jede Berechnung
> mit 16-Bit erfolgt... das wäre nun doch recht ineffizient!

LIes ein C-Buch.

Es spielt keine Rolle was du dir auf einem 8-Bit µC vorstellen kannst 
und was nicht. C ist eine genormte Sprache. Entscheidend ist, was in 
dieser Norm steht. Und da steht nun mal drinnen, dass mindestens in int 
gerechnet wird.

Es steht allerdings auch drinnen, dass es die AS_IF Regel gilt.
Wenn der Compiler beweisen kann, dass sich am Ergebnis nichts ändert, 
wenn er anstelle von in 16 Bit, die ganze Berechnung nur in 8-Bit 
realsiert, dann darf er das tun.
Allerdings wird ihm das in deinem Fall schwer fallen.

Autor: Erik H. (agutanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Woran kann ich erkennen, wie groß "int" im GCC-Compiler ist?

Ich Kompiliere immer mit der Optimierung: "-0s" könnte das zu Problemen 
führen?

habe es so probiert:

16-bit-variable = (uint16_t)(rechnung);

Die Rechenergebnisse sind noch immer  recht verwirrend... Irgendwie viel 
zu gering.

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

Bewertung
0 lesenswert
nicht lesenswert
Erik H. schrieb:
> Woran kann ich erkennen, wie groß "int" im GCC-Compiler ist?

sizeof(int)
sagt es dir.
Aber im WinAVR ist siezof(int) gleich 2. Also 16 Bit

> Ich Kompiliere immer mit der Optimierung: "-0s" könnte das zu Problemen
> führen?

Kann.
Aber anders als du denkst. Der Compiler bearbeitet deinen Text deswegen 
immer noch nach den C-Regeln. Nur nutzt er konsequenter Möglichkeiten 
aus, die du ihm offen lässt. Darum ist es auch wichtig, die C-Regeln zu 
kennen.
Denn dein Compiler lässt sich nicht weichkochen. Der hält sich 
konsequent an: Unwissenheit schützt nicht vor Strafe.

> 16-bit-variable = (uint16_t)(rechnung);

Das bringt nichts.

Einem Kind, das schon in den Brunnen gefallen ist, kannst du hinterher 
Mund zu Mund Beatmung machen, bis du umfällst. Das bringt niemanden 
weiter.
Du musst im Vorfeld schon dafür sorgen, dass es erst gar nicht 
reinfällt!

http://www.mikrocontroller.net/articles/FAQ#Datent...

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

Bewertung
0 lesenswert
nicht lesenswert
OK.
Jetzt mal Tacheles

PWM = ( ((T-Tmin) * (PWMmax-PWMmin)) / (Tmax-Tmin) ) + PWMmin

Nachdem wir jetzt einig sind, dass das als int (oder unsigned int, 
aufpassen! Max - Min darf dann natürlich nicht negativ werden) gerechnet 
wird:
wie sehen deine Zahlenwerte aus? bzw. Wobei gibt es Ärger?

Autor: Erik H. (agutanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab den Fehler Gefunden:
War lediglich ein Denkfehler und etwas ungenaues Hinsehen...
Sobald die gemessene Temperatur (T) größer als Tmax war, stiegen die 
errechneten Werte über das PWMmax. Ist aber auch logisch!
Vor der Rechnung frage ich zwar ab, ob T < Tmin aber nicht ob T > Tmax.
Nun läufts!


Die Variablen wurde mit Absicht als unsigned gewählt, da nirgends ein 
negativer Wert vor kommen sollte.

Der Sensor misst bis -30°C, daher wird die Temperatur mit einem Offset 
von 30 verarbeitet: -30°C werden dann als 0 verarbeitet. Positive Werte 
vereinfachen die Umrechnung vom ADC-Wert in die Temperatur und später in 
den PWM-Wert.
Zum Ausgeben verwende ich sowieso selbst geschriebene 
"my_utoa()"-Funktionen, sodass ich diese für den Temperatur-Offset 
angepasst habe.

Nun versuche ich den PWM-Wert direkt über den ADC-Wert zu berechnen, da 
dann die Sprünge von 1K (Kelvin) nicht mehr so groß sind. (5x LSB-ADC = 
1K)

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.