Forum: Mikrocontroller und Digitale Elektronik ADC auslesen geht nicht richtig!


von Der G. (jonnyk)


Lesenswert?

Hallo leute,

Kann mir jemand beim ADC auslesen helfen?

Ich habe folgendes problem:

Ich habe die funktion aus dem tutorial übernommen.

AREF auf 5 V

wenn ich jetzt einen wert auslese bekomme ich nicht den richtigen z.b. 
bei 2V, sollte er sein (bei 10 bit auflösung) ca.409 ich bekomme aber 
einen 353 beim 2 durchlauf 180 beim 3. 368 usw.
er bleibt nie stabil und stimmt ja auch nicht ganz.

Ich habe keine kondensatoren oder wiederstände in meiner schaltung zum 
stabilisieren, kann das, das problem sein?


bedanke mich im vorraus.

von Fabio S. (codehamster)


Lesenswert?

sag doch bitte um welchen Przessortyp / Familie es sich handelt!
Dann kann man dir weiterhelfen.

Wenn der Wert ungefähr stimmt kannst du auch einen Mittelwert bilden! 
Sprich 10 mal Messen jeweils Addieren und danach durch 10 Teilen. Schon 
hast du dein Wert gemittelt...

von Der G. (jonnyk)


Lesenswert?

ATmega 2560 mit 16 Mhz takt.

von Fabio S. (codehamster)


Lesenswert?

Ein Bit entspricht

Referenzspannung / (2^Auflösung -1)

Somit:

2V bei 10Bit 409.6

Mittelwertbilden kannst du ganz einfach!
Mehrmals messen, Addieren und durch die Anzahl Messungen dividieren. 
Falls dir das was bringt.

von Andreas N. (poolspieler)


Lesenswert?

Hi,
ich kann jetzt nur von einem PIC sprechen:
Hatte da mal das gleiche Problem.
Wenn Du die A/D-Wandlung zu schnell aufeinander machst, bzw. bei 
asynchronem Modus das Ergebnis ausliest, bevor die A/D-Wandlung beendet 
ist --> dann treten evtl. solche Probleme auf.

Weiter Möglichkeiten:
- Falsche Referenzspannung (zu hoch oder zu niedrig --> kenne wie gesagt 
den ATMEGA nicht...)
- Brumm auf dem zu messenden Signal --> miss mal mit nem Oszi
- Brumm auf der Versorgungsspannung --> miss mal mit nem Oszi
- Brumm auf der Referenzspannung --> und nochmal mit Oszi messen ;-)
(Wobei ich bei einem Fehler von 180Digits einen Brumm fast ausschließen 
würde)

Falls KEIN Brumm auf den Leitungen ist, dann würde ich von einer 
Mittelung großen Abstand nehmen. Denn eine Schwankun von 180 Digits ist 
wirklich zu VIEL!!! +-1 Digits solltest Du erreichen...

Als schnellen Test würde ich folgenden pseudocode vorschlagen:

1. A/D-Wandlung machen
2. Ergebnis ausgeben
3. Warte 1000ms
4. zurück zu 1.

Beste Grüße,

Andreas

von Der G. (jonnyk)


Lesenswert?

@ Andreas N.

Hast du recht.

der Test funktioniert eigentlich so wie er sein sollte.

gucke ich mir einfach mal die brumm spannungen an.


aber mal ne andere frage zwieschen durch.

Kann man in c double nicht % 10 rechnen???

ist für die ausgabe der zahlen.

Oder wie kann ich die Zahlen mit komma ausgeben?

von Andreas N. (poolspieler)


Lesenswert?

Hi,
natürlich kann man den Modulo-Operator NICHT auf eine Gleitkommazahl 
anwenden! Der ist nur für ganze Zahlen...
Verstehe aber auch nicht, wo Du % 10 brauchen könntest...?
Poste mal Deinen Code, dann kann Dir vielleicht geholfen werden ;-)

Oder suchst Du sowas:
printf("Meine Gleitkommazahl: %.2f\r\n", _meine_zahl);

Ausgabe für _meine_zahl = 123.4567:
   Meine Gleitkommazahl: 123.46


Gruß,
Andreas

von Der G. (jonnyk)


Lesenswert?

> Oder suchst Du sowas:
> printf("Meine Gleitkommazahl: %.2f\r\n", _meine_zahl);
>
> Ausgabe für _meine_zahl = 123.4567:
>    Meine Gleitkommazahl: 123.46


Genau das brauch ich nur das ich jetzt

sprintf(string,"%.2f",zahl);

das mache in anschliessend sthet im string '?' (63) sonnst nix.

aber im debuger kann ich sehen das ich tatsächlich eine double variable 
übergebe wie z.b. 3.04496 usw.

von Andreas N. (poolspieler)


Lesenswert?

Sorry,
aber das kann ich nicht glauben.
Poste doch mal den ganzen Codeabschnitt inklusive Variablendeklaration.
Es sieht so aus, als ob Du einen falschen Variablentyp übergibst.
Ist "zahl" vielleicht ein Zeiger? Dann müßtest Du "*zahl" schreiben...

Kann Dir aber erst morgen Antworten - muss jetzt weg.

Gruß,
Andreas

von Der G. (jonnyk)


Lesenswert?

Hier wird sie aufgerufen

double Analog_Werte;

//Analog Digital Converter Starten um die aktuellen werte einzulesen.
Analog_Werte = ReadChannel(0);

//U=Vref*adwert/1023
Analog_Werte = (5*Analog_Werte)/1023;

uart_putd_PC(Analog_Werte );

also das ist die funktion:

// ausgabe eines String mit einer double Variable wird für den ADC 
verwendet
char uart_putd_PC( double value )
{
    char *string;

  sprintf(string,"TEST %.2f",value);
  uart_puts_PC( string );

  return(0);
}

als ergebniss kommt dann

"TEST ?"

von Hans J. (hjm)


Lesenswert?

Hallo,

Mittelwertbildung z.B. über 4 Werte:
1
signed short result;
2
unsigned char i;
3
4
result = 0; 
5
for( i=0; i<4; i++ )
6
{
7
  ADCSR |= (1<<ADSC);               // eine Wandlung "single conversion"
8
  while ( ADCSR & (1<<ADSC) ) {;}   // auf Abschluss der Konvertierung warten
9
  result += ADCW;                   // Wandlungsergebnisse aufaddieren
10
}
11
12
result = result >> 2;               // Summe durch vier teilen = Mittelwert


Um eine Zahl mit Komma auszugeben gibts eine schöne C-Funktion, div, mit 
dem Typ dd, der Wert und Rest ausgibt:
1
div_t dd;
2
3
dd = div(wert,10);
4
sprintf(buffer,"%2d,%01d",dd.quot,dd.rem);

Grüße
Hans-Josef

von Der G. (jonnyk)


Lesenswert?

> Um eine Zahl mit Komma auszugeben gibts eine schöne C-Funktion, div, mit
> dem Typ dd, der Wert und Rest ausgibt:
>
1
> div_t dd;
2
> 
3
> dd = div(wert,10);
4
> sprintf(buffer,"%2d,%01d",dd.quot,dd.rem);
5
>
>
> Grüße
> Hans-Josef

wie funktioniert diese Funktion?

Ich habe das jetzt einfach mal so übernommen:-)

und mit folgendem ergebniss:

  div_t dd;
  char *string;

  dd = div(value,10);
  sprintf(string,"%2d,%01d",dd.quot,dd.rem);

  //sprintf(string,"TEST %.2f",value);
  uart_puts_PC( string );

value ist ein double.
jetzt mekert der Compiler dass ich 2 integer an div übergeben soll.
und als ergebniss kommt auch nix.
Hans-Josef könntest du es mir vieleicht näher erklären?

von Der G. (jonnyk)


Lesenswert?

So wie ich es im gefühl habe ist es kommplet was anderes ich möchte 
nicht eine zahl mit komma ausgeben sondern ein komma zahl möchte ich 
ausgeben.

von Hans J. (hjm)


Lesenswert?

Hey,

die Funktion div arbeitet mit int's und nicht mit double.

Brauchst Du denn double?

Ich hatte Dir die Funktion gezeigt, da man damit im Prg nicht mit 
double, sondern mit int's arbeiten kann. Schneller und kürzer.

Normalerweise brauchst Du es ja nur als Anzeige und da arbeitet dann die 
Funktion wie beschrieben.

Wenn Du also einen AD-Wert (0..1024 entspricht 0..5V) mit einer 
Nachkommastelle ausgeben möchtest,  dann z.B. so:
1
div_t dd;
2
int temp;
3
4
temp = AD_Wert * 50;       // 5V*10 für Nachkommstelle
5
temp >>=10;                // auf richtigen Wert bringen teilen durch 1024
6
7
dd = div(temp,10);
8
sprintf(buffer,"%1d,%01d",dd.quot,dd.rem);

So bekommst Du dann die Spannung als X.X ausgegeben

Grüße
Hans-Josef

von Bernhard M. (boregard)


Lesenswert?

Der Grosse wrote:
> char uart_putd_PC( double value )
> {
>     char *string;
>
>   sprintf(string,"TEST %.2f",value);
>   uart_puts_PC( string );
>
>   return(0);
> }
>
> als ergebniss kommt dann
>
> "TEST ?"

Das kann ja nicht gehen, denn "string" wird ja nicht initialisiert und 
zeigt dann irgendwohin...
Also besser z.B.:
1
char uart_putd_PC( double value )
2
{
3
  char string[8];
4
5
  sprintf(string,"TEST %.2f",value);
6
  uart_puts_PC( string );
7
8
  return(0);
9
}

von Der G. (jonnyk)


Lesenswert?

Also ich weiss nicht was ich da tuhe. >> Nicht gut...

also

ich bekomme ein wert vom adc. sagen wir mal 512
damit habe ich eine spannung von 2.5V

so dann rechne ich das mal 50 ergibt 25600 ne

dann teile ich durch 1024 ergibt 25

damit bekomme ich dann den wert 2.5 angezeigt.

richtig?

soweit zur theorie.

wieso funktioniert es dann nicht in der Praxis???

hier der code:


SR (TIMER1_OVF_vect)
{
  div_t dd;
  int temp;
  int AD_Wert;

  SREG &= ~(1<<WDIF);  //Globale interrupts sperren

//Analog Digital Converter Starten um die aktuellen werte einzulesen.
  AD_Wert = ReadChannel(0);

  temp =   AD_Wert*50;

  temp = (temp)/1023;// auf richtigen Wert bringen teilen durch1024

  dd = div(temp,10);

  sprintf(buffer,"\n%1d,%01d\n",dd.quot,dd.rem);

  uart_puts_PC(buffer);

  TCNT1H = 0x00;
  TCNT1L = 0x00;

  SREG |= (1<<WDIF);  //Globale interrupts erlauben

}

von Der G. (jonnyk)


Lesenswert?

Und hier noch mal das auslesen des ADC´s
1
uint16_t ReadChannel(uint8_t mux)
2
{
3
  uint8_t i;
4
  uint16_t result;
5
 
6
  ADMUX = mux;                      // Kanal waehlen
7
  ADMUX &= ~(1<<REFS1) | (1<<REFS0); // externe Referenzspannung nutzen, interne aus
8
 
9
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0);    // Frequenzvorteiler 
10
                               // setzen auf 32 (1) und ADC aktivieren (1)
11
 
12
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
13
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
14
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
15
  while ( ADCSRA & (1<<ADSC) ) {
16
     ;     // auf Abschluss der Konvertierung warten 
17
  }
18
  result = ADCW;  // ADCW muss einmal gelesen werden,
19
                  // sonst wird Ergebnis der nächsten Wandlung
20
                  // nicht übernommen.
21
 
22
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
23
  result = 0; 
24
  for( i=0; i<4; i++ )
25
  {
26
   ADCSRA |= (1<<ADSC);               // eine Wandlung "single conversion"
27
   while ( ADCSRA & (1<<ADSC) ) {;}   // auf Abschluss der Konvertierung warten
28
   result += ADCW;                   // Wandlungsergebnisse aufaddieren
29
  }
30
31
  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)
32
 
33
  result = result >> 2;                     // Summe durch vier teilen = arithm. Mittelwert
34
 
35
  return result;
36
}

von Der G. (jonnyk)


Lesenswert?

ich bekomme z.b. für 2.5 V  z.b. den wert

225

346

9

398

188

371

350

und so weiter halt alles was falsch ist.

aber nie den richtigen wert.

von FL (Gast)


Lesenswert?

Ist int auf dem AVR ein 16 Bit-Typ?

Dann hast Du mit
1
temp =   AD_Wert*50;
wenn AD_Wert > 655 ist einen Überlauf, und das Ergebnis wird nicht zu 
gebrauchen sein...

von Der G. (jonnyk)


Lesenswert?

änderung auf

uint16_t temp;
uint16_t AD_Wert;

hat leider nicht zu gewünschten erfolg gebracht.

von Andreas N. (poolspieler)


Lesenswert?

Hi,
folgender Code von Dir kann nicht funktionieren:
1
char uart_putd_PC( double value )
2
{
3
    char *string; // das ist nur ein ZEIGER - es wird dafür KEIN Speicher reserviert...!!! Und jede Ausgabe ist Zufall. Jede Zuweisung kann zum Systemabsturz führen!
4
5
  sprintf(string,"TEST %.2f",value);
6
  uart_puts_PC( string );
7
8
  return(0);
9
}

es muss heißen:
1
char uart_putd_PC( double value )
2
{
3
    char string{50]; // Korrektes ARRAY of char
4
5
  sprintf(string,"TEST %.2f",value);
6
  uart_puts_PC( string );
7
8
  return(0);
9
}

Und schon wird es funktionieren... ;-)

Gruß,
Andreas

von Hans J. (hjm)


Lesenswert?

Hallo,

den Werten nach zu urteilen liegt das Problem woanders.

Probier einmal den interene Referenz (am besten mit ext. Kondensator):
1
ADCSR = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);  // ADC enable, Teiler = 64
2
ADMUX = (1<<REFS1) | (1<<REFS0);    // interne Referenzspannung nutzen mit ext. Kondensator

Dies würde ich auch nur bei der Init machen und nicht bei jeder Messung.
Dann die Messung mit:
1
/*************************************************************************
2
 Function: GET ADC
3
 Purpose:  
4
**************************************************************************/
5
signed short Get_ADC(char channel)
6
{
7
signed short result;
8
unsigned char i;
9
10
ADMUX = channel | (1<<REFS1) | (1<<REFS0);      // Kanal waehlen
11
12
result = 0; 
13
for( i=0; i<4; i++ )
14
{
15
  ADCSR |= (1<<ADSC);              // eine Wandlung "single conversion"
16
  while ( ADCSR & (1<<ADSC) ) {;}  // auf Abschluss der Konvertierung warten
17
  result += ADCW;       // Wandlungsergebnisse aufaddieren
18
}
19
20
result = result >> 2;              // Summe durch vier teilen = arithm. Mittelwert
21
22
return result;
23
}

Grüße
Hans-Josef

von Der G. (jonnyk)


Lesenswert?

ALSO Leute ich bedanke mich hezlich...

es funktioniert.

Ich hätte euch die schltung geben sollen dann wüsstet ihr sofort was los 
ist.

ich habe für die messung eine externe spannung verwendet. ABER keine 
massen verbunden oder sonnst was.

Jetzt habe ich alles von der Spannungsversorgung des MC genommen und es 
ist alles stabil und läuft!!! super hää..

hier jetzt der funktionierende code der vom adc einliest und auf eine 
stelle genau ausgibt.

1
//Initialisierung:
2
3
//Analog digital converter aktivieren
4
 
5
ADMUX = (0); // Kanal waehlen
6
ADMUX &= ~(1<<REFS1) | (1<<REFS0); // externe Referenzspannung nutzen, interne aus
7
 
8
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0);    // Frequenzvorteiler 
9
                               // setzen auf 32 (1) und ADC aktivieren (1)
10
11
12
//Das aufrufen uber einen Timer interrupt:
13
14
ISR (TIMER1_OVF_vect)
15
{
16
  div_t dd;
17
  uint16_t temp;
18
  uint16_t AD_Wert;  
19
20
  SREG &= ~(1<<WDIF);  //Globale interrupts sperren
21
22
  //Analog Digital Converter Starten um die aktuellen werte einzulesen.
23
  AD_Wert = ReadChannel(0);
24
25
  temp =   AD_Wert*50;  
26
27
  temp = (temp)/1023;                // auf richtigen Wert bringen teilen durch 1024
28
29
  dd = div(temp,10);
30
31
  sprintf(buffer,"\n%1d,%01d\n",dd.quot,dd.rem);
32
    
33
  uart_puts_PC(buffer);
34
35
36
  TCNT1H = 0x00;
37
  TCNT1L = 0x00;
38
  
39
  SREG |= (1<<WDIF);  //Globale interrupts erlauben
40
    
41
}
42
43
44
//Die funktion zum einlesen der spannung:
45
46
uint16_t ReadChannel(uint8_t mux)
47
{
48
  uint8_t i;
49
  uint16_t result;
50
51
    ADCSRA |= (1<<ADEN);    //ADC aktivieren (1)
52
 
53
    /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
54
    also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
55
    ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
56
    while ( ADCSRA & (1<<ADSC) );     // auf Abschluss der Konvertierung warten 
57
    result = ADCW;  // ADCW muss einmal gelesen werden,
58
                    // sonst wird Ergebnis der nächsten Wandlung
59
                    // nicht übernommen.
60
61
    /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
62
    result = 0; 
63
    for( i=0; i<4; i++ )
64
    {
65
     ADCSRA |= (1<<ADSC);               // eine Wandlung "single conversion"
66
     while ( ADCSRA & (1<<ADSC) ) {;}   // auf Abschluss der Konvertierung warten
67
     result += ADCW;                   // Wandlungsergebnisse aufaddieren
68
    }
69
70
    ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)
71
 
72
    result = result/4;                     // Summe durch vier teilen = arithm. Mittelwert
73
 
74
    return result;
75
}
Danke an alle freue mich dass mir geholfen wurde werde mit sicherheit 
versuchen auch anderen zu helfen... :-))

von Johannes M. (johnny-m)


Lesenswert?

1
temp = (temp)/1023;          // auf richtigen Wert bringen teilen durch 1024
Und warum teilst Du hier durch 1023 und nicht durch 1024 (wie es 
korrekt im Kommentar steht)? Zumal Du dem Programm damit keinen Gefallen 
tust. Eine Division durch 1023 ist signifikant aufwändiger als eine 
durch 1024 (abgesehen davon, dass 1024 in diesem Fall der einzig 
richtige Divisor ist)!

von Der G. (jonnyk)


Lesenswert?

weil ich es im kommentar leider vergessen habe zu ändern...
Die auflösung ist ja 1023 und nich 1024 ;-)

von Johannes M. (johnny-m)


Lesenswert?

Der Grosse wrote:
> weil ich es im kommentar leider vergessen habe zu ändern...
> Die auflösung ist ja 1023 und nich 1024 ;-)
Nein! Die Referenzspannung wird in 1024 gleiche Teile unterteilt, 
nicht in 1023! Ausgegeben werden kann zwar nur 1023, das ändert aber 
nichts daran, dass der Gesamtbereich 1024 Intervalle hat. Ein ADC 
"verliert" prinzipbedingt ein LSB und gibt für Werte, die größer als 
VREF-1LSB sind, den Maximalwert aus. Schau Dir mal die Funktionsweise 
eines solchen ADC an und vertraue auch mal den Formeln im Datenblatt.

von Der G. (jonnyk)


Lesenswert?

Ja gut ist richtig. ändert im endeffeckt nichts am ergebniss. Es 
verfälscht den wert an der 3 stelle nach´m komma, aber so genau muss es 
jetzt auch nicht sein.

von Johannes M. (johnny-m)


Lesenswert?

Der Grosse wrote:
> Ja gut ist richtig. ändert im endeffeckt nichts am ergebniss.
Es macht aber das Programm schneller (und u.U. auch kürzer), siehe oben! 
Ob das in Deinem Fall eine Rolle spielt, musst Du selbst wissen.

Abgesehen davon heißt es "Effekt" ohne "c" und "Ergebnis" mit einem 
"s"...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Macht doch die Mittelwertbildung über einen gleitenden Mittelwert 
(Tiefpass). Das ist wesentlich kompakter... ;-)
1
uint16_t ReadChannel(uint8_t mux)
2
{
3
    #define FILTERLAENGE 4
4
    static uint16_t summe;
5
6
    ADCSRA |= (1<<ADEN);    //ADC aktivieren (1)
7
 
8
    /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
9
    also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
10
    ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
11
    while ( ADCSRA & (1<<ADSC) );     // auf Abschluss der Konvertierung        
12
13
    /* dann "richtiger" Readout */
14
    ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
15
    while ( ADCSRA & (1<<ADSC) );     // auf Abschluss der Konvertierung warten 
16
17
    /* Filter */
18
    summe -= summe/FILTERLAENGE ;      // einen alten Wert aus der Summe heraus nehmen
19
    summe += ADCW;                    // neuen Wert dazuaddieren
20
    return summe/FILTERLAENGE ;       
21
}

von Der G. (jonnyk)


Lesenswert?

@ Lothar Miller

aha diese lösung sieht sehr elegant aus.
schaue ich mir mal eben an..

2 min später...

Es ist zwar eine gutte lösung es dauert aber wesentlich länger bis man 
die richtige spannung berechnet hat. Wenn sie sich also schnell ändert 
merkt man es halt nicht sofort.

Kann ich den nicht einfach 1 einzige messung machen ohne 4 messungen 
durchzuführen, oder wird das ergebnis falsch?


Danke...

@Johannes M.

>Abgesehen davon heißt es "Effekt" ohne "c" und "Ergebnis" mit einem
>"s"...

na, wer will den da schlau wirken... :-)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Wenn sie sich also schnell ändert merkt man es halt nicht sofort.
Sowas nennt man Tiefpass ;-)

> Kann ich den nicht einfach 1 einzige messung machen...
Das ist der übliche Weg, du bist nur gleich am Anfang dieses Freds auf 
falsche Pfade gelockt worden im 
Beitrag "Re: ADC auslesen geht nicht richtig!".
Frei nach dem Motto: rechne dir einen schönen Wert her...

> Ein ADC "verliert" prinzipbedingt ein LSB und gibt für Werte,
> die größer als VREF-1LSB sind, den Maximalwert aus.
Ist das nicht etwas extrem,
allen ADCs einfach so eine Schlamperei zu unterstellen ;-)

Für alle, die jetzt erschrocken nach dem verlorenen Bit suchen:
es ist die Null.

Ein 10-Bit Wandler kann 1024 Spannungs-Bereiche auflösen:
0    =     0            bis     <1*Vref/1024
1    =     1*Vref/1024  bis     <2*Vref/1024
2    =     2*Vref/1024  bis     <3*Vref/1024
3    =     3*Vref/1024  bis     <4*Vref/1024
4    =     4*Vref/1024  bis     <5*Vref/1024
:
:
1021 =  1021*Vref/1024  bis  <1022*Vref/1024
1022 =  1022*Vref/1024  bis  <1023*Vref/1024
1023 =  1023*Vref/1024  bis  <Vref

Wenn irgendwo im Zusammenhang mit AD-Wandlern eine Zahl
mit 2^n-1 (n=8....24) also 255, 511, 1023, 2047... auftaucht,
ist dort idR. irgendwas faul.

von Johannes M. (johnny-m)


Lesenswert?

Lothar Miller wrote:
> Für alle, die jetzt erschrocken nach dem verlorenen Bit suchen:
> es ist die Null.
Naja, eigentlich eher die Tatsache, dass ein ausgegebener Wert eben 
nicht einen konkreten Spannungswert bezeichnet, sondern ein Intervall 
zwischen zwei Spannungswerten. Und da ein "größer als Vref" nunmal nicht 
auswertbar ist, kann man eben am oberen Ende nur sagen "Der 
Spannungswert am Eingang ist größer als Vref - 1 LSB".

> Ein 10-Bit Wandler kann 1024 Spannungs-Bereiche auflösen:
Genau.

> [...]
> 1023 =  1023*Vref/1024  bis  <Vref
Naja, das letzte "<" würde ich weglassen. Auch Spannungen, die größer 
als Vref sind, ergeben 1023 als Ausgangswert. Man kann eben keine 
konkrete Aussage über dieses letzte Intervall treffen, außer dass die 
Spannung größer als Vref - 1 LSB ist. Es gibt dort keine obere Grenze 
mehr.

von Der G. (jonnyk)


Lesenswert?

Jetzt sehe ich einiges klarer...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Es gibt dort keine obere Grenze mehr.
Gilt (abhängig vom Wandler) üblicherweise auch für die untere Grenze bei 
unipolaren Wandlern. Ein Wert kleiner 0 wird als 0 ausgegeben.

Formal richtig wäre dann die erste Zeile mit
0    =          bis    <1*Vref/1024

von Johannes M. (johnny-m)


Lesenswert?

Lothar Miller wrote:
> Gilt (abhängig vom Wandler) üblicherweise auch für die untere Grenze bei
> unipolaren Wandlern. Ein Wert kleiner 0 wird als 0 ausgegeben.
>
> Formal richtig wäre dann die erste Zeile mit
> 0    =          bis    <1*Vref/1024
Rüchtüch. Die erste Zeile war mir grad nicht so aufgefallen.

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.