Forum: Mikrocontroller und Digitale Elektronik #define rechnet anders als ich es erwarte


von pi_user (Gast)


Lesenswert?

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;
}

von Joachim (Gast)


Lesenswert?

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ß

von Tom (Gast)


Lesenswert?

Der Preprozessor macht das daraus:
1
double test = ((47500.0f*8.0f/(270000.0f +47500.0f)/5.0f/1024));
Wo die Klammer fehlt, findest Du bestimmt selbst heraus ;)

Wenn man schon defines benutzen muss, immer alles klammern.

von Lars (Gast)


Lesenswert?

pi_user schrieb im Beitrag #4617657:
> #define    ADCstep    Utarget/1024  //


Mach da mal Klammern drum.

von pi_user (Gast)


Lesenswert?

Danke!

Wenn man es so stehen sieht dann ist es auch logisch!!!!

Danke

von Experte (Gast)


Lesenswert?

> #define rechnet anders als ich es erwarte

Nein, "#define" rechnet überhaupt nichts. "#define" ersetzt nur den 
Text, "#define" weiß nicht, was es da ersetzt.

von eagle user (Gast)


Lesenswert?

#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.

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Don (Gast)


Lesenswert?

Joachim schrieb:

> Btw: Es sind nur 1023 Steps bei 10 Bit.

2^10 sind bei dir 1023?

von Alex W. (a20q90)


Lesenswert?

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!

von Joachim (Gast)


Lesenswert?

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ß

von Jobst M. (jobstens-de)


Lesenswert?

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

: Bearbeitet durch User
von mr. mo (Gast)


Lesenswert?

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. :)

von jau (Gast)


Lesenswert?

mr. mo schrieb:
> Bei 10 Bit sind es 1024 Abstufungen, da du die Stufe 0 mitzählen musst
> sind es 0 bis 1023.

Hauptsache du hast was geschrieben.

von Jobst M. (jobstens-de)


Lesenswert?

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

von Rolf M. (rmagnus)


Lesenswert?

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.

: Bearbeitet durch User
von Joachim (Gast)


Lesenswert?

Hier bspw. wird auch auf die 1023/1024-Problematik eingegangen:

http://www.st.com/content/ccc/resource/technical/document/application_note/9d/56/66/74/4e/97/48/93/CD00004444.pdf/files/CD00004444.pdf/jcr:content/translations/en.CD00004444.pdf

Seite 12-13

Jobst M. schrieb:
> 512 ist genau Vref/2, 256 Vref/4, 128 Vref/8, ...

Zitat Seite 4:

The SAR starts by forcing the MSB (Most Significant bit) high (for 
example in an 8 bit ADC it becomes 1000 0000), the DAC converts it to V
AREF/2. The analog comparator compares the input voltage with VAREF/2. 
If the input voltage is greater than the voltage corresponding to the
MSB, the bit is left set, otherwise it is reset.

Das heißt doch, wenn exakt Vref/2 anliegt, dann wird das MSB auf 0 
gesetzt, weil nicht größer.

Gruß

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Jobst M. schrieb:
> Nein. Das Maximum ist 1023.

 LOL, soviele Worte um nichts.

 Werte insgesammt = 2^n
 Maximaler Wert   = 2^n - 1

 Und das wars dann.

von Rolf M. (rmagnus)


Lesenswert?

Mit wenigen Worten nichts zu sagen, ist auch nicht wirklich besser, als 
mit vielen Worten nichts zu sagen.

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
Noch kein Account? Hier anmelden.