mikrocontroller.net

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


Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Fabio S. (codehamster)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ATmega 2560 mit 16 Mhz takt.

Autor: Fabio S. (codehamster)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andreas N. (poolspieler)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Andreas N. (poolspieler)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andreas N. (poolspieler)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht 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 ?"

Autor: Hans Josef (hjm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Mittelwertbildung z.B. über 4 Werte:
signed short result;
unsigned char i;

result = 0; 
for( i=0; i<4; i++ )
{
  ADCSR |= (1<<ADSC);               // eine Wandlung "single conversion"
  while ( ADCSR & (1<<ADSC) ) {;}   // auf Abschluss der Konvertierung warten
  result += ADCW;                   // Wandlungsergebnisse aufaddieren
}

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:
div_t dd;

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

Grüße
Hans-Josef

Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Um eine Zahl mit Komma auszugeben gibts eine schöne C-Funktion, div, mit
> dem Typ dd, der Wert und Rest ausgibt:
>
> div_t dd;
> 
> dd = div(wert,10);
> sprintf(buffer,"%2d,%01d",dd.quot,dd.rem);
> 
>
> 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?

Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hans Josef (hjm)
Datum:

Bewertung
0 lesenswert
nicht 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:
div_t dd;
int temp;

temp = AD_Wert * 50;       // 5V*10 für Nachkommstelle
temp >>=10;                // auf richtigen Wert bringen teilen durch 1024

dd = div(temp,10);
sprintf(buffer,"%1d,%01d",dd.quot,dd.rem);


So bekommst Du dann die Spannung als X.X ausgegeben

Grüße
Hans-Josef

Autor: Bernhard M. (boregard)
Datum:

Bewertung
0 lesenswert
nicht 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.:
char uart_putd_PC( double value )
{
  char string[8];

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

  return(0);
}


Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht 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

}

Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und hier noch mal das auslesen des ADC´s
uint16_t ReadChannel(uint8_t mux)
{
  uint8_t i;
  uint16_t result;
 
  ADMUX = mux;                      // Kanal waehlen
  ADMUX &= ~(1<<REFS1) | (1<<REFS0); // externe Referenzspannung nutzen, interne aus
 
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0);    // Frequenzvorteiler 
                               // setzen auf 32 (1) und ADC aktivieren (1)
 
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
  while ( ADCSRA & (1<<ADSC) ) {
     ;     // auf Abschluss der Konvertierung warten 
  }
  result = ADCW;  // ADCW muss einmal gelesen werden,
                  // sonst wird Ergebnis der nächsten Wandlung
                  // nicht übernommen.
 
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
  result = 0; 
  for( i=0; i<4; i++ )
  {
   ADCSRA |= (1<<ADSC);               // eine Wandlung "single conversion"
   while ( ADCSRA & (1<<ADSC) ) {;}   // auf Abschluss der Konvertierung warten
   result += ADCW;                   // Wandlungsergebnisse aufaddieren
  }

  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)
 
  result = result >> 2;                     // Summe durch vier teilen = arithm. Mittelwert
 
  return result;
}

Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: FL (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist int auf dem AVR ein 16 Bit-Typ?

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

Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
änderung auf

uint16_t temp;
uint16_t AD_Wert;

hat leider nicht zu gewünschten erfolg gebracht.

Autor: Andreas N. (poolspieler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
folgender Code von Dir kann nicht funktionieren:
char uart_putd_PC( double value )
{
    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!

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

  return(0);
}


es muss heißen:
char uart_putd_PC( double value )
{
    char string{50]; // Korrektes ARRAY of char

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

  return(0);
}


Und schon wird es funktionieren... ;-)

Gruß,
Andreas

Autor: Hans Josef (hjm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

den Werten nach zu urteilen liegt das Problem woanders.

Probier einmal den interene Referenz (am besten mit ext. Kondensator):
ADCSR = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);  // ADC enable, Teiler = 64
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:
/*************************************************************************
 Function: GET ADC
 Purpose:  
**************************************************************************/
signed short Get_ADC(char channel)
{
signed short result;
unsigned char i;

ADMUX = channel | (1<<REFS1) | (1<<REFS0);      // Kanal waehlen

result = 0; 
for( i=0; i<4; i++ )
{
  ADCSR |= (1<<ADSC);              // eine Wandlung "single conversion"
  while ( ADCSR & (1<<ADSC) ) {;}  // auf Abschluss der Konvertierung warten
  result += ADCW;       // Wandlungsergebnisse aufaddieren
}

result = result >> 2;              // Summe durch vier teilen = arithm. Mittelwert

return result;
}

Grüße
Hans-Josef

Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht 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.


//Initialisierung:

//Analog digital converter aktivieren
 
ADMUX = (0); // Kanal waehlen
ADMUX &= ~(1<<REFS1) | (1<<REFS0); // externe Referenzspannung nutzen, interne aus
 
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0);    // Frequenzvorteiler 
                               // setzen auf 32 (1) und ADC aktivieren (1)


//Das aufrufen uber einen Timer interrupt:

ISR (TIMER1_OVF_vect)
{
  div_t dd;
  uint16_t temp;
  uint16_t 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 durch 1024

  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
    
}


//Die funktion zum einlesen der spannung:

uint16_t ReadChannel(uint8_t mux)
{
  uint8_t i;
  uint16_t result;

    ADCSRA |= (1<<ADEN);    //ADC aktivieren (1)
 
    /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
    also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
    ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
    while ( ADCSRA & (1<<ADSC) );     // auf Abschluss der Konvertierung warten 
    result = ADCW;  // ADCW muss einmal gelesen werden,
                    // sonst wird Ergebnis der nächsten Wandlung
                    // nicht übernommen.

    /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
    result = 0; 
    for( i=0; i<4; i++ )
    {
     ADCSRA |= (1<<ADSC);               // eine Wandlung "single conversion"
     while ( ADCSRA & (1<<ADSC) ) {;}   // auf Abschluss der Konvertierung warten
     result += ADCW;                   // Wandlungsergebnisse aufaddieren
    }

    ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)
 
    result = result/4;                     // Summe durch vier teilen = arithm. Mittelwert
 
    return result;
}



Danke an alle freue mich dass mir geholfen wurde werde mit sicherheit 
versuchen auch anderen zu helfen... :-))

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)!

Autor: Der Grosse (jonnyk)
Datum:

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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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"...

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Macht doch die Mittelwertbildung über einen gleitenden Mittelwert 
(Tiefpass). Das ist wesentlich kompakter... ;-)
uint16_t ReadChannel(uint8_t mux)
{
    #define FILTERLAENGE 4
    static uint16_t summe;

    ADCSRA |= (1<<ADEN);    //ADC aktivieren (1)
 
    /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
    also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
    ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
    while ( ADCSRA & (1<<ADSC) );     // auf Abschluss der Konvertierung        

    /* dann "richtiger" Readout */
    ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
    while ( ADCSRA & (1<<ADSC) );     // auf Abschluss der Konvertierung warten 

    /* Filter */
    summe -= summe/FILTERLAENGE ;      // einen alten Wert aus der Summe heraus nehmen
    summe += ADCW;                    // neuen Wert dazuaddieren
    return summe/FILTERLAENGE ;       
}

Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht 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... :-)

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Der Grosse (jonnyk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt sehe ich einiges klarer...

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.