www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Soft-PWM und AD-Wandler parallel


Autor: Martin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 :-)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
void my_delay( int time )
{
  int i;
  for( i = 0; i < time; ++i )
    _delay_ms( 1 );
}

und dann diese Funktion anstelle von
   _delay_ms( dauer );

aufrufen.

Du kannst aber auch die ADC Abfrage mit in diese Wartefunktion aufnehmen
void my_delay()
{
  int time = AD_Wandlung();
  int i;

  for( i = 0; i < time; ++i )
    _delay_ms( 1 );
}

Autor: Zaphod Beeblebrox (brezel) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Zaphod Beeblebrox (brezel) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 -.-

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.