Forum: Mikrocontroller und Digitale Elektronik AVR-C Analog Read


von Martin F. (martin_f70)


Lesenswert?

Hallo!
Ich wollte ein Potentiometer an einem Pin auslesen (Pin ADC0).
Ich habe nach diesem Tutorial gearbeitet: 
http://creativeelectron.net/blog/2009/09/avr-how-to-take-analog-input-in-avr/
Die an PORTB angeschlossene LED leuchtet aber nicht, woran liegt das?

LG, Martin

von Martin Fisher (Gast)


Lesenswert?

Hallo!
Ich wollte ein Auto an einem Bordstein parken (München Sportplatz).
Ich habe nach diesem Tutorial gearbeitet:
http://www.meinschein.at/ausbildung/einparken
Der am Auto angeschlossene Tacho zeigt aber nichts an, woran liegt das?

LG, Martin

von Martin F. (martin_f70)


Lesenswert?

Sehr lustig

von Martin F. (martin_f70)


Lesenswert?

Ok!
Wenn ich am Poti drehe dann Blink die LED merkwürdig, ich habe jetzt 
auch mal im LCD den ADCH Wert ausgeben lassen. Er Blättert ein paar 
ASCII-Zeichen durch...

von Karl H. (kbuchegg)


Lesenswert?

Es soll aber nicht lustig sein.
Es soll dir veranschaulichen, dass wir hier keine Hellseher sind und du 
mit ein paar mehr Informationen rüber kommen musst.

zb deinem Programm.
Nicht irgendein Programm von irgendeiner Website, sondern dein konkretes 
Programm, welches auf deinem µC läuft.

von Martin F. (martin_f70)


Lesenswert?

Mein Programm:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include "lcd-routines.h"
4
5
int main(void)
6
{
7
  DDRB = 0xff;
8
  lcd_init();
9
10
  ADMUX=(1<<REFS0)|(1<<ADLAR);
11
12
  ADCSRA=(1<<ADEN)|(1<<ADPS2);
13
14
    lcd_setcursor(0, 1);
15
  lcd_string("Loading...");
16
  _delay_ms(1000);
17
  lcd_clear();
18
19
    while (1)
20
    {
21
      ADCSRA|=(1<<ADSC);
22
      lcd_clear();
23
      lcd_setcursor(0, 1);
24
    lcd_data(ADCH);
25
        PORTB = ADCH;
26
        _delay_ms(100);
27
28
    }
29
    return 0;
30
}

von Karl H. (kbuchegg)


Lesenswert?

Martin Fischer schrieb:

>     lcd_data(ADCH);

ADCH kannst du nicht einfach so aufs LCD geben.
Logisch kriegst du da seltsame Zeichen.

Du musst dir schon einen String basteln, der deiner Zahl entspricht. Den 
String kannst du dann ausgeben.

FAQ
gleich der erste Punkt

von Karl H. (kbuchegg)


Lesenswert?

Weils wurscht ist
1
int main()
2
{
3
  char buffer[10];
4
5
....
6
7
    while (1)
8
    {
9
      ADCSRA|=(1<<ADSC);
10
      while( ADCSRA & ( 1 << ADSC ) )   // warte drauf, dass der ADC fertig wird
11
        ;
12
13
      sprintf( buffer, "%4d", ADCH );
14
      lcd_setcursor(0, 1);
15
      lcd_string( buffer );
16
17
      PORTB = ADCH;
18
      _delay_ms(100);
19
    }
20
}

: Bearbeitet durch User
von Martin F. (martin_f70)


Lesenswert?

was meinst du mit "Weils wurscht ist!"?

von Amateur (Gast)


Lesenswert?

Bei Kaspertheater ruft der Kasper: "Seid ihr denn auch alle da"?
Bevor das "Ja" nicht erschallt, macht er nicht weiter.

Ich weiß nicht mit welchem Publikum/µP Du sprichst und somit auch nicht 
ob die Initialisierung OK ist, aber ich weiß als höflicher Programmierer 
fragt man vor jeder A/D-Wandler Abfrage: "Bist Du auch fertig"? Wird 
diese Höflichkeit ignoriert, darfst Du Dich nicht wundern, wenn Du 
Blödsinn aus den Registern kitzelst. Manche A/D-Wandler wollen auch 
gestartet bzw. erneut gestartet werden.

von Karl H. (kbuchegg)


Lesenswert?

Martin Fischer schrieb:
> was meinst du mit "Weils wurscht ist!"?

eigentlich solltest du zu diesem Zeitpunkt schon selber wissen, wie man 
Variablenwerte auf ein LCD ausgibt.
Aber damit das nicht noch länger dauert, gibts eben dieses Code-Snippet.

von Cyblord -. (cyblord)


Lesenswert?

Das Problem mit Martin ist, dass er unglaublich wenig Ahnung hat, gar 
nicht verstehen will sondern nur fertige Lösungen haben will und er dazu 
unglaublich hartnäckig ist. Schlimme Mischung.

von Martin F. (martin_f70)


Lesenswert?

Karl, danke für diese Info, auch zum FAQ!
Hat mir sehr geholfen, danke!!!!

von Martin F. (martin_f70)


Lesenswert?

Noch eine Frage...
Womit wähle ich den Port aus andem gemessen werden soll? Das verstehe 
ich nicht ganz...

von Karl H. (kbuchegg)


Lesenswert?

Auf lange Sicht wirst du nicht umhin kommen, auch mal einen Blick ins 
Datenblatt zu riskieren. Da steht im Abschnitt über den ADC all das 
drinnen.

Die entsprechenden Bits sind im ADMUX Register.

von Martin F. (martin_f70)


Lesenswert?

Ok. Könntest du mir jedoch vllt. bitte erklären, was 
ADMUX=(1<<REFS0)|(1<<ADLAR); dort das REFS0 und das ADLAR ist?
Ich verstehe das so wie es im Forum-Tutorial steht nicht ganz...

von Karl H. (kbuchegg)


Lesenswert?


: Bearbeitet durch User
von Martin F. (martin_f70)


Lesenswert?

Also muss ich an diese Zeile nur noch (1<<MUX0) anhängen zu:
  ADMUX=(1<<REFS0)|(1<<ADLAR)|(1<<MUX0);
?

von Eumel (Gast)


Lesenswert?

Martin Fischer schrieb:
> Also muss ich an diese Zeile nur noch (1<<MUX0) anhängen zu:
>   ADMUX=(1<<REFS0)|(1<<ADLAR)|(1<<MUX0);
> ?

Schau halt ins Datenblatt. Und die Sache wie man Werte aufs Display 
ausgibt wurde dir doch schon ausführlichts vorgekaut.

von Martin F. (martin_f70)


Lesenswert?

Habe ich gefunden, hier:
1
Table 22-1. Analog Comparator Multiplexed Input
2
ACME   ADEN   MUX2..0   Analog Comparator Negative Input
3
0     x     xxx     AIN1
4
1     1     xxx     AIN1
5
1     0     000     ADC0
6
1     0     001     ADC1
7
1     0     010     ADC2
8
1     0     011     ADC3
9
1     0     100     ADC4
10
1     0     101      ADC5
11
1     0     110     ADC6
12
1     0     111     ADC7
Ich bin nun noch kein Profi...
Ich verstehe nicht ganze wie ich diese Tabelle zu lesen habe bzw. wie 
ich den MUX nun richtig setzte...sry...aber könnte mir jemand das 
verraten?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Martin Fischer schrieb:
> Habe ich gefunden, hier:
>
> Table 22-1. Analog Comparator Multiplexed Input
> ACME   ADEN   MUX2..0   Analog Comparator Negative Input
> 0     x     xxx     AIN1
> 1     1     xxx     AIN1
> 1     0     000     ADC0
> 1     0     001     ADC1
> 1     0     010     ADC2
> 1     0     011     ADC3
> 1     0     100     ADC4
> 1     0     101      ADC5
> 1     0     110     ADC6
> 1     0     111     ADC7
>
> Ich bin nun noch kein Profi...

Mann muss ja auch kein Profi sein, um Werte aus einer Tabelle ablesen zu 
können.

Du willst den ADC1 benutzen?
Dann sind die Bits MUX2 bis MUX0 auf 0, 0, 1 zu setzen. (MUX2 auf 0, 
MUX1 auf 0, MUX0 auf 1)
001, welches, oh Wunder, genau der Binärrepräsentierung für 1 
entspricht.

: Bearbeitet durch User
von Martin F. (martin_f70)


Lesenswert?

Ist das dann so richtig? Ich bezweifle das...

ADMUX=(1<<REFS0)|(1<<ADLAR)&~(1<<MUX0)&~(1<<MUX1)|(1<<MUX2);

von Karl H. (kbuchegg)


Lesenswert?

Ich bezweifle, dass du in den letzten Wochen deine Hausaufgaben gemacht 
hast, und in Theorie und Praxis (vor allen Dingen Praxis) gelernt hast, 
wie man einzelne Bits auf 1 bzw. auf 0 setzt, bzw. dass man 0 Bits nicht 
explizit setzen muss, wenn man sowieso dem Register als ganzes etwas 
zuweist.

von Martin F. (martin_f70)


Lesenswert?

Ich habe sehrwohl Hausaufgaben gemacht, hatte nur grade eine Verwirrung 
wie man Bits auf 0 setzt, sry, danke aber

von Martin F. (martin_f70)


Lesenswert?

Eine Frage noch...wie kann ich mehrere Analoge Signale gleichzeitig 
messen?
Mit diesem Code geht das ja nicht weil halt immer nur ein bestimmter 
Port gelesen wird...?

von Cyblord -. (cyblord)


Lesenswert?

Martin Fischer schrieb:
> Eine Frage noch...wie kann ich mehrere Analoge Signale gleichzeitig
> messen?
> Mit diesem Code geht das ja nicht weil halt immer nur ein bestimmter
> Port gelesen wird...?

Wie du im Datenblatt lesen könntest, hat der AVR nur EINEN ADC. Also 
kann immer nur eine Spannung zur Zeit gemessen werden. Welche, wird mit 
einem Multiplexer davor (daher ADMUX) bestimmt.

> Ich habe sehrwohl Hausaufgaben gemacht, hatte nur grade eine Verwirrung
> wie man Bits auf 0 setzt, sry, danke aber

Und warum setzt du die Bits da oben überhaupt auf 0? Die sind nach einem 
Reset auf 0, müssen also bei Bedarf nur auf 1 gestellt werden. Außer du 
willst im Programm öfter hin und her schalten.

von Martin F. (martin_f70)


Lesenswert?

Ja, mit auf 0 setzen meine ich sie gar nicht setzen. Wenn ich sie von 1 
zu 0 setzen mag, muss ich sie ja nur löschen, oder? Und kann ich in dem 
While-Loop des Programms einfach sämtliche Angaben ändern...muss danach 
dann noch ein kurzes Delay wegen dem Hochfahren des ADC?
Und was passiert wenn ich das, was gesetzt ist (auf 1) nochmal 
setze..bleibt es 1 oder verschiebt es sich dann nochmal wegen dem 
Shift-Operator?

von Cyblord -. (cyblord)


Lesenswert?

Martin Fischer schrieb:
> Ja, mit auf 0 setzen meine ich sie gar nicht setzen.
Ein Bit ist entweder 1 oder 0. Fangen wir jetzt bei Adam und Eva an?


> Wenn ich sie von 1
> zu 0 setzen mag, muss ich sie ja nur löschen, oder?
Ja

> Und kann ich in dem
> While-Loop des Programms einfach sämtliche Angaben ändern...
Du setzt die Register auf die Werte welche du willst. Das geht 
jederzeit.

> muss danach
> dann noch ein kurzes Delay wegen dem Hochfahren des ADC?
Es steht im Datenblatt auch was dazu. Vor allem was das Ändern des ADC 
Kanals und die 1. Messung nach dem Einschalten oder die Änderung der 
Referenzspannung betrifft. Lesen bildet.

> Und was passiert wenn ich das, was gesetzt ist (auf 1) nochmal
> setze..bleibt es 1 oder verschiebt es sich dann nochmal wegen dem
> Shift-Operator?
Bleibt auf 1.
Aber du hast doch echt nix kapiert. Überleg dir doch mal selber was wann 
passiert. Der Shift Operator ist doch nur eine Konstante zur 
Ausführungszeit. Der Shiftet doch zur Laufzeit nix.

gruß cyblord

von Martin F. (martin_f70)


Lesenswert?

Ja, ich habe schon kapiert, blos halt mit Shift-Operatoren hatte ich 
mich noch nicht so intensiv wie mit den Anderen (und, oder, etc.) 
beschäftigt.
Ich suche mal im Datenblatt, hoffe dass ich es finde...

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.