Hallo zusammen! Ich versuche gerade eine Spannung über einem LDR über den ADC auszulesen. Leider funktioniert das immer nur am Anfang (kurz nach dem Anlegen der Betrebsspannung) nach ein paar Messungen kommen plötzlich nur noch Werte die keinen Sinn ergeben. Die Messung ist nicht zeitkritisch, Messung erfolgt nur alle paar Sekunden und läuft mit langsamster Geschwindigkeit. Ob Single Modus oder Free Running macht keinen Unterschied. Controller: ATMega32 Referenzspannung: intern 2,56 V, Aref mit 100n auf Masse sonstige Bertiebsspannungen über Kondensator und Spule entkoppelt Ich hoffe da hat jmd noch eine Idee... Danke
Die Spannung am Pin ist so, wie sie sein sollte. Das heißt der Fehler liegt im Mikrocontroller. Ich werde dann morgen mal etwas Code posten...
So, wie versprochen der Code: while(1) { //ADC Messung sbi(ADCSRA, ADSC); //Messung starten while (ADCSRA & 0x40) {} hold_ADCL = ADCL; //Messwerte abspeichern hold_ADCH = ADCH; while ( !( UCSRA & (1<<UDRE)) ) {} //Messergebnis an PC senden UART_send(hold_ADCH, hold_ADCL); //hier irgendwas tun //und nochmal messen //ADC Messung sbi(ADCSRA, ADSC); //Messung starten while (ADCSRA & 0x40) {} hold_ADCL = ADCL; //Messwerte abspeichern hold_ADCH = ADCH; while ( !( UCSRA & (1<<UDRE)) ) {} //Messergebnis an PC senden UART_send(hold_ADCH, hold_ADCL); //hier irgendwas anderes tun } Wie gesagt, die Spannung am Eingang ist korrekt, nur die AD-Wandlung im µC funktioniert nicht richtig. Manchmal(!) klappt es wenn man 2 mal direkt hintereinander wandelt. Dann ist der 2. Wert korrekt. Die Initialisierung des ADC: sbi(ADCSRA, ADEN); //ADC einschalten sbi(ADCSRA, ADPS2); sbi(ADCSRA, ADPS1); sbi(ADCSRA, ADPS0); sbi(ADMUX, REFS1); //A1 als Eingang, zu Vref intern 2,56 V sbi(ADMUX, REFS0); und evtl noch: //free running mode sbi(ADCSRA, ADATE); sbi(ADCSRA, ADSC); aber ob free-running oder single conversion macht keinen Unterschied. Gruß
Versuche mal die Wandlung so zu starten:
1 | ADCSRA |= (1<<ADSC); // 'single conversion' einleiten |
2 | while(!(ADCSRA & 0x10)); // auf ende der Wandlung warten, ADIF flag '1' |
und erst danach ADCL und dann ADCH einzulesen.
Ach ja, immer daran denken mindestens 40µs nach Umschalten des MUX und 120µs nach Umschschalten der Betriebsart (single-ended <=> differentiell) abzuwarten.
So ich hab das jetzt nochmal im Single Modus getestet mit den 2 Zeilen Code von Sonic: ADCSRA |= (1<<ADSC); // 'single conversion' einleiten while(!(ADCSRA & 0x10)); // auf ende der Wandlung warten, ADIF flag '1' Aber das hilft auch nicht. Deshalb erläutere ich mal die Anwendung genauer: Am ADC-Pin können 2 verschiedene Spannungen angelegt werden. Der Ablaufplan in der Endlosschleife sieht so aus: 1) Spannung 1 anlegen 2) Diese Spannung mit dem ADC messen 3) Spannung 2 anlegen 4) Diese Spannung mit dem ADC messen Das heißt am Ende sollte ich abwechselnd den Wert der Spannung 1 und der Spannung 2 erhalten. In Wirklichkeit klappt das ganze nur im ersten Durchgang, ab dann gibt der ADC IMMER nur noch einen der beiden Werte zurück. Und nochmal: Das ganze ist völlig zeitunkritisch. Zwischen dem Anlegen und dem Samplen sind mehrere Sekunden Pause. Gruß
Woran merkst du, dass es nicht geht? Wie schnell läuft der µC? - der ADC-takt soll zwischen 50kHz und 200kHz liegen, bei 10Bit Auflösung, du hast 128 als Prescaler gewählt (ADCPS0:2 alle gesetzt), d.h. dein µC "muss" mindestens 6.4MHz schnell sein damit der ADC richtig funktioniert.
Er läuft mit 11,xxx MHz. Dass es nicht funktioniert, merke ich daran, dass der ADC immer den gleichen Wert liefert, obwohl die Spannung an seinem Pin sich ändert!? Lässt man ihn einen Spannungswert 2x samplen, dann stimmt der 2. der beiden Werte.
> sbi(ADMUX, REFS1); //A1 als Eingang, zu Vref intern 2,56 V > sbi(ADMUX, REFS0); Wenn "A1" "PORTA.1" sein soll, dann stimmt die Multiplexer-Konfiguration nicht. So wie es hier eingestellt ist, ist PORTA.0 als Eingang konfiguriert. Check mal, ob wirklich der korrekte Pin angeschlossen ist. Und ob Du das Ende der Wandlung durch Abfrage von ADIF oder von ADSC ermittelst, sollte gehopst wie gesprungen sein.
- stimmt jedes Mal nur die zweite Messung, oder stimmt nur die _erste überhaupt_ nicht ? - liegt das Prob. vl. woanders ?(s. johnny.m) - wie sieht eigentlich die funktion "UART_send()" aus? sendet die korrekt zwei chars nach einander? also ungefähr vom Typ: "void UART_send(char erstes, char zweites)" geht
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.