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
voidmy_delay(inttime)
2
{
3
inti;
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
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.
Eine eigene Frage?
Dieser Thread ist über 16 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.