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
So wie ich dein Programm verstehe (bin eher C-Programmierer), gibst du den ADC-Interrupt frei, benutzt ihn aber nicht.
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!
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
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. ...
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
> 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. ...
@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...
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
@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?
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
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!
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
>> 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. ...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.