Hallo! habe nun meinen ADC zum Laufen gebracht. Das Problem ist jetzt, dass er mir anstatt einem vernünftigen Ergebnis (z.B. 3,5V) lediglich die ASCII-Zeichen ausgibt. Das ist der Code: uint8_t lese_Temperatur(void) { ADMUX = 0xE0; ADCSRA = 0x85; //4MHz:32; uint8_t x=0; //Start conversion ADCSRA |= (1<<ADSC); // wait until converstion completed while (ADCSRA & _BV(ADSC) ) {} // get converted value x = ADCH; // output the higher 8 bits return x; } Mir ist klar, dass da noch keine Umwandlung von uint8_t zu float gemacht wird. Nur wie kann ich das realisieren?! Habe schon versucht, die Tausender-, Hunderter-, Zehner- und Einerstellen separat zu berechnen, er gibt aber trotzdem nichts Vernünftiges aus. Mein Controller: ATmega16 Umgebung: AVR Studio 4 + WinAVR Display mit HD44780-Controller im 4bit Modus. Wäre cool, wenn mir der Eine oder Andere von euch helfen könnte.... Gruß der Praktikant
> ...lediglich die ASCII-Zeichen ausgibt.
Dann solltest Du Dich fragen, wo er irgendwelche ASCII-Zeichen hernimmt.
In dem geposteten Codeschnipsel (Ich glaub ich hab heute schon mal in
einem anderen Thread gefragt, warum zum Geier immer nur nichtssagende
Fragmente geschickt werden und keine einigermaßen vollständigen
Programme...) ist jedenfalls nichts in Sachen ASCII drin...
Wenn Du den Wert auf dem Display darstellen willst, musst Du ihn
zunächst mal umrechnen. Anschließend kann er dann in einen ASCII-String
umgewandelt und aufs Display gerotzt werden...
>uint8_t lese_Temperatur(void) es heisst: "lies_Temperatur"! >anstatt einem vernünftigen Ergebnis Den Dativ ist dem Genitiv sein Tod. >Wäre cool, wenn mir der Eine oder Andere von euch helfen könnte.... Noch cooler wäre es, wenn du dein komplettes Programm posten würdest. Was willst du ausgeben? Spannungen? Den ADC-Wert? In welchen Zahlen-Darstellung?
Während Rahul wieder mit der Puppe spielt und Johnny sich am Boden windet: In der Zwischenzeit, soll sich der Original-Poster mal das hier durchlesen: http://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F
Ohne groß mit Floatwerten rechnen zu müssen wären DIV und MODULO deine Freunde. Mit dem DIV könntest du schonmal ganz einfach die Vorkommastelle berechnen. Das mal als kleinen Denkanstoß..
>Während Rahul wieder mit der Puppe spielt >und Johnny sich am Boden windet: LOL
so, hier ist das vollständige programm.....obwohl das nicht viel mehr ist als der codeschnipsel von vorhin g
>ADC_einlesen_LCD_ausgeben.zip
Wieso ziped man eine Text-Datei?
Rahul, der Trollige wrote: >>ADC_einlesen_LCD_ausgeben.zip > > Wieso ziped man eine Text-Datei? Weil es ein ganzes Projekt des AVR Studio 4 ist....
Der Artikel mit der Ausgabe is ja auch sehr clever in der Artikelsammlung untergebracht. Wer kommt denn schon bei FAQ auf LDC/UART Ausgabe.
Um wenigstens den ADC-Wert als solches auszugeben, ist der Artikel durchaus ne Hilfe, aber eine Umrechnung wirst du nicht vermeiden können. Es sei denn du verzichtest auf ein gewisses Maß an Genauigkeit und legst ne Tabelle an und vergleichst den aktuellen Wert mit den Einträgen in der Tabelle. Dann kann man relativ einfach mit nem switch..case die entsprechenden Strings ausgeben. Aber die Umrechnung finde ich persönlich eleganter.
@Steffen Spielt überhaupt keine Rolle. Wer sowas fragen muss, der durchsucht weder das Forum noch die Artikelsammlung. Nein, der frägt einfach. Selbst wenn dieses Thema in einem anderen Posting 20 Sekunden vorher abgearbeitet wurde und der Postingtitel schon schreit: 'lies mich, lies mich'. Selbst wenn man auf der Hauptseite in grossen roten Buchstaben eine Anleitung für sprintf, ito oder eine händische Lösung schreiben würde, würde genau diese Frage noch immer mindestens 20 mal die Woche auftauchen. Du musst schon froh sein, wenn einer das Tutorial alleine findet.
>Du musst schon froh sein, wenn einer das Tutorial >alleine findet. ... oder nicht direkt in die Codesammlung postet ;-)
@KHB So schlimm?? kann ich mir gar nich vorstellen, ich such auch immer erst ne runde durch die Codesammlung und µElektronik bevor ich anscheinend doofe Fragen stelle. Manche wollens einfach aufm Silbertablett serviert bekommen andere suchen erstmal so isses halt.
>würde genau diese Frage noch immer mindestens 20 mal die Woche auftauchen. Das liegt ja nun leider auch daran, dass die ADCs der AVR sich völlig von einander unterscheiden, Display keinem Standard gehorchen und C sowieso völlig unterschiedlich ist. Ausserdem sind solche Probleme ja auch nie gleich...Es muß doch eine bessere Lösung geben, als die Standard-Lösung (oder doch mit t? ;-), irgendwer hat die bestimmt schon, rückt sie aber nicht raus - vielleicht wird sie mir ja erzählt, wenn ich "Hilfe!" oder "Geht nicht!" in die Betreffzeile schreibe, oder nur Codefragmente poste... Irgendwie bin ich heute etwas genervt...
>bevor ich anscheinend doofe Fragen stelle
Dafür gehe ich lieber in den Chat. Da kann man dann auch noch so
"rumblödeln"...
So, gut, jetzt weiß ich wenigstens, wie das mit der Umrechnung geht....nicht wirlich kompliziert. Nur hab ich jetzt das Problem, wenn ich mit: sprintf( Buffer, "%d", x ); //x ist das ADC-Wandlungsergebnis lcd_puts( Buffer ); die Daten an das LCD sende und die Zahl wieder kleiner wird, die letzte Ziffer trotzdem stehen bleibt. Wenn also mal 120 angezeigt wurde und ich zurück auf z.B. 77 drehe steht dann nachher 770 auf dem LCD.... Versuche ich das zu umgehen, indem ich eine for-Schleife als Warteschleife mißbrauche, dann die Stellen mit Leerzeichen überschreibe und anschließend das richtige Ergebnis darüberschreibe, das LCD flackert.... Code der Warteschleife: lcd_gotoxy(0,1); lese_Temperatur(); for(i=0; i<1500; i++){}; lcd_gotoxy(0,1); lcd_puts(" "); Das gesamte Projekt ist im Anhang!
Dann gib im sprintf-Aufruf eine minimale Ausgabebreite für x an
1 | sprintf( Buffer, "%3d", x ); |
Dann werden immer drei Stellen ausgegeben. Ich würde aber für sowas nicht sprintf nehmen, weil ich i.d.R. mit meinen Speicherressourcen ein wenig haushalte. Nimm lieber die Transformationsfunktionen aus der stdlib.h (in diesem Falle itoa)...
Rahul, der Trollige wrote: >>würde genau diese Frage noch immer mindestens 20 mal die Woche auftauchen. > Das liegt ja nun leider auch daran, dass die ADCs der AVR sich völlig > von einander unterscheiden, Display keinem Standard gehorchen und C > sowieso völlig unterschiedlich ist. Ausserdem sind solche Probleme ja > auch nie gleich...Es muß doch eine bessere Lösung geben, als die > Standard-Lösung (oder doch mit t? ;-), irgendwer hat die bestimmt schon, > rückt sie aber nicht raus - vielleicht wird sie mir ja erzählt, wenn ich > "Hilfe!" oder "Geht nicht!" in die Betreffzeile schreibe, oder nur > Codefragmente poste... > Irgendwie bin ich heute etwas genervt... Hm.....dann schau doch gar nicht mehr rein in den Thread? Anscheinend ist deine Neugier doch recht groß......
>Anscheinend ist deine Neugier doch recht groß......
Manchmal habe ich auch einfach nur einen Drang zum Masochismus...
johnny.m wrote: > Dann gib im sprintf-Aufruf eine minimale Ausgabebreite für x an >
1 | > sprintf( Buffer, "%3d", x ); |
2 | >
|
> Dann werden immer drei Stellen ausgegeben. Ich würde aber für sowas > nicht sprintf nehmen, weil ich i.d.R. mit meinen Speicherressourcen ein > wenig haushalte. Nimm lieber die Transformationsfunktionen aus der > stdlib.h (in diesem Falle itoa)... Okay, danke! Das war die Lösung die ich gesucht habe.... die itoa() habe ich gerade ausprobiert....da ist das gleiche Problem, dass die letzten Nulen stehen bleiben und das Ergebnis verfälschen....
Naja ne UMRECHNUNG ists ja nicht gerade... Das Flackern liegt wohl an den zu häufigen Updates auf dem Display. 1500 Cycles @ 4MHz sind in etwa 0,4µs. Wenn der C-Compiler schlecht optimiert sinds bestimmt aber immer noch nur 1-2µs. Der AD-Wandler schafft auch einige Tausend Wandlungen pro Sekunde. D.h. das Display wird so oft, wie die Display-Routinen es zulassen geupdatet. (Ich schätze mal so einige 100mal pro Sekunde - vielleicht n bischen oft) Denk mal über nen Timer nach. Ich denke mal mehr als 1-2 Messwerte pro Sekunde kann man eh nicht sinnvoll mit Augen und Verstand erfassen.
>0,4µs
Dürften eher 0,4ms sein... (1500/4MHz = 375µs =~ 0,4ms)
> die itoa() habe ich gerade ausprobiert....da ist das gleiche Problem, > dass die letzten Nulen stehen bleiben und das Ergebnis verfälschen.... Das ist richtig, weil itoa keinen Ausgabebreite-Parameter hat. Aber es ist doch nicht so schwer, den String entsprechend zu manipulieren, dass die Breite immer stimmt. Und itoa ist wesentlich ressourcenschonender.
und der code tut nüscht.... gibt ne warning aus: double format, float arg (arg3); Und auf dem Display steht an der Stelle, an der normalerweise meine Zahl ausgegeben wird, ein Fragezeichen! Ich kapiers einfach nicht....wo liegt da der Hund begraben?!
Tja, der letzte funktionierende Code ist 28.7 KB, der neue 28.8 KB. Was wurde geändert?
Werner wrote: > Tja, der letzte funktionierende Code ist 28.7 KB, der neue 28.8 KB. Was > wurde geändert? Dass ich beim 2. eine float-Zahl auf dem Display ausgeben wollte.... Aber sprintf() nimmt keine floats?!?! Code, der nicht tut: #include <avr\io.h> uint8_t lese_Temperatur(); void berechnen_VStrom(); float lese_Absolutdruck(void); float lese_Differenzdruck(void); int main (void) { while(1) { lese_Temperatur(); } } void lese_Temperatur(void) { ADMUX = 0xE0; ADCSRA = 0x85; //4MHz:32; int x=0; double a=0.0; char Buffer[20]; //Start conversion ADCSRA |= (1<<ADSC); // wait until converstion completed while (ADCSRA & _BV(ADSC) ) {} //get converted value x = ADCH; a=7.4; sprintf(Buffer, "%5.2f", a); x = x + 1.0 ; //Dummy-Zeile um Breakpoint zu setzen. //return x; }
> Dass ich beim 2. eine float-Zahl auf dem Display ausgeben wollte.... > Aber sprintf() nimmt keine floats?!?! Alles klar. Das Problem ist, dass der WinAvr die Floating Point Version der xprintf() Funktionen nicht einbindet. Da musst du deine Linkersettings umstellen. Such mal im gcc Forum nach 'printf float' Beitrag "ATmega16, WinAVR und float"
Es ist aber doch richtig, wenn ich Dezimalzahlen mit Komma ausgeben möchte, dass ich dann wohl den Datentyp float nicht umgehen kann....zumindest sagen mir das meine C-Kenntnisse..... Oder sollte ich falsch liegen?! Gruß der Praktikant
@Philip Kottmann >Es ist aber doch richtig, wenn ich Dezimalzahlen mit Komma ausgeben >möchte, dass ich dann wohl den Datentyp float nicht umgehen >kann....zumindest sagen mir das meine C-Kenntnisse..... Oder sollte ich >falsch liegen?! Du liegst falsch. Man kann auch wunderbar mit Integer/Festkomma arbeiten. Z.B. nimmt man ein long (32 Bit) und verwendet die oberen 16 Bit für den Ganzzahl-Anteil und die unteren 16 Bit für die Nachkommastellen. MFG Falk
Du liegst falsch. Nur weil am Display ein Komma auftaucht, heist das noch lange nicht, dass da Gleitkommzahlen im Spiel sind. Es heist nur, dass irgendeine Ausgaberoutine ein Komma hingepinselt hat. Wenn du 2487 Meter als Kilometer ausgeben möchtest, kannst du so vorgehen. 2487 / 1000 macht 2. Also sind das schon mal 2 ganze Kilometer. Danach pinselst du ein Komma aufs Display Und dann noch den Nachkommaanteil: 2487 % 1000 macht 487 Das auch noch hingepinselt, und schon steht am Display 2,487 % ist der Restoperator. Also: Wenn man 2487 durch 1000 ganzzahlig dividiert, wieviel Rest bleibt dann. Pass aber beim Ausgeben auf. Beim Nachkommaanteile dürfen führende Nullen nicht wegfallen. 2,05 ist was anderes als 2,5
Hier ist nun meine Version der Berechnung des Spannungswertes. Eigentlich sollte er die versch. Deszimalstellen korekt berechnen, gibt aber auf dem Display immer nur 0,000 aus. Was stimmt bei der Übergabe der versch. Werte nicht? Vielen Dank für eure Hilfe der Praktikant
>ADC_einlesen_LCD_ausgeben.zip
Kannst du hier nicht vielleicht einfach nur das .c-File anhängen?
Ich will nicht dein ganzen Projekt haben...
Rahul, der Trollige wrote: >>ADC_einlesen_LCD_ausgeben.zip > > Kannst du hier nicht vielleicht einfach nur das .c-File anhängen? > Ich will nicht dein ganzen Projekt haben... Okay, wenn ich das .c-File anhänge motzt gleich der nächste, warum ich denn nur code-fetzen poste....deshalb gibts alles...........
>Okay, wenn ich das .c-File anhänge motzt gleich der nächste, warum ich >denn nur code-fetzen poste....deshalb gibts alles........... Dann bin ich raus...
>auf dem Display immer nur 0,000 >x = ADCH; > faktor = 196; //19,6mV * 10 > ausgangswert = x*10; //x um eine Null erweitert... > > vorkomma = ausgangswert / 100000; > zehntel = (ausgangswert%100000)/10000; > hundertstel = (zehntel%10000)/1000; > tausendstel = (hundertstel%1000)/100; >x = ADCH; x ist eine Zahl zwischen 0 und 255 >ausgangswert = x*10; ausgangswert ist eine Zahl zwischen 0 und 2550 >vorkomma = ausgangswert / 100000; größte Zahl ausgangswert 2550 vorkomma= 2550 / 100000= 0 bei Integer >zehntel = (ausgangswert%100000)/10000; 2550%100000=2550 <-was soll das, das ist sinnlos x%100000=x für x<100000 2550/10000 gibt immer noch 0 für integer ich denke den Rest kannst du selbst nachvollziehen... Ein C-Compiler macht das was du sagst, nicht das was du denkst (gesagt zu haben) Wenn du einen Algorithmus entwirfst, sollte er als erstes auf dem Papier funktionieren. Anscheinend versuchst du diesen Schritt zu überspringen. Das funktioniert nicht! Das zeigst du hier hervorrragend. Du hast kein Problem bei der Übergabe, du hast ein Problem mit der Mathematik. Dies verhinderst du, wenn du den Algorithmus erstmal auf dem Papier entwirfst und überprüfst. Die folgende Verwendung von sprintf ist extrem umständlich. Das Lesen eines C- Buches ist durch kein Forum zu ersetzen.
Hallo Wolfram! Hab selbst bemerkt, dass in meiner Rechnung der eine der andere Fehler versteckt war.... Mein aktuelles .c-File mit der Rechnung ist im Anhang.... Es gibt aber leider bis auf das "," nichts vernünftiges aus. habe die Libraries von Peter Fleury benutzt (zwecks lcd_puts, etc).....
Hast du mal einen Wert in "ausgabewert" geschrieben, ohne den ADC zu benutzen und dann ausgegeben?
ja, so! gibt nur "||" aus....... aber die Verwendung von lcd_puts() und lcd_putc() ist doch in meinem Fall schon richtig?!
Mach das mal so (für alle "buffer"): buffer[4] = (ausgangswert/10000) + '0';
Und wenn ich es wie in der Anlage direkt in main() einbinde gibt er "5" aus...
Hab jetzt einmal für alle "buffer" das ganze so geschreiben: buffer[4] = (ausgangswert/10000) + '0'; buffer[3] = (ausgangswert/10000) + '0'; buffer[2] = (ausgangswert/10000) + '0'; buffer[1] = (ausgangswert/10000) + '0'; buffer[0] = (ausgangswert/10000) + '0'; und nochmal so, wie in der Anlage. Beides hat nicht wirklich zu einem Ergebnis geführt.....
>buffer[4] = (ausgangswert/10000) + '0'; >buffer[3] = (ausgangswert/10000) + '0'; >buffer[2] = (ausgangswert/10000) + '0'; >buffer[1] = (ausgangswert/10000) + '0'; >buffer[0] = (ausgangswert/10000) + '0'; Denkst du auch mit? So gehört das: buffer[4] = (ausgangswert/10000) + '0'; buffer[3] = ','; buffer[2] = ((ausgangswert%10000)/1000) + '0'; buffer[1] = ((buffer[2]%1000)/100) + '0'; buffer[0] = ((buffer[1]%100)/10) + '0';
hast du in die anlage geschaut? da ist das so! mir erschien das auch schwachsinnig. aber ich hab alle möglichkeiten durchgemacht...
>ausgabewert = '45';
Da gibt es das kleine Problem, dass '' einen Char einschliessen und ""
einen String...
Sowas schon probiert:
buffer[4] = '0';
buffer[3] = ',';
buffer[2] = '0';
buffer[1] = '4';
buffer[0] = '5';
(Nein, ich habe mir nicht alle Postings dieses Thread angeguckt!)
okay, wenn ich das einbinde und über lcd_putc(buffer[1]) versuche die '4' auszugeben, dann tut er das.....
also so sieht meine funktion jetzt aus: void lese_Temperatur(void) { ADMUX = 0xE0; ADCSRA = 0x85; //4MHz:32; long int x_h=0, x_l=0, faktor=0, ausgangswert=0; char buffer[20]; //Start conversion ADCSRA |= (1<<ADSC); // wait until converstion completed while (ADCSRA & _BV(ADSC) ) {} //get converted value x_h = ADCH; x_l = ADCL; faktor = 196; //19,6mV * 10 ausgangswert = faktor * x_h; //faktor * x_h; /*buffer[4] = '0'; buffer[3] = ','; buffer[2] = '0'; buffer[1] = '4'; buffer[0] = '5';*/ buffer[4] = (ausgangswert/10000) + '0'; buffer[3] = ','; buffer[2] = ((ausgangswert%10000)/1000) + '0'; buffer[1] = ((buffer[2]%1000)/100) + '0'; buffer[0] = ((buffer[1]%100)/10) + '0'; lcd_putc(buffer); } Ich multipliziere den Wert zw. 0 und 255 (wert x_h) mit dem Faktor von 196. dann versuche ich, die zahl die dabei rauskommt interpretierbar zu gestalten. Also 1 Zahl vor dem Komma, die anderen dahinter. und über die ausgabe lcd_putc(buffer) müsste doch der gesamte buffer auf einmal ausgspuckt werden. oder muss ich nach jeder ausgabe eines buffer-feldes eine stelle weiterspringen mit lcd_gotoxy() und dort dann das nächste ergebnis hineinschreiben?!
>dann tut er das.....
Fehler in der Berechnung, oder?
Für sowas baue ich mir dann eine "manuelle" Division:
verglwert = 10000;
i=0;
while (verglwert>10)
{
buffer[i]='0';
while(ausgabewert>=verglwert)
{
buffer[i]++;
ausgabewert -= verglwert;
}
i++;
verglwert /=10;
}
lcd_putc(buffer[0]);
lcd_putc(',');
lcd_putc(buffer[1]);
lcd_putc(buffer[2]);
lcd_putc(buffer[3]);
> buffer[1] = ((buffer[2]%1000)/100) + '0'; > buffer[0] = ((buffer[1]%100)/10) + '0'; Was soll das "buffer[x]" da in der Rechnung? Da müsste doch wohl "ausgangswert%1000" usw. stehen...
>über die ausgabe lcd_putc(buffer) müsste doch der gesamte buffer auf >einmal ausgspuckt werden. Nein, lcd_putc() schreibt nur ein Zeichen aufs Display. Wenn, dann musst du lcd_puts() benutzen und "buffer" vermutlich um ein Zeichen verlängern ('\0'), damit lcd_puts() das Ende des Trings erkennt.
>über die ausgabe lcd_putc(buffer) müsste doch der gesamte buffer auf >einmal ausgspuckt werden putc ist gewöhnlich zur Ausgabe eines char (eines Zeichens)
Mir gibt irgendwie zu denken, dass meine Variable "faktor" und "ausgangswert" als "unsigned long int" definiert sind. Nach der Umrechnng sollen sie aber in einem Feld von "char" stehen..... kannd as unktionieren?! Irgendwohin müssen ja die 24 Bit Differenz verschwinden?!?!
Das macht der Compiler durch einen "cast" ganz von alleine.
1 | void lese_Temperatur(void) |
2 | {
|
3 | ADMUX = 0xE0; |
4 | ADCSRA = 0x85; //4MHz:32; |
5 | |
6 | long int x_h=0, x_l=0, faktor=0, ausgangswert=0; |
7 | char buffer[20]; |
8 | |
9 | |
10 | //Start conversion
|
11 | ADCSRA |= (1<<ADSC); |
12 | |
13 | // wait until converstion completed
|
14 | while (ADCSRA & _BV(ADSC) ) {} |
15 | |
16 | //get converted value
|
17 | x_h = ADCH; |
18 | x_l = ADCL; |
19 | |
20 | faktor = 196; //19,6mV * 10 |
21 | ausgangswert = faktor * x_h; //faktor * x_h; |
22 | |
23 | sprintf( buffer, "%ld,%04ld", ausgangswert / 10000, ausgangswert % 10000 ); |
24 | lcd_puts( buffer ); |
25 | }
|
sprintf ist natürlich eine teure Funktion. Wenn du den Platz im AVR hast, spielt das keine Rolle. Ansonsten müsste man dafür einen gleichwertigen Ersatz schreiben. lcd_putc .... gibt ein einzelnes Zeichen aus lcd_puts .... gibt einen String aus, also eine Abfolge von Zeichen, die mit '\0' abgeschlossen ist. Ich hab auch nicht kontrolliert ob der ADC Code sinnvoll ist, sprich: ob in x_h überhaupt was Sinnvolles steht. Wenn der Code jetzt immer noch 0,0000 hinschreibt, dann liegt es an deinem ADC Abfrage Code.
> Ich hab auch nicht kontrolliert ob der ADC Code sinnvoll ist, > sprich: ob in x_h überhaupt was Sinnvolles steht. Wenn der > Code jetzt immer noch 0,0000 hinschreibt, dann liegt es an > deinem ADC Abfrage Code. der ADC gibt auf jeden fall was sinnvolles aus. Das hab ich auch abgefragt. die werte bewegen sich so, wie sie sollen zwischen 0 und 255. also das passt, da bin ich mir sicher.....
so siehts aus. er zeigt mir sofort nach dem einschalten den richtigen spannungswert an.... aber wenn ich die spannung verändere, dann tut sich nix. schalte ich ihn wieder aus und wieder ein steht der richtige spannungswert da.... funktioniert also, aber nicht "online".....
> er zeigt mir sofort nach dem einschalten den richtigen spannungswert > an.... Das glaub ich nicht, Tim: > buffer[0] = (ausgangswert/10000) +0x30; > buffer[1] = ','; > buffer[2] = ((ausgangswert%10000)/1000)+0x30; > buffer[3] = ((buffer[2]%1000)/100)+0x30; > buffer[4] = ((buffer[3]%100)/10)+0x30; > buffer[5] = '\0'; Schau noch mal in die Zeile in der du Buffer[3] berechnest. Schau noch mal genau hin! Auf Grund welcher Daten wird Buffer[3] berechnet? Selbiges für Buffer[4] > schalte ich ihn wieder aus und wieder ein steht der richtige > spannungswert da.... Ich denke du hast den ADC Code schon durchgetestet? Das übliche Problem: zuerst ADCL auslesen und erst dann ADCH
>> //get converted value >> x_l = ADCL; >> x_h = ADCH; >> vari = (x_h<<2) | x_l; der kommt wieder....
hm....nö, bisher tut alles.....lag nur daran, das ich zuerst die High-Bits der AD-Wandlung und dann die Low-Bits abgefragt habe..... Andersrum (so wie es im Manual steht) gehts problemos auch "online"....
>>> //get converted value >>> x_l = ADCL; >>> x_h = ADCH; >>> vari = (x_h<<2) | x_l; >der kommt wieder.... Die Abfragen-Reihenfolge ist dch richtig. Das ADC(H)-Register wird fürs Beschreiben gesperrt, wenn ADCL gelesen wird. Man kann sich das Auslesen von ADCL auch sparen, wenn ADLAR = 1 ist.
Wolfram wrote: >>> //get converted value >>> x_l = ADCL; >>> x_h = ADCH; >>> vari = (x_h<<2) | x_l; > > der kommt wieder.... Yep. Dann warten wir mal wie lange es dauert bis er merkt dass seine Werte nicht stimmen.
Rahul, der Trollige wrote: >>>> //get converted value >>>> x_l = ADCL; >>>> x_h = ADCH; >>>> vari = (x_h<<2) | x_l; > >>der kommt wieder.... > > Die Abfragen-Reihenfolge ist dch richtig. Schau dir mal den Zusammenbau des Gesamtergebnisses an. Manchmal frag ich mich schon was so toll am einzelnen Auslesen von 2 8-Bit Registern ist. Der Compiler könnte das alles ganz von alleine richtig machen. Nur benutzen muesste mans halt.
>vari = (x_h<<2) | x_l;
LOL
Warum liest er nicht einfach ADC in eine int-Variable ein?
Also so:
vari = ADC;
>Schau dir mal den Zusammenbau des Gesamtergebnisses >an. Gerade gesehen...(und verbessert...)
Was mich viel trauriger stimmt: Das geht ja jetzt schon eine ganze Weile so. Ich geh mal davon aus, dass er eine bekannte Spannung am ADC anliegen hat. Und nicht merkt, dass seine Ausgabe einen ganz anderen Wert anzeigt. Also das alte Spiel: Debuggen ohne zunächst mal zu wissen was eigentlich rauskommen müsste.
>Debuggen ohne zunächst mal zu wissen, was eigentlich rauskommen müsste.
Dann kommt die Frage "Mein Multimeter spinnt! Mein ADC zeigt diesen Wert
an, mein Multimeter aber diesen..."
Gegenfrage darauf: "Hast du das Multimeter auf AC oder DC stehen?"
Das wird überhaupt noch lustig ADMUX = 0xE0; ADLAR ist gesetzt.
>Das wird überhaupt noch lustig > ADMUX = 0xE0; Sowas beachte ich inzwischen nicht mehr... (entweder ein "BV" oder "1<<"). Da würde dann noch sowas kommen wie "Tausch doch mal die Messspitzen gegeneinander aus!" ;-)
Okay Jungs, alles klar. Hätte mir eigentlich vorher klar sein sollen, dass hier von sozialer Kompetenz keine Spur sein wird. Seht es doch mal so: Wenn ihr nicht gerne helft, dann lasst es einfach ganz bleiben. Sowas bringt mich nicht und euch erst recht nicht weiter... In diesem Sinne
Also Fehleranalyse: ADMUX = 0xE0; left adjust, interne Referenz! wow, das ist ja ein richtiger Hauptgewinn >faktor = 196; //19,6mV * 10 >ausgangswert = faktor * x_h; faktor dürfte von 5000mV/(8bit) 256 *10 sein interne Referenz 2,56V das liefert wohl erstmal doppelt so grosse Werte dann leftadjust bei >> //get converted value >> x_l = ADCL; >> x_h = ADCH; >> vari = (x_h<<2) | x_l; also verknüpfe x_h um 2 nach links geschiftet mit xl das zerstört bei vari den Wert in den bits 7 und 6 von 0 gezählt. Damit gibt es eine effektive Auflösung von 2 Bit, darunter kommen die zerstörten Bits über den Rest muss man wohl nicht sprechen.
>Sowas bringt mich nicht und euch erst recht nicht weiter... Vielleicht nicht weiter, aber Spaß... >Hätte mir eigentlich vorher klar sein sollen, dass hier von sozialer >Kompetenz keine Spur sein wird. Nu hatter uns erwischt.
Wolfram wrote: > Also Fehleranalyse: > ADMUX = 0xE0; > left adjust, interne Referenz! > wow, das ist ja ein richtiger Hauptgewinn hä?? >>faktor = 196; //19,6mV * 10 >>ausgangswert = faktor * x_h; > faktor dürfte von 5000mV/(8bit) 256 *10 sein nee, faktor ist die auflösung ~20mV x 10 (damit bei der berechnung das Komma rausfällt). > interne Referenz 2,56V > das liefert wohl erstmal doppelt so grosse Werte nein, leifert es nicht. das was ich eingebe, kommt genauso auch bei der berechnung raus. > > dann leftadjust bei >>> //get converted value >>> x_l = ADCL; >>> x_h = ADCH; >>> vari = (x_h<<2) | x_l; das war bullshit, hab ich grade beim nachdenken auch gemerkt. wenn dann überhaupt: x_1 = ADCL; x_h = ADCH; vari = (x_h<<8) | x_l; > > also verknüpfe x_h um 2 nach links geschiftet mit xl > das zerstört bei vari den Wert in den bits 7 und 6 von 0 gezählt. > Damit gibt es eine effektive Auflösung von 2 Bit, darunter kommen die > zerstörten Bits über den Rest muss man wohl nicht sprechen. richtig
>> faktor dürfte von 5000mV/(8bit) 256 *10 sein >nee, faktor ist die auflösung ~20mV x 10 (damit bei der berechnung das >Komma rausfällt). der Faktor mit dem du arbeitest ist 196 , oder wie du es bezeichnest deine Auflösung. 19,6 mV du arbeitest mit dem ADC in 8Bit (nur ADCH) 8bit =256 256*19,6mV =Fullrange=~5000mV =5V wo hast du den Faktor her? du arbeitest mit der internen Referenz 2,56V laut initialisierung. >nein, leifert es nicht. das was ich eingebe, kommt genauso auch bei der >berechnung raus. ist was du "eingibst" eine Spannung am ADC? >x_1 = ADCL; >x_h = ADCH; >vari = (x_h<<8) | x_l; ist immer noch falsch left adjust heisst der ganze Wert in ADC(H/L) ist links anliegend und es gab auch schon den Hinweis das es bequemer geht, siehe avrlibc Doku du scheinst den gutgemeinten Rat ans Papier zurückzukehren nicht zu verstehen. Du machst eine ganze Menge Fehler, weil du zu schnell ungeordnet arbeitest. Lies das Datenblatt, mach es auf dem Papier und checke es dort erstmal durch und dann gehe auf den Mikrocontroller , wenn es nicht klappt zurück ans Papier mit der Fehlersuche und erst dann wenn es nicht klappt ins Forum. Sonst musst du dich nicht wundern wenn du hier "lustige" Kommentare findest.
Hat eingentlich schon mal jemand daran gedacht, die Umrechnung und die Zerlegung in einem Schritt zu machen?
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.