Forum: Mikrocontroller und Digitale Elektronik Probleme mit AD-Wandler im Atmega 32


von Moritz M. (hvgguser)


Angehängte Dateien:

Lesenswert?

Hallo ich bin gerade dabei mir einen Midicontroller zu bauen und möchte
natürlich auch ein paar Potis mit einbauen. Ich habe mal zum testen ein
einfaches Programm geschrieben mit dem ich ein Poti auslese und per midi
die Daten versende. Wenn ich jetzt aber das Programm simuliere bzw. auf
den AVR spiele bleibt das Programm an der Stelle hängen wo ich die
Daten von der AD-Wandlung auslesen will. Ich habe keine Ahnung woran es
liegt. Bitte helft mir. Es ist leider das erste mal das ich den
AD-Wandler benutze und somit habe ich damit auch keine Erfahrung.
Danke schonmal jetzt.

Mfg Moritz

von inoffizieller WM-Rahul (Gast)


Lesenswert?

So wie ich dein Programm verstehe (bin eher C-Programmierer), gibst du
den ADC-Interrupt frei, benutzt ihn aber nicht.

von johnny.m (Gast)


Lesenswert?

Wenn das oberhalb von "initial" die ADC-Interrupt-Routine sein soll
(was ich mal annehme), dann schickst Du den ADC, wenn ein Ergebnis
vorliegt (dann wird die ISR ja aufgerufen) in den Sleep- bzw.
Noise-Reduction Mode, ohne vorher das Ergebnis auszulesen! Dann macht
er natürlich nix mehr. Wenn Du im Hauptprogramm den ADC inkl. Noise
Reduction startest, brauchst Du in der ISR nur noch das ADCH auszulesen
(bzw. eigentlich brauchst Du in der ISR gar nichts zu machen, da der
Interrupt ja nur dazu dient, ihn aus dem Sleep zu holen, das Auslesen
von ADCH machste ja schon im HP). Dann geht's zurück ins Hauptprogramm
und das ermittelte Eregbnis kann ausgewertet werden. Dann die Schleife
und das Ganze von vorne. Du darfst den µC halt nicht in der ISR in den
Schlaf schicken!

von Moritz M. (hvgguser)


Angehängte Dateien:

Lesenswert?

Also müsste das Ganze so aussehen?
Geht so aber auch nicht. Ich stehe irgendwie auf dem Schlauch. Wäre
vielleicht ganz hilfreich für mich wenn ihr mir ein kurzes Codebeispiel
geben könntet (Code so ändern das er funktioniert).

Bitte helft mir.

Mfg Moritz

von Hannes L. (hannes)


Lesenswert?

Schau mal hier:
http://www.hanneslux.de/avr/mobau/7ksend/7ksend02.html
Da findest du auch noch andere wertvolle Hinweise zur
Programmgestaltung, nicht nur zum ADC.
Auch hier:
http://www.hanneslux.de/avr/divers/melody/index.html
wird (teilweise) mit dem ADC gearbeitet. Beides ist leider nicht mit
Mega32, was aber nur daran liegt, dass ich nicht gerne mit Kanonen auf
Spatzen schieße.

...

von Moritz M. (hvgguser)


Angehängte Dateien:

Lesenswert?

So ich habe jetzt das Programm nach den Informationen von HanneS
modifiziert, aber es funktioniert immer noch nicht. Ich bin am
verzweifeln!!!

Bitte, bitte helft mir.

Mfg Moritz

von Hannes L. (hannes)


Lesenswert?

> ich habe jetzt das Programm nach den Informationen von HanneS
> modifiziert,

Das glaube ich nicht. Das Programm ist verdammt weit von meinem Stil
entfernt.
Das geht schon mit der Formatierung des Programmtextes los (Lesbarkeit,
Kommentare), dann gibt es bei mir grundsätzlich die komplette
Interrupt-Sprungtabelle. Weiterhin kommt bei mir kein Programm dieser
Größenordnung ohne Timer-Interrupt aus. Auch gibt es bei mir keine
Programmroutinen im Interrupt-Vektor-Bereich des Programmspeichers...
Das alles sind aber keine Gründe, warum Dein Programm nicht
funktionieren sollte, es ist lediglich nicht mein Stil.

Dann fällt mir auf:
- Du schaltest in der ISR den ADC aus. Da Du single-Conversion
eingestellt hattest, schaltet der sich selbst aus.
- Du nutzt in der ISR das Register tmp, aber auch in der loop. Was
passiert eigentlich, wenn die ISR genau zwischen ldi tmp und out
MCUCR,tmp zuschlägt?
- Du stellst in loop andauernd den Sleep-Mode ein. Wozu? Der Sleepmode
wird durch SLEEP nicht verändert.
- Du schaltest in der ISR den ADC aus, Du hast in loop einen Kommentar,
dass Du den ADC startest, startest ihn aber nicht. Das Programm geht
pennen und wacht nie wieder auf...

Wenn es nur darum geht, den Potiwert (0..127) als MIDI-Parameter zu
senden, dann brauchst Du keinen ADC-Interrupt. Es genügt, den ADC im
FreeRun-Mode laufen zu lassen und vor Senden des MIDI-Datenbytes den
ADC-Wert einzulesen und durch 2 zu teilen. Du musst dabei (wenn nur ein
ADC-Kanal genutzt wird) nichtmal sicherstellen, dass der ADC auch schon
einen neuen Wert ermittelt hat.

Aber ich glaube nicht, dass Du dir den MIDI-Kanal zumüllen willst,
indem Du immer den selben Wert überträgst. Du müsstest also eine
Hysterese einbauen, die die unterschiedlichen Werte bei unverändertem
Poti ausfiltert. Dann brauchst Du eine Erkennung, ob sich der Wert
wirklich geändert hat und ob der neue Wert inzwischen stabil anliegt.
Erst dann solltest Du das MIDI-Telegramm generieren und absenden.

Da ich vermute, dass Du später mal mehrere Potis mit den ADC-Kanälen
abfragen willst, rate ich dazu, im SRAM einige Bytes für die ADC-Werte
zu reservieren. Dann im ADC-Interrupt den gelesenen Wert in die zur
Messquelle gehörenden RAM-Zelle schreiben, dann die nächste Messquelle
(ADMUX) einschalten und den ADC erneut starten (ADSC setzen). Somit
werden im Interrupt nacheinander alle ADC-Eingänge eingelesen und ins
RAM gelegt. Diese können dann von der Mainloop ausgewertet, bearbeitet
und versendet werden.

...

von johnny.m (Gast)


Lesenswert?

@Hannes:

> Du hast in loop einen Kommentar, dass Du den ADC startest, startest
> ihn aber nicht.

Afaik wird der ADC aber, wenn ADC Noise Reduction Mode eingestellt ist,
bei Ausführen der sleep-Instruktion automatisch gestartet. Zumindest das
scheint also korrekt zu sein...

von Dennis Kleine-Beck (Gast)


Lesenswert?

Hallo,

an welcher Stelle wird ADCL gelesen? IMHO garnicht. Könnte es evtl.
daran liegen (ich weiß, dass es laut Spec. ausreicht, ADCH zu lesen,
wenn man nicht mehr Auflösung wünscht, und das Ergebnis "left adjusted
ist").

Gruß,
Dennis

von johnny.m (Gast)


Lesenswert?

@Dennis:
Wenn er nur 8 Bit braucht und "left adjust" eingestellt hat (was der
Fall ist), wieso sollte es dann irgendwas bringen, ADCL zu lesen?

von Dennis Kleine-Beck (Gast)


Lesenswert?

Das ist wie mit den Pferden vor den Apotheken ;-)

Ne, keine Ahnung, ist nur so ein Gedanke und ja auch relative schnell
und einfach zu testen.
Finde nur komisch, dass es offenbar genau an der Stelle

"in ain, ADCH"

hängt.

Dennis

von johnny.m (Gast)


Lesenswert?

Ich vermute, er hängt eher davor, also wacht nicht auf...

Wenn ein Befehl ausgeführt wird, wird der Programmzähler erhöht, so
dass im Simulator auf den nächsten Befehl gezeigt wird. "sleep" wird
noch ausgeführt, "in ain, ADCH" allerdings nicht mehr, d.h. er kommt
gar nicht erst so weit!

von Dennis Kleine-Beck (Gast)


Lesenswert?

Ja, klingt plausibel.
Persönlich ziehe ich es vor, in "Hardware" z.B. eine LED an der
betreffenden Stelle umzuschalten, oder über die Stromaufnahme auf den
Sleepmodus zu schließen. Damit kann man sehr schön eingrenzen, wo es
hängt (und es macht mir persönlich mehr Spaß, als der Simulator. Bin
aber auch eher aus Spaß am "Basteln" dabei ;-))

Dennis

von Hannes L. (hannes)


Lesenswert?

>> Afaik wird der ADC aber, wenn ADC Noise Reduction Mode eingestellt
ist,
bei Ausführen der sleep-Instruktion automatisch gestartet. Zumindest
das
scheint also korrekt zu sein...<<

Das ist durchaus möglich. Aber schau Dir mal (in den Datenblättern) das
Verhalten des ADCs bei den verschiedenen AVRs an, da wirst Du sehen,
dass das von Typ zu Typ unterschiedlich gehandhabt wird. Da nun der
Mega32 nicht gerade mein Lieblingstyp ist (wegen Kanonen und Spatzen)
ist es durchaus möglich, dass ich hier irre.

Andererseits kann der ADC durch den Aufruf von Sleep nicht gestartet
werden, weil er in der ISR deaktiviert wurde. Zum Start der Conversion
per Sleep muss ja zumindest ADEN aktiv sein, das wurde aber in der ISR
gelöscht.

Die LED zum Debuggen benutze ich auch gerne. Ich nutze sie inzwischen
auch gerne zum Ausmessen der Prozessorauslastung indem ich vor SLEEP
die LED ausschalte und in jeder ISR wieder an. So kann ich mit dem
Frequenzzähler eines Multimeters (Tastgradmessung) die Auslastung des
Prozessors bestimmen.

Was ich oben noch vergaß: Üblicherweise wird in jeder ISR das SREG
gesichert. Das ist in diesem Fall zwar nicht nötig, da in der ISR
(noch) keine Flags verändert werden. Es wird aber gern vergessen, wenn
die ISR dann größer wird.

...

von Moritz M. (hvgguser)


Lesenswert?

Danke für die vielen Antworten.
Jetzt habe ich es endlich hinbekommen. Danke übrigens auch für die Idee
mit dem SRAM.

Mfg Moritz

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.