Hallo zusammen,
ich möchte einen festen Strom mittels #define vorgeben.
Da das ganze über einem Stromfühle und dem ADC gemessen wird, kommen
eben Wert wie 0x01BC raus oder so. Nun mächte ich den Strom in mA
vorgeben, z.B. 800mA (also zb #define strom 800)
Das ganze müsste ja dann umgerechnet werden wie folgt:
[(800mA / 1000 * R) * 1024 ] / Uref = ADC-vergleichswert.
Wie gebe ich das jetzt in ein define, dass es funzt?
Ich hätte eigentlich so gedacht:
Aber irgendwie nimmt das der Compiler nicht an.
Was mache ich falsch? Geht das überhaupt so wie ich mir des vorstelle?
Achja, ich arbeite mit dem AVR-Studio.
Gruß
Daniel
Was heißt "der Compiler nimmt das nicht an"? Fehlermeldung?
Wenn der Compiler es schlucken würde, käme aber auch nicht raus, was Du
vermutlich willst. Grundsätzlich werden alle Berechnungen zunächst in
int durchgeführt, wenn nicht explizit etwas anderes angegeben ist bzw.
wenn einer der beteiligten Operatoren nicht in int darstellbar ist.
Bei Dir fängt es aber schon mit
1
(strom/1000)
an:
strom hat den Wert 800 -> passt in int
1000 passt auch in int
Also gibt das eine Integer-Division, und wieviel 800/1000 in int ist,
solltest Du vielleicht mal als ersten Schritt überlegen...
Weiter geht's mit R , das bei Dir mit 0.5 definiert ist. Wenn er das
R sieht, wird er also ab diesem Punkt in Gleitkomma weiterrechnen
(weil das der größte Datentyp ist, der in dem Ausdruck vorkommt). Das
Ergebnis der ganzen Geschichte ist also ein float und führt (wenn die
restlichen Unzulänglichkeiten in der Rechnung beseitigt sind) zur
Einbindung der Gleitkommabibliotheken, sobald der Wert irgendwo im
Programm verwendet wird. Und das dürfte ziemlich sinnfrei sein. Gerade
für eine popelige Multiplikation mit 0,5 ist das nicht sinnvoll. Die
kann man eigentlich immer in Ganzzahlen machen.
Hm, ob der Präpozessor auch rekursive Definitionen übersetzt, bin ich
mir nicht wirklich sicher, wo mault der Compiler denn? Ich tippe auf die
letzte Zeile. Eventuell solltest du die Rechnung nicht in das Define,
sondern dorthin schreiben, wo du den Wert nachher verwenden willst, das
sollte tun.
Aber zwei andere Sachen:
> #define vergleichswert ((strom/1000) * R) *1024) / Uref
So ein Konstrukt ist prinzipiell gefährlich. Wenn du irgendwelche
Rechnungen in ein Define packst, dann immer eine zusätzliche Klammer
drum. Sonst kann es lustige Effekte geben. Beispiel:
#define WERT (5 * 2) + 10
int zahl = WERT * 10
-> Hier ersetzt der Präprozessor stur den "WERT" durch "(5 * 2) + 10",
durch die verschiedenen Prioritäten der Operatoren (Punkt vor Strich...)
wird das Ergebnis vermutlich nicht das erwartete sein.
Und zu letzt: Wenn man alle Definitionen in GROSSBUCHSTABEN schreibt,
hat man etwas mehr Übersicht, ob man mit einer Variable oder einem
"ersetzten Wert" rechnet.
Peter
Peter wrote:
> Hm, ob der Präpozessor auch rekursive Definitionen übersetzt, bin ich> mir nicht wirklich sicher, ...
Klar macht er das. Sonst würde von heute auf morgen die Welt stehen
bleiben. ;-) Das heißt, wirklich rekursive natürlich nicht (du
kannst also nicht FOO definieren und dann in der Definition FOO
benutzen), aber geschachtelte Definitionen (andere Makros innerhalb
der Definition eines Makros auflösen) sehr wohl.
> Klar macht er das. Sonst würde von heute auf morgen> die Welt stehen bleiben. ;-)
Da war mir doch tatsächlich eine weltbewegende Möglichkeit völlig
unbekannt ;-) Aber man lernt ja gern dazu, danke für die Aufklärung.
Zur Antwort von Johannes M.:
Also wenn man Float-Arithemetik vermeiden will, würde man vermutlich die
Rechenoperationen so vertauschen, dass man die Multiplikationen zuerst
ausführt (soweit vom Wertebereich möglich) und erst als letztes eine
(Integer)-Division (durch das Produkt aller Divisoren) durchführt. So
sollte doch lediglich ein Rundungsfehler von +-1 entstehen. Natürlich
dürfen dann keine Float-Werte verwendet werden, aber das sollte sich ja
durch Kommaverschiebung lösen lassen. Oder steckt da noch ein Denkfehler
drin?
Peter
Peter wrote:
> Oder steckt da noch ein Denkfehler> drin?
Wie schon gesagt, ich vermute erstens, dass der OP eigentlich gar keine
floats verwenden will und zweitens eben nicht bedenkt, dass 800/1000
nunmal immer 0 ist...
>Wie schon gesagt, ich vermute erstens, dass der OP eigentlich gar keine>floats verwenden will und zweitens eben nicht bedenkt, dass 800/1000>nunmal immer 0 ist...
Sicher alles richtig was du da sagst. Solange alles konstante
Werte sind kann man ja ruhig den Compiler (nicht den uC)
in float rechnen lassen. Anschliessend macht man ein int draus.
#define strom 800.0
#define R 0.5
#define Uref 5.0
#define vergleichswert ((unsigned int)(((strom/1000.0) * R) *1024.0) /
Uref))
Passendes auf/abrunden noch nicht integriert.
Spricht irgend was dagegen?
#define vergleichswert ((strom/1000) * R) *1024) / Uref
=> Da fehlt ganz einfach eine Klammer! Richtig, bzw. besser wäre:
#define vergleichswert ((((strom/1000) * R) *1024) / Uref)
Der Complier macht dann automatisch einen int draus, falls Du das
Resultat einem int zuweist.
>#define vergleichswert ((((strom/1000) * R) *1024) / Uref)>Der Complier macht dann automatisch einen int draus, falls Du das>Resultat einem int zuweist.
strom/1000 ist und bleibt dann aber immer noch Null
bei integer Rechnung.
Eine eigene Frage?
Dieser Thread ist über 18 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.