Forum: Mikrocontroller und Digitale Elektronik Atmega8: ADC:Widerstandgröße auslesen


von Luggi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich brauche dringend Hilfe, um für mein erstes echtes Projekt den 
Widerstand auszulesen.
(Ich weiß, dass es dazu auch schon viele Beiträge im Forum gibt, aber 
weitergeholfen haben sie mir bisher nicht.)

In meinem Spannungsteiler ist ein Widerstand mit 10kOhm und ich 
simulieren meinen Widerstand den ich auslesen will einem 1kOhm 
Wiederstand und einem 20kOhm Widerstand. Das Ergebnis soll über 4 Leds 
am PortB ausgegeben werden.

Mit meinem aktuellen Programm und Beschaltung hätte ich gedacht, dass 
für die zwei Testwiderstände die Spannung am ADC0 zwischen nahezu 
maximal (5V)und 0V wechselt. Aber irgendwie will mir das Programm das 
nicht ausgeben.

Ich verwende von embedded-projects das AVR-Starterkit, in dem schon 
einge Kondensatoren eingebaut sind, sodass ich erstmal auf weitere 
verzichtet habe.

Hat jemand eine Idee, was ich falsch mache?

Gruß
Luggi

von Dietrich L. (dietrichl)


Lesenswert?

Luggi schrieb:
> dass für die zwei Testwiderstände die Spannung am ADC0 zwischen nahezu
> maximal (5V)und 0V wechselt.

Dann rechne zuerst mal die Spannungsteiler aus:

+5V -  1k - PC0 - 10 k 0V
+5V - 20k - PC0 - 10 k 0V

Nahezu +5V könnte man ja gelten lassen, aber nahezu 0V wohl nicht.

Gruß Dietrich

von hilmar (Gast)


Lesenswert?

Da fehlt einiges an Außenbeschaltung. Das zweite GND-Bein, AVCC, ARef, 
alles muß beschaltet sein. Schau dir mal den Artikel ADC im Tutorial an, 
da ist alles beschrieben:
http://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC

von Luggi (Gast)


Lesenswert?

Also ich brauch  trotzdem die ganzen Kondensatoren zwischen den Pins und 
GND ?

von spess53 (Gast)


Lesenswert?

Hi

>Mit meinem aktuellen Programm und Beschaltung hätte ich gedacht, dass
>für die zwei Testwiderstände die Spannung am ADC0 zwischen nahezu
>maximal (5V)und 0V wechselt.

Wie kommst du darauf? Bei festen 10k kann die Spannung an PC1 zwischen 
ca. 1,7V (20K) und ca. 4,5V (1k) variieren.

MfG Spess

von Dietrich L. (dietrichl)


Lesenswert?

Luggi schrieb:
> Aber irgendwie will mir das Programm das nicht ausgeben.

Dann sag mal, wie Du Dir die Ausgabe vorgestellt hast.

Das verstehe ich jedenfalls nicht:
1
  if (c<=512){
2
    led_blink(0x03);
3
    led_blink(0x01);
4
    c=600;}
5
  if (c>512){
6
    led_blink(0x0C);
7
    c=0;
8
    led_blink(0x01);}

Und wenn der Kommentar stimmt (ich habe die Initialisierung nicht 
kontrolliert):
1
  c = ADCH; /* Nur ADCH lesen, weil 8-Bit Modus */
ist der Wert von c max. 255. Was soll dann oben ein Vergleich mit 512?

Gruß Dietrich

von Luggi (Gast)


Lesenswert?

Auf jeden Fall ist meine Spannung dann unter 2,5 V. :-D

Das mit dem 8 Bit-Modus hab ich dann wohl falsch verstanden. Ich dachte 
die Werte bleiben zwischen 0 und 1023 bloß dass sie in nur in min 3 
Schritten wechseln.
-Das werde ich dann gleich mal ändern.

Auf jeden Fall schonmal vielen Dank soweit!

von hilmar (Gast)


Lesenswert?

> Also ich brauch  trotzdem die ganzen Kondensatoren zwischen den Pins und
> GND ?

Falls die auf dem Board schon vorhanden sind, mußt du die natürlich 
nicht doppelt einfügen, logisch. Aber die einzelnen Pins müssen auf 
jeden Fall beschaltet sein. Im ADC-Tutorial, das ich verlinkt habe, ist 
eine Beispielschaltung.
Mindestens:
zweites GND-Pin anschließen
AVCC über eine Drossel an VCC anschließen, dazu 100n gegen GND
ARef muß einen 100n gegen Masse bekommen
Reset sollte über 10k gegen VCC liegen

Wie die Kondensatoren auf deinem Board geschaltet sind, weiß ich nicht, 
aber vergleiche mal die gesamte Schaltung mit der Beispielschaltung im 
Tutorial.

von Dietrich L. (dietrichl)


Lesenswert?

Luggi schrieb:
> Das mit dem 8 Bit-Modus hab ich dann wohl falsch verstanden.

... und nicht nachgedacht. Du liest nur ein Teil der Daten des ADC aus, 
und zwar ADCH. Und das ist ein Byte (8 Bit-Register).

> Ich dachte
> die Werte bleiben zwischen 0 und 1023 bloß dass sie in nur in min 3
> Schritten wechseln.

In ein Byte "passen" keine 1023 hinein ;-(

Gruß Dietrich

von Karl H. (kbuchegg)


Lesenswert?

Luggi schrieb:
> Auf jeden Fall ist meine Spannung dann unter 2,5 V. :-D
>
> Das mit dem 8 Bit-Modus hab ich dann wohl falsch verstanden. Ich dachte
> die Werte bleiben zwischen 0 und 1023 bloß dass sie in nur in min 3
> Schritten wechseln.

ABer spätestens bei
1
  unsigned char c;
hätte dir aber klar sein müssen, das der Wert niemals größer als 255 
sein kann. Denn ein unsigned char hat 8 Bit und mit 8 Bit sind nun mal 
nur Werte zwischen 0 und 255 möglich.

AUs dem und ähnlichen Gründen schreibt man auch lieber
1
  uint8_t c;
anstelle von
1
  unsigned char c;
Denn dann ist es recht offensichtlich, dass das eine 8 Bit Variable ist.


Hier in diesem Teil
1
  if (c<=512){
2
    led_blink(0x03);
3
    led_blink(0x01);
4
    c=600;}
5
  if (c>512){
6
    ....
verstehe ich die Zuweisung von 600 an c nicht. Was war da die Idee 
dahinter? Effektiv führt das dazu, dass das 2.te if ausgehebelt wird. 
Denn entweder c war von Anfang an schon größer als dein Grenzwert, dann 
wird das 2.te if genommen, oder es war kleiner/gleich, dann wird am Ende 
des 1.ten if dafür gesorgt, dass auch das 2.te if genommen werden muss.

Ich nehme mal an, dass diese Zuweisung den Grund hatte, dass du etwas 
siehst.
Denn worauf ich eigentlich raus will:
So etwas
1
  if( a <= Grenzwert )
2
  {
3
    ....
4
  }
5
  if( a > Grenzwert )
6
  {
7
    ....
8
  }
ist nicht sinnvoll, wenn sich a zwischendurch sowieso nicht verändern 
kann (wie es in deinem Fall eigentlich sein sollte).
Denn: Wenn a NICHT kleiner/gleich als der Grenzwert ist, dann MUSS es 
größer als der Grenzwert sein. Es gibt keine andere Möglichkeit mehr. 
D.h. obiges ist gleichwertig zu
1
  if( a <= Grenzwert )
2
  {
3
    ....
4
  }
5
  else
6
  { 
7
    ....
8
  }
Verwende dieses 'else', wenn es möglich ist! Denn im Originalcode taucht 
der Grenzwert 2 mal auf. D.h. bei Änderungen musst du darauf achten, 
dass du immer beide Stellen an der der Grenzwert auftaucht anpasst, 
sonst kommt es zu Inkonsistenzen. Das kann dir durch die Verwendung 
eines 'else' nicht passieren. Der Grenzwert taucht nur einmalig auf und 
damit gibt es keine 2.te Stelle die man anpassen müsste, wenn sich der 
Grenzwert verändert.

von Karl H. (kbuchegg)


Lesenswert?

PS: Dein Schreibweisen Schema für { - } Klammern solltest du nochmal 
überdenken. Es ist recht sinnfrei, die schliessende } ans Ende der Zeile 
nach der letzten Anweisung im Block zu setzen.

Du hast zwar sauber eingerückt (was gut ist!), trotzdem muss man zur 
Kontrolle, ob die Einrückung richtig ist und ob alle { - } Blöcke 
korrekt sind, mit den Augen dauernd den Code absuchen
1
  if (c<=512){
2
    led_blink(0x03);
3
    led_blink(0x01);
4
    c=600;}
5
  if (c>512){
6
    led_blink(0x0C);
7
    c=0;
8
    led_blink(0x01);}

So geschrieben
1
  if (c<=512){
2
    led_blink(0x03);
3
    led_blink(0x01);
4
    c=600;
5
  }
6
  if (c>512){
7
    led_blink(0x0C);
8
    c=0;
9
    led_blink(0x01);
10
  }
brauch ich das nicht. Die schliessende { steht IMMER exakt in der 
Spalte, in der auch die Anweisung darüber beginnt, in der auch die 
öffnende { steht.

Wie du es ja zb bei
1
SIGNAL (ADC_vect){
2
  ....
3
}
auch gemacht hast.

Das ist auch gut so, denn diese { } Klammer Einrückungen, und zwar so, 
dass man sie wiederfindet, sind ein Hilfsmittel um bei größerem Code 
nicht den Überblick zu verlieren.

So geschrieben
1
  if (c<=512)
2
  {
3
    led_blink(0x03);
4
    led_blink(0x01);
5
    c=600;
6
  }
7
  if (c>512)
8
  {
9
    led_blink(0x0C);
10
    c=0;
11
    led_blink(0x01);
12
  }
ist dann dieser Zusammenhang noch viel offensichtlicher!
Die schliessende { steht immer exakt in derselben Spalte, wie du 
zugehörige öffnende {. Will ich wissen, zu welchem { eine vorhandene } 
gehört, dann brauch ich nur in derselben Spalte nach oben suchen und die 
erste { auf die ich stosse, ist die richtige (wenn alles andere stimmt).

von Luggi (Gast)


Lesenswert?

Ok,

Ich hab jetzt:
1.) Die fehlenden Kondensatoren und die Spule mit den entsprechenden 
Pins zusammengeschossen (bis auf AGND, der wohl in dem einen GND schon 
drin ist)
2.) Die zwei GND miteinander kurzgeschossen

3.) das Programm bzgl. Schreibweise und dem ADCH-Wert verbessert.

..und .. es FUNKTIONIERT! :-D

Vielen Dank an alle für eure Kritik!!

Ich hätte jetzt aber noch zwei Fragen:

a.) Und zwar leuchten die LEDs nicht so hell, wie in einem einfachen 
"led_blink"-Programm mit der selben Schaltung. Woran kann das liegen?
b.) Welchen Effekt hat die Schaltung am RESET-Pin? Ich hatte jetzt ein 
par Probleme den µController direkt neu zu flashen. Liegt das an dieser 
Schaltung?

Gruß Luggi

von holger (Gast)


Lesenswert?

>a.) Und zwar leuchten die LEDs nicht so hell, wie in einem einfachen
>"led_blink"-Programm mit der selben Schaltung. Woran kann das liegen?

Gib jeder LED einen eigenen Vorwiderstand. Das ist ja grottig so
wie du es machst.

von Mike (Gast)


Lesenswert?

Luggi schrieb:
> a.) Und zwar leuchten die LEDs nicht so hell, wie in einem einfachen
> "led_blink"-Programm mit der selben Schaltung. Woran kann das liegen?

Genau genommen werden sie unterschiedlich hell leuchten - je nach dem, 
wie viele gerade an sind.

von Luggi (Gast)


Lesenswert?

Ok, jede LED hat jetzt ihren eigenen Widerstand und sie leuchten jetzt 
tatsächlich heller.
Vielen Dank dafür!

Das sie dunkler leuchten, wenn alle gleichzeitig aufblinken kann ich 
nicht beobachten.

Gruß Luggi

von Mike (Gast)


Lesenswert?

Luggi schrieb:
> Das sie dunkler leuchten, wenn alle gleichzeitig aufblinken kann ich
> nicht beobachten.

Zusammen sind sie dann auch wieder gleichhell und wenn das Auge nicht 
den direkten Vergleich hat, fällt das nicht so sehr auf.

von hilmar (Gast)


Lesenswert?

> Ich hab jetzt:
> 1.) Die fehlenden Kondensatoren und die Spule mit den entsprechenden
> Pins zusammengeschossen (bis auf AGND, der wohl in dem einen GND schon
> drin ist)

Schließ mal bitte das AGND mit an GND an. Sonst wird innerhalb des 
Controllers der Strom fließen und dir bestenfalls das Meßergebnis 
verfälschen. Grundsätzlich hat jeder VCC-Pin seinen GND-Pin und 
dazwischen gehören immer Abblockkondensatoren (100n), und zwar so kurz 
und dicht wie möglich an den Anschlußbeinen. Genauso ist es bei AVCC und 
AGND, das ist die Stromversorgung für den Analogteil. Auch dort ein 100n 
dazwischen. Und in die Zuführung von VCC nach AVCC eine Drossel. Diese 
Maßnahme filtert dir die Versorgung des ADC.
Der Rest wie in der Beispielschaltung.

> 2.) Die zwei GND miteinander kurzgeschossen

von Luggi (Gast)


Lesenswert?

Soweit ich weiß hat der Atmega8 gar keinen AGND-Pin (hab ich jedenfalls 
so hier im Forum gelesen und im Datenblatt finde ich keine entsprechende 
Belegung). Da kann ich ja AGND nicht mit GND verbinden.
Ansonsten entspricht doch deine Beschreibung der Schaltung aus dem 
Tutorial..

von hilmar (Gast)


Lesenswert?

Du hast Recht, der Pin 22 (beim DIL-Gehäuse) ist nur in der 
Beispielzeichnung als AGND bezeichnet. Ich denke, wegen der 
Verdeutlichung, daß dies der GND-Anschluß für den Analogteil ist und der 
auch zu AVCC gehört. Im Datenblatt ist er nur als GND bezeichnet. Das 
hat zur Verwirrung geführt.
Aber wenn du zwischen 20 und 22 einen 100n hast und zwischen 7 und 8 
auch, dann ist das in Ordnung.

von Luggi (Gast)


Lesenswert?

Ok, hab ich.
Gehören die Kondensatoren in jeder Schaltung an diese Stellen oder nur 
für diese Gleichung?

von Luggi (Gast)


Lesenswert?

Ok, ich denk mal die gehören da immer hin.
Jedenfalls sind sie in dem Starterkit, das ich verwende auch schon drin.

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.