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


von Patrick (Gast)


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

von Bernhard (Gast)


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ß

von Karl H. (kbuchegg)


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
1
              
2
  if( Blink == 1 ) {     // diese Abfrage zieh ich mal vor, da sie in
3
                         // deinen case Fällen anscheinend in jedem
4
                         // case vorkommt
5
   if( TimerWert == OnTime1 )
6
     PORTB &= ~(1<<PB0);
7
8
   else if( TimerWert == OffTime1 )
9
     PORTB |= (1<<PB0);
10
11
   else if( TimerWert == OnTime2 )
12
     PORTB &= ~(1<<PB0);
13
14
   else if( TimerWert == OffTime2 )
15
     PORTB |= (1<<PB0);
16
  }

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
1
  if( Blink == 1 ) {     // diese Abfrage zieh ich mal vor, da sie in
2
                         // deinen case Fällen anscheinend in jedem
3
                         // case vorkommt
4
   if( TimerWert == OnTime1 || TimerWert == OnTime2 )
5
     PORTB &= ~(1<<PB0);
6
7
   else if( TimerWert == OffTime1 || TimerWert == OffTime2 )
8
     PORTB |= (1<<PB0);
9
  }

  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.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Ne einfache Lösung (ohne ISR), als Anregung gegen die ganzen if(...):
1
int toggle=0, adc=0;
2
3
while(1)
4
{
5
    adc = read_adc(channel);
6
7
    if(toggle) toggle=0;
8
    else toggle=1;
9
10
    led(toggle << (LED_PIN));
11
12
    delay(adc);   // oder hiermit den timer neu aufziehen
13
}

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.

von Patrick (Gast)


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

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
Noch kein Account? Hier anmelden.