Habe mir aus diversen Quellen ein Test-Programm für einen A/D-Wandler zusammengestrickt. Eingang C0, Spannung von Poti, der zwischen +5V und Masse hängt und damit als Spannungsteiler fungiert. Das Ergebnis ist leider permanent 0. Wer kann mir helfen? #define F_CPU 3686400 // Taktferquenz des myAVR-Boards #include <avr\io.h> // AVR Register und Konstantendefinitionen int wartekurz() // da delay-Funktion nicht funktioniert { for (long j = 0; j < 10000; j++) int k=k+1; } int main() { int i,sample,value; // Variablen Definition DDRC = 0b00111110; // 0 Eingang, 1-5 Ausgang, 6+7 reserviert PORTC = 0x00; // Ausgänge auf 0 ADMUX |= (1<<REFS0); // AVCC als Referenz ADMUX &= ~(1<<REFS1); // AVCC als Referenz ADMUX |= (1<<MUX0); // C0 als Eingang wählen ADCSRA|= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0); //AD-Wandler an, Frequenzvorteiler auf 32 // Endlosschleife zur kontinuierlichen Auswertung der Eingangsspannung (am ADC) while(1) { ADCSRA |=(1<<ADSC); // Einschwing-Wandlung while(ADCSRA&(1<<ADSC)) // warten bis Konvertierung abgeschlosen sample=ADCW; // Auslesen ADCW // Nun geht es los sample=0; value=0; for(i=0;i<10;i++) // Schleife zum Sammeln von 10 Meßwerten { ADCSRA |=(1<<ADSC); // eine Wandlung while(ADCSRA&(1<<ADSC)) // warten bis Konvertierung abgeschlosen sample+=ADCW; // aufsummierung der Sample-Werte } value=sample/10; // Aritmethisches Mittel der Sample-Werte // Auswertung der Meßdaten if (value==0) // falls 0 -> PORTC=0b00001000; // schalte rote LED (C3) ein if (value>0 && value<1024)// falls zwischen 0 und 1024 -> PORTC=0b00010000; // schalte gelbe LED (C4) ein if (value>=1024) // falls 1024 -> PORTC=0b00100000; // schaltet grüne LED (C5) ein wartekurz(); PORTC=0x00; // schaltet LED aus wartekurz(); } }
Danke, das war eine meiner Quellen... funktioniert dennoch nicht.
Bei dir scheint so einiges nicht zu funktioneren..
>// da delay-Funktion nicht funktioniert
Nö, die funktioniert garantiert.
Im Gegensatz zu Deiner, die vermutlich komplett wegoptimiert wird.
Ebenso funktioniert die Routine im Tutorial.
Ist "Sample" uint16_t ?
...das die grüne LED angeht, erwartest du aber nicht wirklich, oder ? while(ADCSRA&(1<<ADSC))<- wo ist das semikolon ?
> Danke, das war eine meiner Quellen... funktioniert dennoch nicht.
Benutz' doch zuerst den geprüften Quellcode. Dann kämpfst du "nur noch"
mit der Hardware. Wenn du Software und Hardware selbst machst, hast du
einen Zweifrontenkrieg.
Ansonsten:
int i,sample,value; // Variablen Definition
^^^^^^
ADC gibt kein int (vorzeichenbehaftet) zurück sondern unsigned Werte
(nicht vorzeichenbehaftet). Beim Aufsummieren von 10 Werten hast du noch
keinen Überlauf. Bei mehr als 32 Werte aufpassen. Dito Typ von value.
while(ADCSRA&(1<<ADSC)) // warten bis Konvertierung abgeschlosen
^
Da fehlt was.
while(ADCSRA&(1<<ADSC)) // warten bis Konvertierung abgeschlosen
^
Da auch.
int wartekurz() // da delay-Funktion nicht funktioniert
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Diesem Kommentar solltest du nachgehen. Checke die Version deines
Compilers und der dazugehörigen avr-libc. Möglicherweise benutzt du die
Funktion "delay" auch falsch. Gehen müsste
1 | void wartekurz(void) |
2 | {
|
3 | // 10*100ms = 1s Pause
|
4 | unsigned char i = 10; |
5 | for (i=0; i<10; i++) |
6 | delay_ms(100); |
7 | }
|
wenn mit Optimierung übersetzt wird (-Os z.B.). Den folgenden Teil habe ich nicht überprüft. Ich vertraue darauf, dass du das korrekt aus dem AVR-GCC-Tutorial übernommen hast.
1 | ADMUX |= (1<<REFS0); // AVCC als Referenz |
2 | ADMUX &= ~(1<<REFS1); // AVCC als Referenz |
3 | ADMUX |= (1<<MUX0); // C0 als Eingang wählen |
4 | ADCSRA|= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0); //AD-Wandler an, |
5 | Frequenzvorteiler auf 32 |
Hätte vielleicht dazusagen sollen, daß ich gerade erst angefangen habe ... -Hatte das Semikolon übersehen. -Da ich nur 10 Werte zur Mittelwertbildung einsetze, müßte int reichen. -Die Verzögerungsfunktion ist nicht kritisch, sondern die A/D-Wandlung. -Das Musterprogramm verwendet die internen 2,56 Volt als Referenz, ich möchte 0-5V messen (kann es hier zu Beschädigungen kommen?) Semikolon eingefügt => mein Programm funktioniert leider dennoch nicht (das Musterprogramm allerdings auch nicht)
Joachim Krohn schrieb: > Hätte vielleicht dazusagen sollen, daß ich gerade erst angefangen habe > ... > > -Hatte das Semikolon übersehen. Die Stelle ist zweimal vorhanden; du musst 2x ein ; einfügen. > -Da ich nur 10 Werte zur Mittelwertbildung einsetze, müßte int reichen. Stimmt habe ich auch überprüft. > -Die Verzögerungsfunktion ist nicht kritisch, sondern die A/D-Wandlung. Wenn deine Funktion verzögert, Wenn sie das nicht macht, siehst du u.U. kein Ergebnis an den LEDs, weil die passende nur ein paar Microsekunden aufblitzt. > -Das Musterprogramm verwendet die internen 2,56 Volt als Referenz, ich > möchte 0-5V messen (kann es hier zu Beschädigungen kommen?) Nein, allerdings bekommst du bei zu messenden Spannungen >= 2,56V den oberen Grenzwert des ADC (0x3FF). > Semikolon eingefügt => mein Programm funktioniert leider dennoch nicht > (das Musterprogramm allerdings auch nicht) Vielleicht hängt es doch an der Schaltung.
Hallo, > sample=ADCW; // Auslesen ADCW > sample=0; Was soll das?? Wieso weist Du der Variablen "sample" erst den Wert vom ADC zu und setzt sie eine Zeile später auf Null? Kein Wunder, dass da nur Null heraus kommt ... :-( Gruss
> Was soll das?? Wieso weist Du der Variablen "sample" erst den Wert vom > ADC zu und setzt sie eine Zeile später auf Null? Kein Wunder, dass da > nur Null heraus kommt ... :-( Ist doch egal. Nochmal ne Zeile drunter gehts mit der Messung von 10 Werten und Mittelwertbildung weiter.
Oh Wunder, oh Wunder, mit der Schaltung aus dem Musterprogramm habe ich doch hinbekommen. Morgen versuche ich rauszubekommen, warum es in meinem Programm nicht geklappt hat. Danke für den Support.
Habe nun rausbekommen, woran es hing: Ich habe zur Wahl des Eingangs verwendet: ADMUX |= (1<<MUX0); -> funktioniert nicht Musterprogramm: ADMUX = 0; -> funktioniert Warum das so ist, weiß ich nicht.
Joachim Krohn schrieb:
> Warum das so ist, weiß ich nicht.
Weil du das Datenblatt nicht gelesen hast...du hast auf ADC1 gestellt...
Auch auf die Gefahr hin, mich gänzlich zu blamieren: Um C0 als zu A/D-wandelnden Eingang zu setzen, muß doch im Register ADMUX das Bit0 (MUX0) auf 1 gesetzt werden. Warum funktioniert das nicht über ADMUX |= (1<<MUX0)? Und der Befehl ADMUX = 0 setzt doch alle Bits auf 0, incl. REFS0 und REFS1. Danke für Eure Geduld!
Hi >Um C0 als zu A/D-wandelnden Eingang zu setzen, muß doch im Register >ADMUX das Bit0 (MUX0) auf 1 gesetzt werden. Nein. Datenblatt: MUX3..0 Single Ended Input 0000 ADC0 MfG Spess
Hallo Joachim Krohn! Ich weiß der Thread ist schon sehr alt, aber ich hab mich mit dem selben Thema beschäftigt und erstmal ein Lob von mir, dein Programm ist super, habs bei mir ausprobiert und meinen Bedürfnissen angepasst. Ich hab gesehn, dass du Probleme mit der delay-Funktion hattest und du dir daher eine "Warteschleife" geschrieben hast. Ich hatte bis eben auch das selbe Problem mit dem Delay, aber die Lösung ist einfach, wenn man sie denn endlich gefunden hat. Das ist jetzt sozusagen für dich und für die zukünftigen User die Probleme mit dem Delay haben. Bei mir lag es daran, dass ich mit dem myAVR Workpad Plus (Demo) arbeite und der mir immer diese Fehlermeldung ausgabe: warning: #warning "Compiler optimizations disabled; functions from won't work as designed" Da es bei Workpad keine Einstellung dafür gibt, muss man eine kleine Zeile ganz oben im Code schreiben: //CompilerOption: -Os Somit bekommt man beim copelieren diese Meldung: Hinweis: Es werden die im Quelltext angegebenen Compiler-Optionen verwendet: -Os Somit kann man dann auch #include <util/delay.h> einbinde und _delay_ms() funktioniert! =) Hoffe das war jetzt hilfreich.... Liebe Grüße Tanja
Tanja schrieb: > Hallo Joachim Krohn! > > Ich weiß der Thread ist schon sehr alt Leichenfledderei nennt man das auch. > aber ich hab mich mit dem selben > Thema beschäftigt und erstmal ein Lob von mir, dein Programm ist super, LOL, ich hoffe das ist ironisch gemeint. Dieser Murks. > Bei mir lag es daran, dass ich mit dem myAVR Workpad Plus (Demo) arbeite > und der mir immer diese Fehlermeldung ausgabe: > > warning: #warning "Compiler optimizations disabled; functions from won't > work as designed" Und diese Fehlermeldung war dir über so lange Zeit nicht eindeutig genug? Was muss der Compiler denn noch machen, vor dir Tanzen? > Da es bei Workpad keine Einstellung dafür gibt, muss man eine kleine > Zeile ganz oben im Code schreiben: > > //CompilerOption: -Os Was ein Pfusch Programm. Nehmt doch mal was gescheites. Alter Schwede, ich frage mich ja, ob der Sinn der Optimierung überhaupt verstanden wurde. Man setzt diese ja nicht wegen der delay Funktionen auf Os, sondern weil jede andere Einstellung für einen kleinen Controller eigentlich keinen Sinn macht, ausser man weiß wirklich was man tut. D.h. ja du hast die ganze über mit O0 optimiert.
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.