www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Suche Komplettporgramm für ADC in C


Autor: Dominik (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
seit einigen Wochen schaue ich mir hier eure Beiträge an.
Nun bin ich zur Zeit dabei das Tut durchzuarbeiten und hänge gerade an 
dem ADC des Atmega32.
Der wird mit 16Mhz betrieben und der Vorteiler entsprechend auf 128 
gesetzt.
Der Smartprog2 dient mir hierbei als Brenner.

Jetzt hab ich das Problem das ich gerne ein Programm hätte, mit dem ich 
die Werte des ADCL Registers direkt auf einen Port ausgeben möchte.

Anbei habe ich einen Anhang über den Versuch einen Vorhandenen Quellcode 
zu nutzen.

Der Quellcode im Tut liest ja nur einen Wert aus und Speichert ihn in 
der Variablen "result".

Meine Kenntnisse in C sind nicht gerade gut, so viel sei gesagt ;)

Danke schonmal für eure Hilfe.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

was passiert wenn du das "return (0);" rausnimmst?

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
es passiert rein  gar nichts.

Die Pins 0-3 von PortB leuchten, vorher Pin 4-7.

Ich habe vergessen zu erwähnen das ich lediglich ein Poti messen will.

Auch am Poti drehen bringt nichts.

Autor: Tim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
  // Jetzt 4x die analoge Spannung and Kanal channel auslesen
  // und dann Durchschnittswert ausrechnen.
  for(i=0; i<4; i++) {
    // Eine Wandlung
    ADCSRA |= (1<<ADSC);
    // Die Wandlung abwarten
    while(ADCSRA & (1<<ADSC));
    
    resulthigh = ADCW;
  }
  // ADC wieder deaktivieren
  ADCSRA = (0<<ADEN);
  resulthigh /= 4;

Funktioniert nicht, weil bei resulthigh = ADCW; die
addition fehlt. Der Code mist 4x und überschreibt das letzte
Ergebnis immer mit dem neuen. Danach teilt er das durch 4.
Dabei kommt dann etwas zwischen 0 und 255 raus, Was ja
deutlich kleiner als 700 ist.
Mach mal resulthigh += ADCW; draus, damit der aufsummiert.
Ausserdem musst du vor den 4 Messungen noch resulthigh auf 0
Setzen, da darin ja bereits der Dummy read gespeichert ist.

Dann sollte das gehen.

wenn nicht, Prüfe mal bitte ob der ADC im 8 Bit mode Arbeitet.

Wenn du den ADC wert Binär auf einem Port sehen willst
mach in main() sowas wie

PORTB = resulthigh / 4;

(Durch 4 da der AD 0..1023 misst, dein Port aber nur 0..255 anzeigen 
kann)

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,
danke erstmal an die schnelle Hilfe. Habe ehrlich gesagt nicht damit 
gerechnet.
Werde mich heute nachmittag erst da rangeben können weil es ein Projekt 
für die Ausbildung sein soll

Autor: Dominik (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo mal wieder,
bin heute noch dazu gekommen den Vorschlag von Tim durchzugehen, 
allerdings ohne erfolg.

Das Programm habe ich angepasst, nochmal nachgeschaut ob auch alles 
richtig verkabelt ist, allerdings tut sich rein gar nichts wenn ich das 
Poti ändere.

Aber ich habe es doch richtig verstanden das das Prog immer in einer 
Endlosschleife Werte vom ADC ließt und dann an die Variable übergibt.

Vielleicht noch jemand eine andere Idee?
Habs auch schon mit nem anderen ATMEGA32 getestet ohne Erfolg.

Den Code habe ich nochmal angehangen

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier setzt Du den Kanal:
>  ADMUX = channel;
>  //AREF als Spannungsquelle des ADC
...und hier löschst Du ADMUX komplett!
>  ADMUX = (0<<REFS0) | (0<<REFS1);
>  ADMUX = (0<<ADLAR);  //ergebnis rechtsb�ndig ausrichten
Das kann man auch einfach "ADMUX = 0;" schreiben. Überlege bitte mal, 
was "0 << IRGENDWAS" ergibt...

OK, in Deinem Fall ist dieser Klops fast egal, weil sowieso Kanal 0 
gewandelt wird, aber das solltest Du in Zukunft anders machen.

Gleiches gilt natürlich für die Zeile "ADCSRA = (0 << ADEN);". Es gibt 
unendlich viele Möglichkeiten, eine Null zu schreiben, aber es gibt in 
den meisten Fällen keinen Grund, nicht die kürzeste und einfachste zu 
nehmen.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hier
> DDRA = 0xff;
...schaltet den kompletten Port A als Ausgang. Da beim ATMega32 aber 
die Analog-Eingänge an Port A liegen, ist das sehr wenig sinnvoll...

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist das "return (0);" nicht böse zur while Schleife?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast wrote:
> Ist das "return (0);" nicht böse zur while Schleife?
Richtig, das return hat in der while-Schleife nichts zu suchen!

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@johannes

So hatte ich das aus dem Tut herauskopiert. Anscheinend läuft es auch 
mit diesen Einstellungen.

Das man "0" auch anders schreiben kann vor allem in registern ist mir 
bewusst ;)
Hatte es irgendwann mal getestet und ist dann leider auch so hängen 
geblieben. Danke für den Tip.

Die Sache mit den Eingängen schalten wird es wohl sein, leider habe ich 
die sachen nicht hier.

@gast
return(0) wird in dieser Funktion nie erreicht. Man kann es genausogut 
weglassen, ändert aber beim µC gar nichts. Zumindest habe ich nix 
festgestellt.

Danke euch vielmals. Werde mich morgen wieder melden wenn ich die Sachen 
ausprobiert habe.

Autor: M. M. (miszou)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

das return(0) gehört aber nach der schließenden Klammer vom while (1), 
bzw. es gehört zum int main(void) und wird deshalb nie erreicht, weil du 
die while (1) Schleife nicht verläßt. So stehts auch im Tut.

Gruß MISZOU

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik wrote:
> @johannes
>
> So hatte ich das aus dem Tut herauskopiert. Anscheinend läuft es auch
> mit diesen Einstellungen.
Was läuft? Das Tutorial auf dieser Seite ist für einen ATMega8 
geschrieben. Bei dem liegen die Analog-Eingänge an Port C. Beim ATMega32 
sind sie an Port A, wie ein Blick ins Datenblatt auch Dir offenbaren 
wird.

> @gast
> return(0) wird in dieser Funktion nie erreicht.
Doch, in Deinem Fall wird es erreicht! Es steht in der while-Schleife 
und wird nach der if-Abfrage erreicht...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes M. wrote:

> Doch, in Deinem Fall wird es erreicht! Es steht in der while-Schleife
> und wird nach der if-Abfrage erreicht...

Und ich möchte hinzufügen: Eine vernnftige und konsistente 
Einrückstrategie hätte das auch klar und deutlich gezeigt.

Wieder mal ein Fall, indem eine saubere Codeformatierung Wunder wirken 
kann.

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich danke euch vielmals für die Hilfe.
Das Programm funktioniert nun einwandfrei.

Anbei möchte ich nochmals anmerken das ich wirklich blutiger Anfänger 
bin.
Den Code hänge ich später noch an.

Autor: Dominik (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So hier im Anhang befindet sich wie versprochen ein kleines Programm, 
mit dem der ADC in 50er Schritten jeweils eine LED weiter schaltet.

Vielen Dank nochmals für eure Hilfe

Autor: Rainer I. (raih)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Dominik,

um die ganzen if Abfragen zu vereinfachen kannst Du auch modulo rechnen.
  while(1)
  {
    PORTD = (readADC(0) % 50) + 1
  }

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rainer I. wrote:
> um die ganzen if Abfragen zu vereinfachen kannst Du auch modulo rechnen.
Wieso Modulo ? Du weißt, was Modulo macht? Hier muss, wenn überhaupt, 
dann eine normale Division her. Der Rest der Division interessiert 
hier nicht.

Autor: Rainer I. (raih)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, hast Recht. Hab mich vertan.
while(1)
  {
    PORTD = (readADC(0) / 50) + 1
  }

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit dieser Zeile geht vergleicht er immer "result" in 50er Schritten und 
addiert dann in Binärform eine LED weiter?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik wrote:
> Mit dieser Zeile geht vergleicht er immer "result" in 50er Schritten und
> addiert dann in Binärform eine LED weiter?
Genau! Er will schließlich, dass schon bei 0 < result < 50 eine LED 
leuchtet. Da käme bei der Division aber 0 raus, deshalb muss das 
Divisionsergebnis um eins erhöht werden.

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo
Habe es gerade ausprobiert.
Die Version von Johannes Funktioniert super.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik wrote:
> Die Version von Johannes Funktioniert super.
Welche Version von mir?

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
while(1)
  {
    PORTD = (readADC(0) / 50) + 1
  }

;)

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik wrote:
> while(1)
>   {
>     PORTD = (readADC(0) / 50) + 1
>   }
>
Naja, geschrieben hat es Rainer, nur die Korrektur kam von mir...

Autor: Dominik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja gut
an alle ein Dankeschön

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe hierzu mal eine frage:

wenn ich AREF mit VCC verbinde und ADMUX = 0 setze funktioniert mein 
programm nicht mehr, setze ich ADMUX = (1<<REFS0) funktioniert es. woran 
liegt das? muss ich AREF überhaupt mit VCC verbinden?

VCC = 5 V bei einem ATMEGA168

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast wrote:
> wenn ich AREF mit VCC verbinde und ADMUX = 0 setze funktioniert mein
> programm nicht mehr, setze ich ADMUX = (1<<REFS0) funktioniert es. woran
> liegt das? muss ich AREF überhaupt mit VCC verbinden?
Das musst Du nicht nur nicht tun, das solltest Du sogar besser sein 
lassen!

AREF ist ausschließlich zum Anschließen einer Referenzspannung, die 
nicht vom Controller intern zur Verfügung gestellt werden kann. AVCC 
kann aber intern ausgewählt werden.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gut danke erstmal. also löte ich das wieder ab und lasse AREF frei oder 
muss ich den irgendwie beschalten? ich werde dann VCC und AVCC mit 5V 
beschalten und dann ADMUX = 0 setzen. an meinen ADC eingängen hängt ein 
10 kohm poti mit max 5V dran. gibts daran was zu verändern? ich will 
werte von 0 - kleiner 5V einlesen.

achso: ich hatte mal einen schaltplan gesehen, wo AREF mit VCC über eine 
induktivität (10µH?) miteinander verbunden war. was spricht den 
eigentlich dagegen?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast wrote:
> gut danke erstmal. also löte ich das wieder ab und lasse AREF frei oder
> muss ich den irgendwie beschalten?
An AREF normalerweise 100 nF gegen GND.

> ich werde dann VCC und AVCC mit 5V
> beschalten und dann ADMUX = 0 setzen. an meinen ADC eingängen hängt ein
> 10 kohm poti mit max 5V dran. gibts daran was zu verändern? ich will
> werte von 0 - kleiner 5V einlesen.
Wenn das Poti auch an AVCC hängt, ist das kein Problem.

> achso: ich hatte mal einen schaltplan gesehen, wo AREF mit VCC über eine
> induktivität (10µH?) miteinander verbunden war. was spricht den
> eigentlich dagegen?
Wo hast Du das denn gesehen? Normalerweise wird AVCC mit VCC über 
einen LC-Tiefpass verbunden. AREF sollte mit einem 100nF-Kondensator 
nach GND beschaltet werden, sonst nichts, außer Du willst eine externe 
Referenzquelle verwenden. Gegen eine Verbindung von AREF und AVCC 
spricht (neben der o.g. Sinnlosigkeit) auch, dass man ja vielleicht auch 
mal eine andere Referenzquelle auswählen möchte, was dann nicht mehr 
geht.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.