Guten Abend,
ich möchte gerade mein Leben einfacher machen und den Compiler rechnen
lassen. Aber leider rechnet der ganz anders als ich.
Was mache ich falsch?
ich erwarte mir in der Variable test den wert 245 jedoch steht in
Wirklichkeit 0,0002337598 drin!
#define R1 270000.0f // Wiederstandswert1
#define R2 47500.0f // Wiederstandswert2
#define Utarget 5.0f // Versorgung ADC bzw Atmel
#define ADCstep Utarget/1024 //
#define Uschw1 8.0f
#define Ig1 Uschw1/(R1+R2)
#define Uadc1 R2*Ig1
#define _8V ((Uadc1/ADCstep))
double test = _8V
if (voltage < _8V)
{
bla;
}
Mach mal um alle Definitionen eine Klammer!
#define rechnet nicht, sondern ersetzt.
Insbesondere:
#define ADCstep (Utarget/1023)
Btw: Es sind nur 1023 Steps bei 10 Bit.
Gruß
> #define rechnet anders als ich es erwarte
Nein, "#define" rechnet überhaupt nichts. "#define" ersetzt nur den
Text, "#define" weiß nicht, was es da ersetzt.
#define ist böse, man sollte nur Konstanten #definen und die Rechnerei
ganz normal im Programm hinschreiben. Aber selbst dann gibt es
pathologische Fälle, in denen die Klammern nötig sind.
eagle user schrieb:> #define ist böse,
Ja, aber für symbolische Konstanten gibt es in C keine Alternative. Egal
ob berechnet oder nicht. Stroustrup hatte in C++ eben deshalb skalaren
"const" Definitionen abweichend von C die Rolle lexikalischer Konstanten
gegeben. Eine Eigenschaft, die C fehlt.
> man sollte nur Konstanten #definen und die Rechnerei> ganz normal im Programm hinschreiben.
Nein. Symbolische Namen verwendet man, um einen Wert an einer einzigen
Stelle zu definieren und an 1000 Stellen verwenden zu können. Es wäre
absurd, an den 1000 Stellen jeweils die Rechnung hinzuschreiben und
später ändern zu müssen. Es wäre ebenso absurd, statt dessen den
Taschenrechner zu bemühen um den Wert an Stelle einer Rechnung direkt
hinschreiben zu können.
In anderen Sprachen kann man symbolische Konstanten ungefähr so
definieren:
const integer A = B * C;
Das Äquivalent dazu in C ist
#define A ((B)*(C))
Dass man aufgrund des Prinzips der Textersetzung mehr Klammern setzen
muss als in C sonst nötig ist traurig, gehört aber eben zu den Altlasten
von C.
Don schrieb:> Joachim schrieb:>>> Btw: Es sind nur 1023 Steps bei 10 Bit.>> 2^10 sind bei dir 1023?
Steps! Es sind zwar 1024 Werte, aber 1023 Steps! Von 0 auf 1 ist 1 Step.
Von 0 auf 1023 sind 1023 Steps!
Alex W. schrieb:> Don schrieb:>> Joachim schrieb:>>> Btw: Es sind nur 1023 Steps bei 10 Bit.>> 2^10 sind bei dir 1023?> Steps! Es sind zwar 1024 Werte, aber 1023 Steps! Von 0 auf 1 ist 1 Step.> Von 0 auf 1023 sind 1023 Steps!
Genau. Oder einfach Dreisatz:
V_Ref entspricht ADC_Maximalwert (hier 1023).
Gruß
Es sind trotzdem 1024. Auszug vom ATmega48...ATmega328:
"The minimum value represents GND and the maximum value represents the
voltage on the AREF pin minus 1 LSB."
Und so kenne ich es von anderen Wandlern auch.
Das trägt allerdings auch gar nicht zur Lösung seines Problems bei.
Gruß
Jobst
Jobst M. schrieb:> "The minimum value represents GND and the maximum value represents the> voltage on the AREF pin minus 1 LSB."
Jo und was ist das Maximum "minus 1 LSB"? Richtig 1023.
Bei 10 Bit sind es 1024 Abstufungen, da du die Stufe 0 mitzählen musst
sind es 0 bis 1023.
Der Fehler ist mir auch schon paar mal passiert. Merke es häufig wenn
ich den ADC Wert umrechne und mich wundere warum da was nicht ganz so
passt. :)
mr. mo schrieb:> Jo und was ist das Maximum "minus 1 LSB"? Richtig 1023.
Nein. Das Maximum ist 1023.
Einen höheren Wert kannst Du mit 10 Bit nicht darstellen.
Und es soll ja auch nicht vom Wert 1 LSB abgezogen werden, sondern von
Vref.
Und der Wert 1023 entspricht einer Spannung von Vref minus 1 LSB.
Vref ist also 1024 (was maximum + 1 LSB ist)
Du musst also von Vref die Spannung für 1 LSB abziehen und kannst dann
durch Deine 1023 teilen
oder Vref einfach durch 1024 teilen.
mr. mo schrieb:> Der Fehler ist mir auch schon paar mal passiert.
Nein, nun machst Du ihn.
Vielleicht solltest Du mal einen ADC diskret aufbauen, dann weißt Du
auch woher das kommt.
512 ist genau Vref/2, 256 Vref/4, 128 Vref/8, ...
Eingangsspannung darf also nie Vref werden, sondern nur 1023/1024 davon
- oder Vref - 1 LSB.
Ach ja: Auch aus dem Datenblatt:
V IN ⋅ 1024
ADC = -------------
V REF
Gruß
Jobst
Diese alte Diskussion mal wieder...
Der Fehler, der hier immer gemacht wird, ist, dass es hier nicht um
Stufen, sondern um Spannungsbereiche geht. Jeder ADC-Wert entspricht
nicht genau einer Spannung, sondern einem Spannungsbereich. Mal auf 2
Bit reduziert, bei Uref = 1 V:
0 entspricht dem Bereich 0V <= U < 0,25V
1 ensptricht dem Bereich 0,25V <= U < 0,5V
2 ensptricht dem Bereich 0,5V <= U < 0,75V
3 ensptricht dem Bereich 0,75V <= U < 1V
Die aus dem Wert ermittelte gerundete Spannung wäre also
U = (Wert + 0,5) / 4
Das gilt für einen ADC, der nicht selbst schon rundet. Aber auch wenn
der ADC das tut, muss man durch 4 teilen und nicht etwa durch 3 - bei 10
Bit enstprechend durch 1024.