mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ADC Ergebniss auflösen


Autor: blawa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich weis nicht genau wie ich folgendes machen soll:
8 Bit ADC ( 0 - 5 V Input )
diese 0-5V will ich in 200 Teilbereiche zerlegen und das Ergebniss dann
in eine Variable abspeichern...
Mein 8 Bit ADC zerlegt aber diesen Berreich in 255 einzelstücke oder?
Bzw wenn ich dann diese Zerlegung habe, ist das dann eine Integer Zahl
die die Volt angibt?

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nö.
Es ist ein Byte, das nur dir eine Relation zwischen der
Referenzspannung und gemessener Spannung angibt.
Die Zahl in Volt bekommst du durch eine Berechnung:

U = 5V*ADC/255

Wenn du nur noch 200 Teilbereiche haben willst, geht das so:

T = 200*ADC/255

Vielleicht siehst du das System...

Autor: ,,,, (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> U = 5V*ADC/255

Eher so:

U = 5V*ADC/256

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nö. Die Diskussion hatten wir schon zur Genüge.
Wieso sollte ich eine Zahl, die mit maximal 8 Bit dargestellt wird,
durch eine mit 9 Bit teilen (Zahlenraum...)?
Ansonsten ist es egal, ob 255 oder 256, da der Fehler unter 1% liegt...

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Darüber hatten wir schon mal eine Diskussion hier, aber ich kann sie
grad nicht finden.

> Eher so:
>
> U = 5V*ADC/256

Dann bekommst du nie einen Wert von 5V raus, da ADC maximal einen Wert
von 255 haben kann.

Autor: ,,,, (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
8 Bit Auflösung, 256 Möglichkeiten; bei Vref=5V hat das LSB die
Wertigkeit 5V/256. Mit 8 Bit kann man maximal 255*LSB darstellen.

Autor: ,,,, (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wieso sollte ich eine Zahl, die mit maximal 8 Bit dargestellt
> wird, durch eine mit 9 Bit teilen (Zahlenraum...)?

Weil dies die Grundlagen der digitalen Messtechnik sind.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>256 Möglichkeiten

Genau, und eine davon ist 0!

Autor: ,,,, (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Dann bekommst du nie einen Wert von 5V raus, da ADC maximal einen
> Wert von 255 haben kann.

Ein AD-Wandler, dessen Referenz 5V beträgt, kann halt nicht bis 5V
messen.

LOL

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Natürlich kann er das! VREF entspricht dem max. Wandlungsergebnis!

Ansonsten:
1 LSB = VREF / ((2^n)-1) mit n als Anzahl der Bits!
2^8 - 1 = 255

Man hat zwar 256 Zustände, aber der erste ist Null, d.h. es gibt nur
255 Intervalle.

Gruß

Johnny

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@,,,,:
In der Schule nie die berühmte Rechenaufgabe gehabt, wieviele
Zaunpfähle man braucht, um bei einem Pfahl-Abstand von 1 m einen 10 m
langen Zaun zu bauen????

Autor: ,,,, (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Natürlich kann er das! VREF entspricht dem max.
> Wandlungsergebnis!

Diese Aussage ist definitv falsch.

Autor: blawa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich habs jezt folgendermasen Probiert, jedoch funktioniert das
nicht ganz:
void ADC()
{
 ADCON0=0x00;            /* AD-Kanal 0 */
 DAPR=0x00;         /* Bereich 0 V - 5 V */
 while((ADCON0&0x10)!=0);    /* Warten bis Wandlung fertig (15us ) */
 DruckSp1=(5*ADDAT)/255;     /* Umrechnen */
 ADCON0=0x01;                /* AD-Kanal 1 */
 DAPR=0x00;                  /* Bereich 0 V - 5 V */
 while((ADCON0&0x10)!=0);    /* Warten bis Wandlung fertig (15us ) */
 DruckSp2=(5*ADDAT)/255;     /* Umrechnen */
 ADCON0=0x02;                /* AD-Kanal 2 */
 DAPR=0x00;                  /* Bereich 0 V - 5 V */
 while((ADCON0&0x10)!=0);    /* Warten bis Wandlung fertig (15us ) */
 DruckSp2=(5*ADDAT)/255;     /* Umrechnen */
 ADCON0=0x04;                /* AD-Kanal 3 */
 DAPR=0x00;                  /* Bereich 0 V - 5 V */
 while((ADCON0&0x10)!=0);    /* Warten bis Wandlung fertig (15us ) */
 DruckSp2=(5*ADDAT)/255;     /* Umrechnen */
 ADCON0=0x08;                /* AD-Kanal 4 */
 DAPR=0x00;                  /* Bereich 0 V - 5 V */
 while((ADCON0&0x10)!=0);    /* Warten bis Wandlung fertig (15us ) */
 DruckSp2=(5*ADDAT)/255;     /* Umrechnen */
}

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guck dir doch mal die Funktionsweise eines ADC an.
Im Regelfall wird die zu messende Spannung mit einer sich ändernden
Spannung (Rampe) verglichen. Ist die Vergleichsspannung bei einer
steigenden Rampe grösser als die Messspannung, dann hat man den
ADC-Wert.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich meinte die Komma-Ansammlung etc...

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@blawa:
Kommt halt darauf an, wie du DruckSp deklariert hast.
Als integer oder char wird da nur 0-5 rauskommen...

Autor: blawa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich habe es als Integer Deklariert, jedoch krieg ich immer nur 0x00
raus... als was müsste ich es definieren, damit ich meinen Wert kriege?

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Grundsätzlich hängt das alles vom Typ des A/D-Wandlers ab. Die in uCs
verbauten Wandler sind i.a. Successive-Approximation-Wandler und können
z.T. prinzipbedingt tatsächlich nur VREF-1LSB ausgeben (Bei den AVRs ist
das z.B. so). Da blawa jedoch bis zuletzt hartnäckig verschwiegen hat,
was für ein Teil er da eigentlich benutzt, konnte das alles Mögliche
sein... Irgendwo haben halt alle ein bisschen recht! OK, ADCs mit ein-
oder zwei-Rampen-Verfahren werden aufgrund ihrer Langsamkeit nur noch
in Low-Cost-Anwendungen und da wo's nicht auf Speed ankommt
eingesetzt...

Gruß

Johnny

Autor: blawa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok muss mich entschuldigen dass ich das nicht erwähnt g´habe ^^
Es handelt sich um den internen ADC des SAB80C535.... wir sollen einen
Druck von 0-300 Bar messen und ausgeben... dafür werden wir unsere
Spannung des Drucksensors verstärken, damit wir auf einen Berreich von
0-5V kommen...
Jezt würd ich gerne wissen wollen, wie ich es machen kann, dass ich das
Konvertiere um dann den Druck im µC in einer Integervariable stehn zu
haben... wobei wir 2Bar Einheiten verwenden wollen...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist ja net schlimm, hat immerhin zu ner netten Diskussion geführt...

Dass ich mit 8051ern (genau genommen mit nem 80C537) gearbeitet habe
ist schon ne Weile her (stehe eher auf AVR:-), aber ein bisschen ist
noch hängengeblieben...

Was Du mit dem ADCON0-Register machst leuchtet mir nicht ein. Beim
80C537 funktioniert die Kanalwahl mit den drei LSB! Du schreibst aber
00000001, 00000010, 00000100, 00001000... Irgendwie kommt mir das
spanisch vor. Ich glaub, beim 535 müsste das ganz ähnlich laufen wie
beim 537. Außerdem brauchste das DAPR nicht jedes Mal neu zu schreiben.


Was noch viel wichtiger ist: Ich fürchte, Du vergisst einfach, die
Wandlung zu starten (80C537: ADCON0 |= 0x20;).

Probiers mal damit!

Gruß

Johnny

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jonny: Welcher ADC kann denn bis Vref messen?

@Blawa: 0-300 Bar? Bei 300 Bar möchte ich nicht neben dem Drucksensor
stehen...finde ich zumindest ziemlich viel...
Der Drucksensor wird ja irgendeine elektrische Grösse ausspucken.
Mit Hilfe des Datenblattes oder aus einer Messung/Messreihe heraus kann
man dann feststellen, wie groß die Ausgangssgrösse bei welchem Druck
ist.
Dann baut man einen Wandler (Operationsverstärker) auf, der das Signal
entsprechend an 0-5V anpasst.

[alles für die Katz, was ich bis jetzt geschrieben habe...]

Integer haben keine Nachkommastellen...
Du kannst entweder eine Fließkomma-Zahl benutzen (type-casr...), dir
die Formel so umbauen, dass du keine Nachkommastellen brauchst oder
eine Tabelle anlegen, die die auzugebenen Werte enthält.

Autor: blawa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ johnny.m
was bewirkt der Befehl:
>Was noch viel wichtiger ist: Ich fürchte, Du vergisst einfach, die
>Wandlung zu starten (80C537: ADCON0 |= 0x20;).

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der bewirkt, dass das Bit ADEX, das den ADC startet, gesetzt wird. Das
Bit steht beim 80C537 an der Stelle 5, also mit 0x20 (00100000b)
verodern, dann wirds gesetzt. Solange es nicht gesetzt ist, wandelt
auch der ADC nix!

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Rahul:
Hast natürlich recht. Das eine Inkrement bleibt immer übrig. Also
VMESSMAX = VREF-1LSB oder VLSB = VREF/(2^n), also 256 beim
8-Bit-Wandler.

Autor: blawa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm habs jezt folgendermasen probiert, aber auf meinem DSP stehen nur
irgendwelche werte...

void ADC()
{
 P6=0x00;
 ADCON0=0x00;                             /* AD-Kanal 0 */
 DAPR=0x00;                              /* Bereich 0 V - 5 V */
 ADCON0=ADCON0|020;
 while((ADCON0&0x10)!=0);                     /* Warten bis Wandlung 
fertig (15us
) */
 DruckSp1=ADDAT*(11764/10000);                    /* Umrechnen */
 DruckSp11=DruckSp1;
 ADCON0=0x01;                             /* AD-Kanal 1 */
 DAPR=0x00;                            /* Bereich 0 V - 5 V */
 ADCON0=ADCON0|0x20;
 while((ADCON0&0x10)!=0);                     /* Warten bis Wandlung 
fertig (15us
) */
 DruckSp2=ADDAT*(11764/10000);                    /* Umrechnen */
 DruckSp22=DruckSp2;
 ADCON0=0x02;                             /* AD-Kanal 2 */
 DAPR=0x00;                              /* Bereich 0 V - 5 V */
 ADCON0=ADCON0|0x20;
 while((ADCON0&0x10)!=0);                     /* Warten bis Wandlung 
fertig (15us
) */
 DruckSp3=ADDAT*(11764/10000);                    /* Umrechnen */
 DruckSp33=DruckSp3;
 ADCON0=0x03;                             /* AD-Kanal 3 */
 DAPR=0x00;                              /* Bereich 0 V - 5 V */
 ADCON0=ADCON0|0x20;
 while((ADCON0&0x10)!=0);                    /* Warten bis Wandlung 
fertig (15us
) */
 DruckK=ADDAT*(11764/10000);                    /* Umrechnen */
 DruckKK=DruckK;
 ADCON0=0x04;                             /* AD-Kanal 4 */
 DAPR=0x00;                              /* Bereich 0 V - 5 V */
 ADCON0=ADCON0|0x20;
 while((ADCON0&0x10)!=0);                    /* Warten bis Wandlung 
fertig (15us
) */
 DruckFl=ADDAT*(11764/10000);                     /* Umrechnen */
 DruckFll=DruckFl;
}

das 11764/10000 habe ich gschrieben, da ich keine floats verwenden
kann...

und ich will meine 300 bar in 150 teile zerlegen -> ADDAT * 1,1764...
Aber wie gesagt ich bekomme nur irgendwelche werte geliefert, obwohl
ich zu testzwecken nur den Port 6.1 angeschlossen habe...

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guck dir doch die Werte mal ohne Berechnung an. Oder überprüfe die
Funktion des ADC mit einer externen Spannung (einstellbares Netzteil).
Und 11764/10000 ergibt als integer vermutlich 1.
Wenn du 255 mit 11764 multiplizierst, kommt eine Zahl >16bit heraus...

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die alte Integer-Regel:

Erst alles multiplizieren und dann dividieren !!!


Was ne Division einmal abgeschnitten hat, das ist weg und kommt nicht
wieder.


Peter

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rahul hat völlig recht! Lass Dir einfach mal den nackten Wert aus ADDAT
anzeigen. Und Deine Divisiongibt natürlich immer ne 1. Kannste Dir also
eh sparen. Du brauchst auch nach wie vor das DAPR nur einmal am Anfang
zu schreiben. Der Rest sieht eigentlich soweit korrekt aus...

Autor: blawa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok habs mal mit dem ADC Simulator vom Keil ausprobiert und etwas
merkwürdiges festgestellt:
ADDAT hat den richtigen wert
DruckSp1 ist 0x0000 egal bei welcher eingangsspannung
DruckSp11 hat immer irgendeinen Wert...

weis jemand woran das liegt, oder muss ich floats verwenden...
bzw hab auch die klammer versezt...

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>DruckSp1 ist 0x0000 egal bei welcher eingangsspannung
>DruckSp11 hat immer irgendeinen Wert...

mit oder ohne Berechnung?

Dann solltest du dir der Übersichtlichkeit eine Funktion definieren:

integer ADC_mess(integer kanal)
{

 P6=0x00;
 ADCON0=kanal;             /* AD-Kanal */
 DAPR=0x00;               /* Bereich 0 V - 5 V */
 ADCON0=ADCON0|020;
 while((ADCON0&0x10)!=0); /* Warten bis Wandlung fertig (15us) */
 return ADDAT;
}

dann rufst du sie wie folgt auf (Kanal 4 als Beispiel):

DruckF1 = ADC_mess(4);

das Erhöht die Übersichtlichkeit ungemein.

Wenn du jetzt noch irgendwelche Berechnungen anstellen willst, solltest
du immer erst die Multiplikation durchführen, und dann dividieren
(Zahlenraum der ganzen Zahlen...)

Ich kenne den Keil jetzt nicht, aber IMHO gibt es in jedem C-Compiler
"char" bzw. "unsigned char". Das ist nur 8 Bit statt 16 Bit
groß...

Warum willst du den Messbereich eigentlich von 255 auf 150 Werte
verringern?

Autor: blawa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich will den Messbereich auf 150 verringern, da wir von 0-300 bar messen
und 2 bar abstände reichen uns völlig....

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!
Mal ne blöde Frage, kommste nicht besser das Sensorsignal extern zu
teilen? Wenn du das sauber machst ist ein LSB=2Bar und fast die ganze
Rechnerei fällt weg.

MFG Uwe

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie ist es denn jetzt mit den berechneten Werten? Immer noch 0x0000?

Autor: andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Normalerweise ist die Berechnung genauer aber bei 8 Bit sehe ich es auch
so wie Uwe. Schalte vor deinen ADC einen Trimmer und stelle ihn auf 1LSB
= 2Bar.

Autor: blawa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habs gelöst... das Problem war, dass eine normale Integer keine so
hochen Werte speichern kann.... Hab aus der Integer Variable eine
long-Integer gemacht und voila es funzt.... nur hab ich das
Integerproblem, da für ihn 59,998 noch immer 59 ist ^^

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ist 59,998?
Eine floating Point Zahl?
Dann gewoehn Dir bitte an, da einen . zu schreiben.
Ist in der EDV nun mal so. ',' schreiben die
Kaufleute und ev. noch Mathematiker. '.' schreiben
die Informatiker.

Da wirst Du wohl runden muessen anstatt nur einfach die
Nachkommastellen abzuschneiden.
Hinweis: Was passiert wenn Du zu einer Gleitkommazahl
zunaechst mal 0.5 addierst und erst dann die Nachkommastellen
abschneidest?

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bin ich froh, kein Informatiker zu sein...(Bin aber zum Glück auch
keiner der anderen beiden.)

Autor: blawa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja da mir die Vollversion nicht zur verfügung steht, kann ich kein
float verwenden. Ich hatte zwar überlegt, die nachkommastellen mittels
modulo herrauszufinden, aber obs nun 59 oder 60 ist, ist nicht
relevant, dh werd ichs sol lassen wie es ist ^^

Autor: Unbekannter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Dann gewoehn Dir bitte an, da einen . zu schreiben.
> Ist in der EDV nun mal so. ',' schreiben die
> Kaufleute und ev. noch Mathematiker. '.' schreiben
> die Informatiker.

So ein Blödsinn.

In Deutschland wird ein Komma zur Abtrennung der Dezimalstellen
geschrieben und die Ziffern werden in Dreier-Gruppen mit einem kleinem
Abstand dazwischen (bzw. nach DIN 5008 ein ganzer Leerschritt)
geschrieben.

  Also:  1 500 234,234

Das Leerzeichen wird oft weg gelassen, gerade bei vierstelligen
Zahlen.

Auf keinem Fall sollte man ein Punkt zur Gliederung der Dreier-Gruppen
verwenden. Dann ist Chaos vorprogrammiert.

Einfach mal einen Blick in den Duden wagen, oder auch die DIN 5008
anschauen.

Autor: Arno H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Unsitte mit dem Punkt als Dezimalzeichen hat ihren Ursprung auf
einer kleinen unbedeutenden Insel in der westlichen Nordsee. Die
Sprache dieses Volkes hat sich nun mal leider über den Globus
verbreitet.
Da es sich für eine Sprachgruppe von ca 100Mio (Stichwort
Globalisierung) nicht lohnt extra Computerprogramme zu übersetzen,
werden wir damit leben müssen, können das aber durch fehlende Umlaute
gut kompensieren.
Arno

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> In Deutschland wird ein Komma zur Abtrennung der Dezimalstellen
> geschrieben und die Ziffern werden in Dreier-Gruppen mit einem
> kleinem Abstand dazwischen (bzw. nach DIN 5008 ein ganzer
> Leerschritt) geschrieben.

Erklaer das doch bitte mal den internationelen Gremien
die Programmiersprachen normieren.

Autor: Läubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein Programmiersprachensyntax hat doch nichts mit einer "richtigen"
Schreibweise zu tun. (Richtig ist sowieso relativ) du hast aber
behauptet es sei generell falsch mit Komma was faktisch nicht stimmt.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo hab ich behauptet, dass dies falsch waere?
Ich hab ihn lediglich gebeten, sich den ueblichen
Gepflogenheiten zur Schreibweise von Gleitkommazahlen
(im Umfeld von Programmierern, aber das sollte eigentlich
bei so einem Thread implizit vorausgesetzt werden koennen)
anzupassen.

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.