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
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ß
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.