Hallo, ich habe mir eine RGB Leiste besorgt und betreibe sie an einem Atmega 8 (interner Takt 8MHz) + IRLZ34N MOSFETs per Soft PWM. Die Soft-PWM habe ich von http://www.mikrocontroller.net/articles/Soft-PWM weitestgehend übernommen und angepasst. Das Programm (siehe Anhang) blendet bis jetzt die verschiedenen Farben ineinander über. Soweit so gut. Nun möchte ich über einen Poti der am AD-Wandler angeschlossen ist die Geschwindigkeit des Farbwechsels bestimmen und dass wenn der Poti auf "ganz langsamm" steht, die aktuelle Farbe beibehalten wird, spricht der Farbwechsel erst weiter geht wenn der Poti wieder auf "schneller" gestellt wird. Die AD Wandlung an sich funktioniert auch. Das Problem, das ich habe ist folgendes: Es wird für die Soft-PWM regelmäßig ein Interrupt ausgelöst, jetzt müsste aber gleichzeitig, kontinuierlich der AD-Wandler abgefragt werden. Zu Beginn habe ich versucht die AD Wandlung in den Interrupt mit einzubinden, jedoch flackern dann die LED's... anscheinend dauert die Wandlung zu lange. Die AD Wandlung in einen zweiten Interrupt einbinden? Für Lösungsansätze wäre ich euch sehr dankbar. Oder ist mein Vorhaben in der Art gar nicht realisierbar? Schon mal Danke für euere Mühe.
Martin schrieb: > Das Problem, das ich habe ist folgendes: Es wird für die Soft-PWM > regelmäßig ein Interrupt ausgelöst, jetzt müsste aber gleichzeitig, > kontinuierlich der AD-Wandler abgefragt werden. Du brauchst den AD-Wandler nicht kontinuierlich abfragen. Wenn der ADC in der Sekunde vielleicht 100 mal drann kommt reicht das völlig aus. Du könntest zb anstatt dem _delay_ms(1) in den for-Schleifen jeweils eine ADC Wandlung machen und abhängig vom ADC Wert noch zusätzliche Wartezeit drannhängen. Ob dein µC im _delay Däumchen dreht oder den ADC befragt ist ja dem µC wieder egal
Martin schrieb: > Für Lösungsansätze wäre ich euch sehr dankbar. Oder ist mein Vorhaben in > der Art gar nicht realisierbar? Solange die meiste Rechenzeit in einem Programm für _delay_ms draufgeht, gibt es immer eine andere Lösung :-)
Ich weiß jetzt nicht, ob es zeitlich passt, aber eventuell geht es auf, wenn man im Interrupt am Ende die AD-Wandlung startet und beim nächsten Mal dann das Ergebnis holt.
Ach und noch was: Du darfst bei _delay_ms keine Variablen benutzen. Das Argument zu _delay_ms muss eine Konstante sein, ansonsten stimmen die Zeiten hinten und vorne nicht. Du kannst das so lösen
1 | void my_delay( int time ) |
2 | {
|
3 | int i; |
4 | for( i = 0; i < time; ++i ) |
5 | _delay_ms( 1 ); |
6 | }
|
und dann diese Funktion anstelle von
1 | _delay_ms( dauer ); |
aufrufen. Du kannst aber auch die ADC Abfrage mit in diese Wartefunktion aufnehmen
1 | void my_delay() |
2 | {
|
3 | int time = AD_Wandlung(); |
4 | int i; |
5 | |
6 | for( i = 0; i < time; ++i ) |
7 | _delay_ms( 1 ); |
8 | }
|
Klaus Wachtler schrieb: > Ich weiß jetzt nicht, ob es zeitlich passt, aber eventuell > geht es auf, wenn man im Interrupt am Ende die AD-Wandlung > startet und beim nächsten Mal dann das Ergebnis holt. wozu den Aufwand? Tu uns allen und dir selber doch bitte den gefallen und rücke deinen Quelltext richtig schön ein und pack die #defines an den Anfang, danke! Nimms mir nicht bitte nicht übel, aber den Arschlochkommentar konnte ich mir nicht verkneifen ;) Und noch was Konstruktives von mir: mach in deine Endlosschleife statt "_delay_ms(dauer)" einfach "_delay_ms(AD_Wandlung())" bzw "_delay_ms(AD_Wandlung() * (long)dauer / 1024)" rein.
Karl heinz Buchegger schrieb: > Du darfst bei _delay_ms keine Variablen benutzen. Das Argument zu > _delay_ms muss eine Konstante sein, ansonsten stimmen die Zeiten hinten > und vorne nicht. mist. Dann eben so -.-
Vielen Dank für eure sehr schnellen und vorallem hilfreichen Antworten. Ich habe das ganze nun mit der Funktion void my_delay() { int time = AD_Wandlung(); int i; for( i = 0; i < time; ++i ) _delay_ms( 1 ); while(time > 585) //Zum anhalten der Farbe, AD Wandlung max = 600 { time = AD_Wandlung(); _delay_ms( 20 ); } } (Tipp von Karl Heinz Buchegger) Funktioniert einwandfrei.
Nun habe ich allerdings noch ein paar Verständnis fragen an euch. Karl heinz Buchegger schrieb: > Du darfst bei _delay_ms keine Variablen benutzen. Das Argument zu > _delay_ms muss eine Konstante sein, ansonsten stimmen die Zeiten hinten > und vorne nicht. Der Prototyp der Funktion sieht doch so aus: void _delay_ms(double __ms) Warum kann ich keine double Variable übergeben sondern nur eine Konstante? Und die zweite Frage, warum muss ich den Interrupt nicht mit cli(); vor der AD Wandlung unterbrechen? Kann es so nicht Probleme geben, wenn während einer Wandlung der Interrupt zuschlägt? Nochmal Danke für eure Hilfe.
Martin schrieb: > Nun habe ich allerdings noch ein paar Verständnis fragen an euch. > > Karl heinz Buchegger schrieb: >> Du darfst bei _delay_ms keine Variablen benutzen. Das Argument zu >> _delay_ms muss eine Konstante sein, ansonsten stimmen die Zeiten hinten >> und vorne nicht. > > Der Prototyp der Funktion sieht doch so aus: void _delay_ms(double > __ms) > > Warum kann ich keine double Variable übergeben sondern nur eine > Konstante? Weil diese Zeit in eine Berechnungsformel eingeht, aus der die Anzahl von Schleifenwiederholungen hervorgeht. Diese Berechnung ist eine Floting Point Berechnung und es ist wichtig, dass der Optimizer diese Berechnung optimieren kann, so dass er zum Schluss nur mit einem Zahlenwert da steht. Das geht aber nur dann, wenn er auch alle Zahlen während des Compilierens kennt. Kann der Optimizer die Berechnungsformel nicht während des Compilierens auflösen, so muss das zur Laufzeit gemacht werden. Und bei kleineren Wartezeiten ist es nicht ungewöhnlich, dass dann diese Berechnung schon länger dauert, als das Abarbeiten der daraus berechneten Schleifenwiederholungen. :-) > Und die zweite Frage, warum muss ich den Interrupt nicht mit cli(); vor > der AD Wandlung unterbrechen? Kann es so nicht Probleme geben, wenn > während einer Wandlung der Interrupt zuschlägt? Während eine ISR läuft, sind Interrupts sowieso automatisch gesperrt. Wenn du dich da mit cli() / sei() einmischt machst du die Dinge im Extremfall nur schlimmer, weil dann durch den sei() die Interrupts zu früh freigegben werden.
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.