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
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
Kanst du dir alles sparen: Alte C-Regel: gerechne twird mindestens im Datentyp int. Auf dem AVR also mit 16 Bit
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!
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.
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.
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#Datentypen_in_Operationen
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?
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)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.