Moin,
ich habe dieser Tage ein einfaches Thermostat gebaut mit einem Atmega88
und nem DS18B20.
Das Thermostat hat eine Hysterese damit das Aggregat nicht zu oft
anspringen muss.
Als Parameter habe ich eine Konstante deklariert und einen Wert
zugewiesen:
1
constuint32_thysterese=(15*60*1000);//Hysterese in ms
Beim Trockentest ging noch alles, da habe ich den Wert auf 10000
gesetzt, aber bei Verwendung obiger Zeile kam offenbar ein Wert raus,
der nicht 900000 Betrug, da nie geschalten wurde.
Ich benutze als IDE Visual Studio Code mit Platformio und dem Arduino
Framework.
Für Konstanten habe ich sonst immer Makros bzw. einfache
Präprozessoranweisungen genutzt, aber ich dachte mir wenn man eine
Konstante deklariert, dann weiß man wenigstens genau, was die für einen
Typ hat, das ist am Ende transparenter und sicherer.
Meine Frage ist jetzt, wieso hat die Zuweisung so nicht funktioniert?
Ich würde das gerne verstehen.
Der Compiler rechnet mit int, wenn man ihm bei numerischen Konstanten
nichts anderes mitteilt. Auf Deinem AVR-Arduino ist int ein
16-Bit-Datentyp.
Ändere Deine Initialisierung mal zu
1
constuint32_thysterese=(15*60*1000L);//Hysterese in ms
(Das Suffix L weist den Compiler an, mit long zu rechnen. Analog gibt
es auch das Suffix UL, das hat unsigned long zur Folge).
... und wenn Du die Compiler-Warnungen eingeschaltet hättest (etwas, was
man immer machen sollte, -Wall, mindestens), hätte dir der Compiler
hier eine Warnung bezüglich des Integer-Overflows ausgeworfen.
DerEinzigeBernd schrieb:> Der Compiler rechnet mit int, wenn man ihm bei numerischen> Konstanten> nichts anderes mitteilt. Auf Deinem AVR-Arduino ist int ein> 16-Bit-Datentyp.>> Ändere Deine Initialisierung mal zu> const uint32_t hysterese = (15 60 1000L); //Hysterese in ms>> (Das Suffix L weist den Compiler an, mit long zu rechnen. Analog gibt> es auch das Suffix UL, das hat unsigned long zur Folge).
Ah, ok. Also damit hab ich nicht gerechnet. Klar dass ein int beim
Atmega 16-bit hat, aber ich ging davon aus, dass der Compiler das
ohnehin zur Compilezeit berechnet und dabei, entsprechend der CPU
Architektur des PCs, mit 32-bit rechnet.
Alles klar, wieder was gelernt.
Markus F. schrieb:> ... und wenn Du die Compiler-Warnungen eingeschaltet hättest (etwas, was> man immer machen sollte, -Wall, mindestens), hätte dir der Compiler> hier eine Warnung bezüglich des Integer-Overflows ausgeworfen.
Mann muss die Warnungen auch beachten und deren Ursache beheben.
(-Wall ist nicht die Ursache)
Yves E. schrieb:> //Hysterese in ms
Mal eine ganz andere Frage:
Wie kommst du auf eine Hysterese in Zeiteinheiten?
Das Ganze soll ja wohl ein Thermostat werden, also wäre da eine
Hysterese in Temperatureinheiten angesagt.
W.S.
Yves E. schrieb:> aber ich ging davon aus, dass der Compiler das> ohnehin zur Compilezeit berechnet und dabei, entsprechend der CPU> Architektur des PCs, mit 32-bit rechnet.
Warum sollte der Compiler die Architektur des PC (heute üblicherweise
64-bit) berücksichtigen, wenn doch für ein ganz anderes Target, hier
AVR, compiliert wird?
Wenn Du etwas von Sprache X nach Sprache Y übersetzen sollst, spielt es
für Dich doch auch keine Rolle, in welchem Land du dich befindest.
constuint32_thysterese=(15*60*1000);//Hysterese in ms
>> Ich benutze als IDE Visual Studio Code mit Platformio und dem Arduino> Framework.
Weil Du Arduino benutzt, benutz Du also C++ ...
> Für Konstanten habe ich sonst immer Makros bzw. einfache> Präprozessoranweisungen genutzt, aber ich dachte mir wenn man eine> Konstante deklariert, dann weiß man wenigstens genau, was die für einen> Typ hat, das ist am Ende transparenter und sicherer.
CPP-Macros kannst Du bei C++ immer vermeiden (weil sie Mist sind).
Mache
1
constexpruint32_thysterese=(15*60*1000);//Hysterese in ms
draus, und Du bekommst auch einen Fehler.
Und schalte in Zukunft Deine Warnungen ein (mindestens -Wall -Wextra
...).
> Meine Frage ist jetzt, wieso hat die Zuweisung so nicht funktioniert?
Es ist keine Zuweisung!
Den Unterschied zwischen Zuweisung und Initialisierung ist etwas, was
man ganz am Anfang des Lernens von C++ verstehen sollte / muss!
Alles klar, danke für die zahlreichen Antworten.
W.S. schrieb:> Yves E. schrieb:>> //Hysterese in ms>> Mal eine ganz andere Frage:> Wie kommst du auf eine Hysterese in Zeiteinheiten?> Das Ganze soll ja wohl ein Thermostat werden, also wäre da eine> Hysterese in Temperatureinheiten angesagt.>> W.S.
Weil sich diese Hysterese auf die Schalthäufigkeit bezieht und nicht auf
die Temperatur. Das System, das gekühlt werden soll ist recht träge, da
spielt es keine Rolle, wenn höchstens alle 15 Min. etwas am
Schaltzustand geändert werden kann. Die Temperaturabweichungen sind
überschaubar und das Aggregat wird so nicht sinnlos strapaziert.
Kaj schrieb:> Warum sollte der Compiler die Architektur des PC (heute üblicherweise> 64-bit) berücksichtigen, wenn doch für ein ganz anderes Target, hier> AVR, compiliert wird?> Wenn Du etwas von Sprache X nach Sprache Y übersetzen sollst, spielt es> für Dich doch auch keine Rolle, in welchem Land du dich befindest.
Schon klar, aber Compiler optimieren ja auch ne Menge Dinge weg, von
daher ging ich davon aus, da es sich hier um eine Konstante handelt,
würde der Compiler aus dieser Initialisierung einfach eine Zuweisung
machen.
So dass am Ende einfach:
1
constuint32_thysterese=900000;
daraus wird.
Wie ja nun hinreichend geklärt wurde, war das eine falsche Annahme.
Markus F. schrieb:> ... und wenn Du die Compiler-Warnungen eingeschaltet hättest (etwas, was> man immer machen sollte, -Wall, mindestens), hätte dir der Compiler> hier eine Warnung bezüglich des Integer-Overflows ausgeworfen.
Es geht um Arduino. Das unterdrückt defaultmäßig alle Warnungen, weil
sowas für die Arduino-Zielgruppe als zu kompliziert angesehen wird…
Yves E. schrieb:> Klar dass ein int beim> Atmega 16-bit hat, aber ich ging davon aus, dass der Compiler das> ohnehin zur Compilezeit berechnet und dabei, entsprechend der CPU> Architektur des PCs, mit 32-bit rechnet.
Es wird zur Compilezeit berechnet, allerdings nach genau den selben
Regeln wie eine Berechnung zur Laufzeit. Man will ja nicht, dass ein und
die selbe Berechnung zur Compilezeit ein anderes Ergebnis hat als wenn
sie zur Laufzeit durchgeführt worden wäre.
Yves E. schrieb:> Schon klar, aber Compiler optimieren ja auch ne Menge Dinge weg, von> daher ging ich davon aus, da es sich hier um eine Konstante handelt,> würde der Compiler aus dieser Initialisierung einfach eine Zuweisung> machen.> So dass am Ende einfach:> const uint32_t hysterese = 900000;>> daraus wird.
Das ist nach wie vor keine Zuweisung, sondern eine Initialisierung.
Korrekterweise solltest Du
1
constuint32_thysterese=900000UL;
schreiben, denn 900000 ist kein int, und Du willst eine
unsigned-Variable damit initialisieren.
Léo schrieb:> Korrekterweise solltest Du> const uint32_t hysterese = 900000UL;>> schreiben, denn 900000 ist kein int, und Du willst eine> unsigned-Variable damit initialisieren.
Noch besser:
Johann L. schrieb:> Wenn man den Initwert von Hand ausrechnet, gibt's ja kein Problem mehr> weil 900000 long ist, 15*60*1000 jedich int. Also wenn schon, dann>>