Forum: Mikrocontroller und Digitale Elektronik AD-Wandler Atmega 32


von Flea (Gast)


Lesenswert?

Hallo, ich möchte bei einem Gerät noch eine Batterie-Zustands-Anzeige 
machen. Dazu beutze ich den AD-Wandler des Controllers. Der AD-Wandler 
liefert doch einen Wert zwischen 0 und 1023 oder?
Ich möchte, dass ich nur Werte zwischen 0 und 7 (bzw. 1 und 8) erhalte. 
Dazu muss ich doch als Teilungsfaktor "128" einstellen, also ADPS2, 
ADPS1 und ADPS0 auf 1 setzen. Stimmt das so?
Ich erhalte auf meinem Display nämlich Ergebnisse, die nicht gerade der 
Realität entsprechen.

Vielen Dank!

von Johannes M. (johnny-m)


Lesenswert?

Mit dem Teilerfaktor hat das ganze überhaupt nichts zu tun! Der 
definiert nur, mit welchem Takt der ADC arbeitet, also wie lange er für 
eine Wandlung braucht. In Deinem Fall musst Du aber das Ergebnis der 
Wandlung entsprechend weiterverarbeiten.

Zunächst mal solltest Du das ADLAR-Bit im ADMUX-Register setzen. Dann 
wird das Ergebnis schon mal linksbündig ausgegeben und Du musst nur noch 
das 8-Bit-Register ADCH auslesen (Wertebereich 0...255). Und den Wert 
teilst Du noch durch 32. Dann hast Du Deinen Wertebereich von 0...7.

von Thilo M. (Gast)


Lesenswert?

Lies dich mal im Dateblatt ein, wie das ADC-Ergebnis 'left-adjusted' 
eingestellt wird, dann bist du bei 8 bit (die unteren 2 bit kannst du 
ignorieren, indem du dann nur ADCH ausliest). Diese 8 bit nun 5 bit nach 
rechts schieben und du bist bei 3 bit Auflösung (0..7). In Assembler und 
in C die schnellste Variante.

von Matthias (Gast)


Lesenswert?

Wenn dir 0..3 (also 1..4) als Wertebereich ausreichen, dann nimm doch 
einfach right-adjusted und lies nur das ACDH aus, das denthält dann 
werte zwischen 0...3

von Flea (Gast)


Lesenswert?

Also hier ist mal der Quellcode, hab im Moment noch Probleme mit dem 
AD-Wandler. Wenn ich den Pin am Controller auf Masse ziehe, krieg ich 
immer noch einen hohen Wert, also eigentlich immer...
1
uint16_t ReadChannel(uint8_t kanal)
2
{
3
  uint8_t i;
4
  uint16_t result;
5
6
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);      // Frequenzteiler auf 128 setzen --> 8 Zustände 
7
                                            
8
  ADMUX = kanal;                              // Kanal waehlen
9
  ADMUX |= (1<<REFS1) | (1<<REFS0);         // interne Referenzspannung nutzen 
10
11
/*  // Dummy-Messung (wird bei ADC-Initialisierung selbständig ausgeführt...
12
13
  ADCSRA |= (1<<ADSC);                      // eine ADC-Wandlung 
14
  while ( ADCSRA & (1<<ADSC) ) {
15
     ;                           // auf Abschluss der Konvertierung warten 
16
  }
17
  result = ADCW;                    // ADCW muss einmal gelesen werden,
18
                                    // sonst wird Ergebnis der nächsten Wandlung
19
                                    // nicht übernommen.
20
*/
21
  // Eigentliche Messung
22
23
  result = 0; 
24
    ADCSRA |= (1<<ADSC);                    // eine Wandlung "single conversion"
25
    while ( ADCSRA & (1<<ADSC) ) {
26
      ;                         // auf Abschluss der Konvertierung warten
27
    }
28
    result = ADCW;                    // Wandlungsergebnis
29
  ADCSRA &= ~(1<<ADEN);                     // ADC deaktivieren
30
 
31
  return result;
32
}

von Johannes M. (johnny-m)


Lesenswert?

Wundert mich nicht wirklich. Im Datenblatt steht eindeutig, dass das 
erste Ergebnis nach dem Start des ADC u.U. für die Tonne ist. Warum hast 
Du die Dummy-Wandlung auskommentiert? Die könnte das Problem nämlich 
beheben. Und je nachdem, wie oft gewandelt werden soll, ist es auch 
unsinnig, den ADC nach jeder Wandlung wieder zu deaktivieren. Dann kann 
man sich auch die Dummy-Wandlung sparen (außer beim ersten Mal, aber das 
kann man in main nach der Initialisierung machen).

Außerdem solltest Du bei Änderungen im Code auch die Kommentare 
entsprechend anpassen. Das mit "Frequenzteiler auf 128 setzen --> 8 
Zustände" hatten wir schließlich schon geklärt (hoffe ich jedenfalls).

von Thilo M. (Gast)


Lesenswert?

Du kannst auch vor der ersten Wandlung 120µs Pause machen (bzw. etwas 
Anderes), dann kommt auch bei der ersten Wandlung was Vernünftiges 
'raus.
Zwischen dem Einstellen der Betriebsart und der nächsten Messung 120µs 
Pause machen.

von Flea (Gast)


Lesenswert?

Also hab jetzt die Dummy-Wandlung wieder drin. Bekomme als Ergebnis 
jedoch immer 255 angezeigt. Sogar wenn ich die den ADC-Kanal auf Masse 
lege. Ich hab aber einen anderen Punkt auf der Platine gefunden 
(übrigens auch auf Masse-Potenzial!!!!!!!!), bei dem dann 31 angezeigt 
wird.

von Johannes M. (johnny-m)


Lesenswert?

Hast Du den Kondensator (100 nF) am AREF-Pin gegen Masse?

von Flea (Gast)


Lesenswert?

Nein hab ich nicht, ist laut Datenblatt auch nicht unbedingt nötig. Bei 
mir ist die Genauigkeit sowieso nicht so wichtig, ich brauch ja nur 3 
Bits.

von Andreas K. (a-k)


Lesenswert?

Verzeihe mir bitte die dumme Frage: AVCC/AGND angeschlossen?

von Flea (Gast)


Lesenswert?

Ja klar ist angeschlossen

von Auch einer (Gast)


Lesenswert?

>Nein hab ich nicht, ist laut Datenblatt auch nicht unbedingt nötig.

Das was die Entwickler vom Atmel vorschlagen ist ja total unwichtig.

von Wurst (Gast)


Lesenswert?

An dem Kondensator liegts ziemlich sicher nicht, der ist zwar wichtig, 
aber wenn er wirklich nur die obersten Bits braucht kann man den auch 
weglassen. Wenn man feststellt, dass diese dennoch flattern sollten kann 
man den auch noch einbauen. Aber momentan scheint er immer den gleichen 
Wert zu bekommen und da ist der Kondensator kaum schuld.
Ich will damit nicht sagen, dass es nicht nötig ist diesen Kondensator 
einzubauen, aber eben...

von Flea (Gast)


Lesenswert?

Also es funktioniert!!!
An was es lag, darf ich hier aber nicht sagen, sonst bekomm ich von euch 
Prügel!

von Matthias (Gast)


Lesenswert?

Sags trotzdem, welchen Fehler hast du gemacht, über den wir sicherlich 
auch mal gestolpert sind

von Johannes M. (johnny-m)


Lesenswert?

Flea wrote:
> Also es funktioniert!!!
> An was es lag, darf ich hier aber nicht sagen, sonst bekomm ich von euch
> Prügel!
Die bekommste auch so...;-) Also raus damit! Falschen Pin an GND 
gezogen?

von Wurst (Gast)


Lesenswert?

Sei kein Spielverderber, Unterhaltung muss sein!

von Flea (Gast)


Lesenswert?

Das Ding ist ne fertige Platine, bei der ich noch den Batteriezustand 
aufs Display machen sollte. Da der Controller so klein ist, habe ich von 
jemand anderem einen losen Draht an den ADC-Pin anbringen lassen. Und 
ich hab jetzt zweieinhalb Stunden gebraucht um herauszufinden, dass der 
Draht Isolierlack drauf hatte ^^

von Matthias (Gast)


Lesenswert?

..n anbringen lassen....raht Isolierlack ..


Wie wurde er dann angebracht? Sekundenkleber?

von Flea (Gast)


Lesenswert?

mit Tesafilm! Was sonst?
Oder wie nennt man das auf dem Draht?

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.