Forum: Mikrocontroller und Digitale Elektronik ADMUX & Messkanal eintragen


von Indiaca (Gast)


Lesenswert?

Hallo,

ich habe folgendes Problem:

In meinem Programm möchte ich in einer Schleife Spannungen an
verschiedenen Kanälen messen (ADC 0 bis ADC 7). In meiner Messroutine
wird der ADC wie folgt initiallisiert:

 ADCSRA = (1<<ADEN) | (1<< ADPS2) | (1<< ADPS1);
// ADC aktivieren und Frequenzvorteiler auf 64 einstellen
 ADMUX = ADMUX | channel;
// AN channel (0x00 bis 0x07) liegt die zumessende Spannung an
 ADMUX |= (1<<REFS1) | (1<<REFS0);
// interne Referenzspannung nutzen

Nun variiere ich channel durch eine Schleife. Dies packe ich dann unter
anderem in die Mainschleife!
Nun entsteht dabei folgendes Problem: Beim ersten Durchlauf macht der
ADC alles richtig ich bekomme meine Spannungen korrekt angezeigt
(UART), aber ab dem zweiten Durchlauf wird bei jeder Messung immer nur
die letzte Spannung ausgegeben.
Ich vermute es liegt an ADMUX, irgendwie gelingt es mir nicht ihn nach
der Messung wieder in den Ursprungszustand zurückzusetzen.

Ich hoffe mir kann jemand helfen, der das Problem kennt und/oder auch
schon hatte.

Danke
         Indiaca

von Aleksej (Gast)


Lesenswert?

Du sollst ADC jedes Mal neu starten (ADCSRA |= (1<<ADSC);)

von Aleksej (Gast)


Lesenswert?

Oder AFR aktivieren, das soll auch gehen

von Indiaca (Gast)


Lesenswert?

Der ADC wird bei mir vor jeder einzelnen Messungen mit
ADCSRA |= (1<<ADSC);
neu gestartet!!
was bedeutet denn AFR??

von Indiaca (Gast)


Lesenswert?

Die eigentliche Messung sieht wie folgt aus !!

 ADCSRA |= (1<<ADSC);
 while (!(ADCSRA & (1<<ADIF)));
 result += ADC;
 ADCSRA |= (1<<ADIF);

von Aleksej (Gast)


Lesenswert?

Das bringt auch nichts, man sieht doch nicht, was ud mit result weiter
machst. Entweder die volle Quelle her, oder wird da keiner was
verstehen.

von Rahul (Gast)


Lesenswert?

Indem du ADMUX |= channel machst, setzt du IMHO irgendwann alle
Adress-Bits des Multiplexers.

Sicherer wäre es so: ADMUX = (ADMUX & 0x1F) | channel;

Dann ist es ja auch so, dass der ADC seine Messung zuende führt, und
dann erst den Kanal wechselt. Vielleicht liegt es ja daran...

von Indiaca (Gast)


Angehängte Dateien:

Lesenswert?

Hast natürlich recht !! Hier im Anhang der Quelltext !!

von Rahul (Gast)


Lesenswert?

interessanter Weise benutzt du als Schleifenindex "i" ein uint_8
(8bit) und als Endwert "mittel" ein uint_16. Da würde ich mich auch
auf eine "Sorte" festlegen (uint_16 i).
Dann hast du "return result/=mittel" geschrieben. Wieso weist du
result das noch zu? "return result/mittel" würde völlig reichen
(result ist ne lokale Variable)...

Und irgendwie habe ich das Programm diese Woche schon in einem anderen
Thread gelesen...

von Indiaca (Gast)


Lesenswert?

Ja, okay, da hast du recht, aber diese beiden Dinge sind doch nur
Schönheitsfehler, hab ich geändert, aber funktioniert dadurch nicht
besser, trotzdem danke.
Und ja, ein alter Thread existiert schon, mein Platzgegüber John hat es
wohl auch schon probiert :) Wir arbeiten zusammen an einer Steuerung für
eine Solarmessung an Tandemzellen!

von Rahul (Gast)


Lesenswert?

habt Ihr den AD-Wandler denn schon mal ohne das ganze Klimbim zum Laufen
bekommen?
Übrigens gute Teamarbeit, wenn zwei aus einer Gruppe (von 2?) das
Problem posten...

von Indiaca (Gast)


Lesenswert?

Ja, bei der Messung eines einzelnen Kanals funktioniert das ganz prima,
auch bei diesem Programm funktioniert ja die erste Messung.

von Rahul (Gast)


Lesenswert?

dann würde ich erst mal das Programm so umbauen, dass die 8 Messungen
nacheinander durchgeführt werden...

von Indiaca (Gast)


Lesenswert?

Das haben wir auch gemacht, nur vier Messungen keine Schleife, kein nix.
Wir erhalten dann vier richtige Werte !!

von Indiaca (Gast)


Lesenswert?

Es funktioniert, ist zwar sehr unelegant, aber es geht!!
habe vor der Mainschleife den gesamten ADMUX-Grundzustand gespeichert

a=ADMUX;

und stelle vor jeder Messung diesen Grundzustand wieder her!!

ADMUX=a;

wenn es hierzu jedoch noch schönere Lösungen gibt, bin ich dafür sehr
dankbar!!

von Rahul (Gast)


Lesenswert?

nicht unbedingt schneller:
ADMUX = (ADMUX & 1F) | channel;

zumindest würde ich sagen, dass es so gehen müsste...

von Aleksej (Gast)


Lesenswert?

1. Ist auch klar, wieso es so aussah:
ADMUX = ADMUX | channel;
Nach der vierten Messung aendert sich gar nichts mehr (0x11 | irgenwas
macht 0x11).
Da hilft wirklich
ADMUX = (ADMUX & 1F) | channel;
2. Ich wuerde trotzdem mit den Variablen vorsichtiger umgehen. Man
braucht ja kaum long int, wenn es hervorragend mit char geht.
Bei diesem ICC AVR weiss man nie, wie es rumgeht.

von Indiaca (Gast)


Lesenswert?

Mit den Variablen hast du wohl recht ich sollte da etwas mehr drauf
achten, was dort wie und mit wieviel Speicherverbrauch abgelegt wird.
Aber mit

ADMUX = (ADMUX & 1F) | channel;

hat es auch nicht geklappt, das habe ich ja probiert, wie oben schon
von dir beschrieben!!

von Aleksej (Gast)


Lesenswert?

Na ja, sorry, hab' wirklich uebersehen, was da Rahul geschrieben hat.
Natuerlich soll es so sein:
ADMUX = (ADMUX & F0) | channel;

von Rahul (Gast)


Lesenswert?

stimmt... und wieder verdreht...
Ich hatte eben das gleiche Problem...
Es müsste/sollte aber "& E0" heissen, da das erste Bit des oberen
Nibble noch zur Adresse gehört...

von Aleksej (Gast)


Lesenswert?

2Rahul:
Aber nur mit den neusten AVRs. 8 Kanaele brauchen ja nicht 5 bit

von Rahul (Gast)


Lesenswert?

ich "bastel" momentan mit dem Mega64 rum...

von Rahul (Gast)


Lesenswert?

Noch Nachtrag:
Wenn man nur die oberen 3 Bit (0xE0) ausmaskiert, ist es universeller
einsetzbar...

von Aleksej (Gast)


Lesenswert?

Schon richtig, das gebe ich zu, leider habe ich nicht viel mit den
maechtigsten AVRs zu tun gehabt

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
Noch kein Account? Hier anmelden.