Forum: Mikrocontroller und Digitale Elektronik Wiederstandsmessung mit ATmega16


von Simon S. (simschmid)


Lesenswert?

Meine Aufgabenstellung ist eigentlich ganz simpel.

Poti an Eingang A des ATmega16 und Binärwert am Ausgang B.

Nun wie muss ich aber den AVR konfigurieren, dass er mir den
analog Wert des ADCs am Ausgang B als Binärwert angiebt?

von Magnus Müller (Gast)


Lesenswert?

Simon Schmid wrote:
> Nun wie muss ich aber den AVR konfigurieren, dass er mir den
> analog Wert des ADCs am Ausgang B als Binärwert angiebt?

Nicht konfigurieren... Programm schreiben(!).

Hast du schon mal einen Blick ins Datenblatt des mega16 geworfen? Da 
stehen sogar kleine Beispielcodes für die Verwendung des ADCs drin.

Gruß,
Magnetus

von Magnus Müller (Gast)


Lesenswert?

Magnus Müller wrote:
> Da stehen sogar kleine Beispielcodes für die Verwendung des ADCs drin.

Ups... hab ich meine Klappe wieder zu früh aufgemacht... da steht gar 
kein Beispielcode drin :(

Sorry

von Simon S. (simschmid)


Lesenswert?

Danke Magnus.

Es steht ja schon was Kleines drin. Aber ich kann halt all die 
Grundlagen noch nicht so. Hab erst ein paar Beispiele aus dem Tutorial 
programmiert.

Also so wie ich das versteh, muesst man lediglich den ADC aktivieren, 
den Kanal angeben und dann wahrscheinlich mit einem Interrupt arbeiten. 
So dass der Wert bei einer Aenderung in ein Register geschrieben wird. 
Dieses Register wird dann am Port B ausgegeben.

Kenn hier jemand ein kleines Programm in ASSAMBLER oder C?

von ab cd (Gast)


Lesenswert?

es herrscht ein gewisser Wiederstand hier ;-)

von Magnus Müller (Gast)


Lesenswert?

Simon Schmid wrote:
> Also so wie ich das versteh, muesst man lediglich den ADC aktivieren,
> den Kanal angeben und dann wahrscheinlich mit einem Interrupt arbeiten.

Den Interrupt musst du nicht unbedingt verwenden. Man kann den ADC auch 
einfach "freilaufend" arbeiten lassen. Der ADC wandelt sich dann zwar 
dumm und dusselig aber wenn du das ADC-Datenregister ausliest hast du 
immer den aktuellsten Wert. Diesen musst du dann nur noch am Port B 
ausgeben.

Gruß,
Magnetus

von Simon S. (simschmid)


Lesenswert?

Magnus Müller wrote:
> Den Interrupt musst du nicht unbedingt verwenden. Man kann den ADC auch
> einfach "freilaufend" arbeiten lassen.

So habe ich das im Tutorial auch verstanden.
Nun, ich mach mich mit dem Tutorial mal ans Programmieren.
Die Befehle sind ja zwar fuer den AT90S8535 weiss nicht,
ob die auch fuer den ATmega16L gelten.

Poste bald meinen Code. Bin gespannt ob ich das so gleich kann, hab bis 
jetzt nur mit ASSAMBLER Codes gearbeitet, nicht mit C.

to be continued ...

von Simon S. (simschmid)


Angehängte Dateien:

Lesenswert?

Ich etwas programmiert, gemaess Tutorial und ATmega16L Description.

Der Aufbau mit dem STK500 sieht folgendermassen aus:

Am Port A Liegt ein 20kOhm Poti. Schleifer direkt am Eingang A, Bit 0.
Eine Seite Masse, die andere Seite via 330 Ohm an Vcc.

Die Leds sind an Port B und zeigen nach Laden des Programms immer den
Wert, der in Zeile 10 definiert wird.
Aber eigentlich muesste doch der 8Bit Wert von ADCL angezeigt werden.

Kann mir jemand weiterhelfen, wo der Fehler liegt?

Ich habe anstelle des Potis auch die Switches des STK500 angehaengt, 
muesste ja eigentlich auch gehen.

von Magnus Müller (Gast)


Lesenswert?

Zitat aus dem Datenblatt:

"If the result is left adjusted and no more than 8-bit precision is 
required, it is sufficient to read ADCH. Otherwise, ADCL must be read 
first, then ADCH, to ensure that the content of the Data Registers 
belongs to the same conversion. Once ADCL is read, ADC access to Data 
Registers is blocked. This means that if ADCL has been read, and a 
conversion completes before ADCH is read, neither register is updated 
and the result from the conversion is lost. When ADCH is read, ADC 
access to the ADCH and ADCL Registers is
re-enabled."

Du liest in deinem Programm immer nur ADCL aus. Wenn du danach nicht 
auch ADCH ausliest bleibt das ADCL und ADCH-Register des µCs für neue 
Werte gesperrt.

Da du ja sowieso nur 8 Bits verwendest, könntest du den ADC so 
konfigurieren, dass er das Ergebnis "left adjusted" ausgibt. Du kannst 
dann die 8 MSBs direkt über ADCH auslesen. Ein Lesezugriff auf ADCH gibt 
immer auch die beiden Register (ADCH und ADCL) wieder für neue 
Wandlungsergebnisse frei.

Gruß,
Magnetus

von André (Gast)


Lesenswert?

Servus,

ich lerne auch gerade, mit der Hilfe eines Forenmitglieds, 
AVR-Assembler. Dabei verwende auch ich den ADC. So wie du das mit dem 
sbi ADCSR, ADSC machst funktioniert das wohl nicht. Das hatte ich auch 
probiert. Schreibst du aber:
ldi  temp, (1<<ADEN) | (1<<ADSC) | (1<<ADIE)
out  ADCSR, temp
Dann werden die Bits wohl richtig gesetzt. Wenn du mit dem AVR Studio 
programmierst, dann wird dir nach dem Drücken von F7 auch angezeigt, an 
welcher Stelle es hakt und auch was nicht in Ordnung ist.

Gruß, André

von Simon S. (simschmid)


Lesenswert?

könnt ihr mir ein code beispiel geben?

ich habe
ldi  temp, (1<<ADEN) | (1<<ADSC) | (1<<ADIE)
out  ADCSR, temp
eingefuegt und nun gibt's beim kompilieren auch keine fehler mehr.

jedoch, wie kann ich im avr studio einen analog wert am adc simulieren, 
um zu sehen das sich an port b etwas tut?

und es gibt doch einen befehl um die ersten und zweiten 8bit in ein 
register zu fuehren. muesste ich nicht das hier machen?

von André (Gast)


Lesenswert?

Wie wäre es mit:

mov temp, ADCH

oder

in temp, ADCH

und dran denken, erst ADCL, dann ADCH auslesen, wenn du im FreeRunning 
arbeitest ist das besonders wichtig, sonst geht gar nichts mehr ;)

Gruß, André

von Karl heinz B. (kbucheg)


Lesenswert?

Den Free Running brauchst du aber gar nicht,
wenn du sowieso jede Messung einzeln startest.
Free Running benutzt man eigentlich nur dann, wenn
der ADC ständig sampeln soll und einen Interrupt
auslösen soll wenn er mit einer Messung fertig ist.

von Simon S. (simschmid)


Lesenswert?

Ich habe nun den Code wie André beschrieben hat abgeändert, heisst, ich 
lese mit in temp, ADCL und in temp, ADCH den Digitalen Wert des Potis 
ein.

ADCL gebe ich an die Leds an PORT B und die Flackern dann auch ganz 
schön.

Nun, möchte ich gerne den eingestellten Wert vergleichen mit einem 
Vorgegebenen und dann über drei LEDS an PORT B  anzeigen, ob der 
Potiwert kleiner, gleich oder grösser ist als der Vorgegebene.

PS. Könnt ihr ein Buch empfehlen, um AVR und Assembler zu lernen, oder 
ist C besser?

von Simon S. (simschmid)


Lesenswert?

Ich hab das mit dem Vergleich nun so geloest:

    in temp, ADCL
    in temp2, ADCH

    cpi temp, 0b00111111
    brlo kleiner
    cpi temp, 0b00111111
    breq gleich
    cpi temp2,0b00111111
    brlo groesser

nun hab ich natuerlich das problem, das BIT 9 und 10 des Wertes nicht 
beruecksichtigt werden.

koennt ihr mir helfen, wie ich ADCH und ADCL zusammen führen und als 
10Bit Wert vergleichen kann?

Obiger Code funktionert, aber natuerlich kommt er waehrend des Poti 
durchgangs mindesten 6 mal vor.

ich bin nun meinem ziel aber schon recht nahe:

also nächstes hänge ich zwei transistoren an die Leds 'grösser' und 
'kleiner' und dann sollte das motorisierte poti auf knopfdruck immer 
zurueck an seine stelle fahren.

von Simon S. (simschmid)


Angehängte Dateien:

Lesenswert?

Nun habe ich den Motor des Volume Potis (Motorisiertes ALPS Poti) über 2 
Transistoren (2N2222, lagen gerade rum) an die Pins Bit1 und Bit2 des 
Ports A gehängt.

Wenn das Poti nun nicht mehr auf seiner "Sollwert-Position" steht, dreht 
es der AVR automatisch an seinen "Sollwert-Position" zurueck.


Nun habe ich versucht über die Taster an Port C eine manuelle Korrektur 
zu erzwingen.
Heisst:

Taste 1 Poti Volume up
Taste 2 Poti Volume down

Programmiert habe ich es über:


       sbis PINC, 0
       rjmp kleiner

       sbis PINC, 2
       rjmp groesser

Das Problem war nun, dass nach dem Laden/Reset, das Poti immer an den 
Endanschlag drehte, auch wenn keine Taste gedrueckt wurde.

Koennt ihr mir helfen, wie ich am besten eine Taste abfrage und dann 
wenn sie gedrueckt wird einen rjmp zur Routine ausloese?

von räschtschraipunk (Gast)


Lesenswert?

"Widerstand" und NICHT "Wiederstand"

mahlzeit!!!

von André B. (cassiopaya8)


Lesenswert?

Du musst nach dem Reset einfach erst einmal für definierte Zustände 
sorgen. Musst dir verstellen dass du aus dem Schlaf wach wirst und alles 
um dich herum ist in Hektik. Also musst du dir erst einmal eine 
Übersicht verschaffen. So auch hier. Nach dem Reset musst du für einen 
Ausgangszustand sorgen, von dem aus dann der eigentliche Programmablauf 
aus gestartet wird.

Gruß, André

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.