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.
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.
> 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????
> Natürlich kann er das! VREF entspricht dem max. > Wandlungsergebnis! Diese Aussage ist definitv falsch.
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 */ }
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.
@blawa: Kommt halt darauf an, wie du DruckSp deklariert hast. Als integer oder char wird da nur 0-5 rauskommen...
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?
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.
@ johnny.m was bewirkt der Befehl: >Was noch viel wichtiger ist: Ich fürchte, Du vergisst einfach, die >Wandlung zu starten (80C537: ADCON0 |= 0x20;).
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!
@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.
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?
Ich will den Messbereich auf 150 verringern, da wir von 0-300 bar messen und 2 bar abstände reichen uns völlig....
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?
Bin ich froh, kein Informatiker zu sein...(Bin aber zum Glück auch keiner der anderen beiden.)
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.