www.mikrocontroller.net

Forum: Compiler & IDEs LED in abhänigkeit der gemessenen analog Spg. blinken lassen?


Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich messe mit einem ATTiny eine analog Spannung. Am Port PB0 ist eine 
LED angeschossen die in Abhängigkeit der gemessenen Spg. unterschiedlich 
schnell blinken soll. Zur Binkzeit möchte ich den Timer1 Interupt 
verwenden.

Einfache Blinken geht gut in dem ich in der ISR einfach zähle und den 
Port mittels Case Ein/Ausschalte

  //LED 3
  case 150: if (Blink == 1) PORTB &= ~(1<<PB0); break;       // EIN

  case 155: if (Blink == 1) PORTB |= (1<<PB0);  break;       // AUS

        case 170: if (Blink == 1) PORTB &= ~(1<<PB0); break;       // 
EIN

  case 175: if (Blink == 1) PORTB |= (1<<PB0);  break;       // AUS

aber wie kann ich es umsetzten dass ich je nach Schwelle der Messspg. 
unterschiedliche Blinkfrequenzen erzeugen kann?

Gruss Patrick

Autor: Bernhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

das einfachste wär wohl den TimerCompare Value
zu verändern, wenn ein entsprechender Wert unter/überschritten wurde.

Einfach in Software den A/D pollen und los geht der Spaß

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

Bewertung
0 lesenswert
nicht lesenswert
Patrick wrote:

> aber wie kann ich es umsetzten dass ich je nach Schwelle der Messspg.
> unterschiedliche Blinkfrequenzen erzeugen kann?

2 Möglichkeiten:

* Entweder du hältst die Schwellwerte variabel.
  Damit musst du dein switch-case Konstrukt durch eine if - else if
  Leiter ersetzen, weil man ja in einem switch-case bei den case
  Fällen keine Variablen angeben kann

  Irgendwas in der Art
              
  if( Blink == 1 ) {     // diese Abfrage zieh ich mal vor, da sie in
                         // deinen case Fällen anscheinend in jedem
                         // case vorkommt
   if( TimerWert == OnTime1 )
     PORTB &= ~(1<<PB0);

   else if( TimerWert == OffTime1 )
     PORTB |= (1<<PB0);

   else if( TimerWert == OnTime2 )
     PORTB &= ~(1<<PB0);

   else if( TimerWert == OffTime2 )
     PORTB |= (1<<PB0);
  }

Durch Verändern von OnTime1/OffTime1 bzw. OnTime2/OffTime2 kannst
du jetzt die Frequenz deiner Blinkerei beeinflussen.

Jetzt kann man natürlich noch die ganzen Ein/Aus Fälle zusammenfassen
  if( Blink == 1 ) {     // diese Abfrage zieh ich mal vor, da sie in
                         // deinen case Fällen anscheinend in jedem
                         // case vorkommt
   if( TimerWert == OnTime1 || TimerWert == OnTime2 )
     PORTB &= ~(1<<PB0);

   else if( TimerWert == OffTime1 || TimerWert == OffTime2 )
     PORTB |= (1<<PB0);
  }

  Wenn dein obiger Programmausschnitt nur ein Teil deiner switch-case
  Struktur ist, und das in Wirklichkeit noch weiter geht, dann könnte
  man auch darüber nachdenken, ob es nicht eine Formel für den
  Zusammenhang zwischen Zählerstand bei Ein und dem aktuellen 
Zählerstand
  gibt.

* Möglichkeit 2
  benutzt einen anderen Timer Mode. CTC (Clear Timer on Compare).
  Dort kannst du dem Timer explizit vorgeben, wie weit er zählen soll
  bevor der Interrupt ausgelöst wird.
  Manipulierst du diese Obergrenze, dann kommt der Interrupt häufiger
  bzw. weniger häufig.

Autor: Random ... (thorstendb) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ne einfache Lösung (ohne ISR), als Anregung gegen die ganzen if(...):
int toggle=0, adc=0;

while(1)
{
    adc = read_adc(channel);

    if(toggle) toggle=0;
    else toggle=1;

    led(toggle << (LED_PIN));

    delay(adc);   // oder hiermit den timer neu aufziehen
}

Oder den Kram ähnlich in ne ISR eines Timers stecken.

Wenn der Duty Cycle des Blinkens 50% ist, dann einfach nen 8Bit Timer 
(mit Prescaler) aufziehen und das obige in ne ISR.
Die AD-Abfrage am besten rausnehmen und in den unkritischen Teil der 
Main packen (mit globaler Var.) da die zeit kostet.



Greetz,
/r.

Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl-Heinz,

danke für die Tipps.. ich werd mal in mich gehen und überlegen wie man 
dies am besten umsetzen kann.

herzlichen Dank

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.