#define rechnet anders als ich es erwarte

Gast #4617661
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;
}
Gast #4617674
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.
#4617809
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.
#4617873
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
Gast #4617893
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. :)
#4618132
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
#4618154
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.
Gast #4618202
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ß

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren