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?
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...
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...
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.
> 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.
> 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
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
@,,,,:
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????
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.
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
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...
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
@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.
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!
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...
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...
Die alte Integer-Regel:
Erst alles multiplizieren und dann dividieren !!!
Was ne Division einmal abgeschnitten hat, das ist weg und kommt nicht
wieder.
Peter
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...
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...
>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?
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
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.
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 ^^
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?
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 ^^
> 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.
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
> 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.
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.
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.