Hi... Controller: ATTiny2313 AVR-Studio C verwende TIMER1 mit OCR1A und OCR1B Ausgängen bezogen auf Thread: Beitrag "LED-Dimmer / PWM Timing-Problem" den habe ich auch verstanden, aber nicht wie ich es praktisch realisieren soll. Ich sitzte nun schon seit Tagen an einem Problem und komme nicht mal ansatzweise darauf wie ich es lösen könnte. Also folgendes: Ich habe zwei LEDs, eine blaue und eine weisse. Blöderweise haben die einen 7200 mcd und die anderen weniger. Ich möchte die Leuchtkraft der LEDs mittels PWM mehr oder weniger gleich einstellen, da sie aber verschiedene mcd haben, leuchten sie bei beispielsweise 50% PWM nicht gleich hell (rein optisch gesehen). Also muss ich die dunkleren etwas heller drehen, beispielsweise auf 60% damit sie mehr oder weniger gleichhell leuchten. So, also habe ich für den Zähler des Timers zwei verschiedene Vergleichswerte, nehmen wir an 40 für die blauen und 20 für die weissen. Jetzt möchte ich dass die blaue LED (OCR1A)von 0 bis 40 hochgedimmt wird, während die weisse (OCR1B) von 20 auf 0 dimmt. Und das ganze natürlich im gleichen Zeitraum. Also zum Beispiel in 40 ms. Bei gleichen Vergleichswerten, nehmen wir an 50 ist das ja kein Problem, da ist ja der Ausgangspunkt: blau: 0, weiss: 50, nach der Schleife wäre es dann blau: 50 und weiss 0. Dann würde das spielchen von vorne losgehen. Bei zwei verschiedenen Vergleichswerte habe ich ja das Phänomen: blau: 0, weiss: 20 -> blau: 20, weiss: 0 -> blau: 40, weiss: 1003 -> blau: 20, weiss: 983 usw. Wie soll ich eine schleife schreiben welche mir die leds mit verschiedenen PWMs in einer vorgegebenen zeit hoch und runterdimmt? Danke schonmal im Voraus.
Mit C kannst du auch rechnen:
1 | for (i=0; i<=20; i++) { |
2 | weiss = i; |
3 | blau = 40-i*2; |
4 | wait_ms(2); // 20*2ms=40ms |
5 | }
|
6 | for (i=20; i>=0; i--) { |
7 | weiss = i; |
8 | blau = 40-i*2; |
9 | wait_ms(2); |
10 | }
|
Am einfachsten ist es also, wenn du irgendeine mathematische Beziehung zwischen den 2 Werten hast. Dann nimmst du eine Formel, die das beschreibt und fertig. Wenn es keine einfache Korrelation zwischen den beiden Werten gibt (nichtlinear) dann kannst du es evtl. über ein Tabelle lösen.
Die Formel hab ich ja welche mir die Zeitschritte berechnet, nur ist der wert ja verschieden. von daher kann ich ja keine schleife schreiben in der ich z.b. die blaue einschalte, 10 ms warte, dann die weisse einschalte und nochmal 5 ms warte.... sonst warte ich ja insgesamt 15ms bis ich die blaue um 1 erhöhe. die schleife die du mir gegeben hast hab eihc ausprobiert. die weisse dimmt zwar hoch und runter, die blaue dimmt aber nicht komplett auf null... sie dimmt also hoch obwohl sie noch nicht ausgegangen ist. udn was die Tabellen angeht, geht das nicht irgendwie anders? mit tabellen habe ich noch überhaupt keien erfahrung.
Ist die Welt kompliziert... Du möchtest LED1 von Wert a nach b ändern, gleichzeitig LED2 von c nach d, und das in n Schritten. Schrittweite1: (b-a)/n Schrittweite2: (d-c)/n Die Schrittweiten addierst du in einer n-mal-Schleife jeweils zum aktuellen Wert, fertig (...fast). Soweit die Theorie. Die Praxis ist insofern etwas unschöner, als das du mit Integern nur ganzzahlig rechnen kannst. Je nach Anspruch und maximaler Größe von n hilft es da, die Werte enstsprechend zu skalieren. z.B.
1 | int Schrittweite1 = (64*(b-a))/n; |
2 | int Schrittweite2 = (64*(d-c))/n; |
3 | |
4 | int temp1 = a*64; |
5 | int temp2 = c*64; |
6 | |
7 | for (int i =0; i<n-1; i++) |
8 | {
|
9 | temp1 += schrittweite1; |
10 | temp2 += schrittweite2; |
11 | |
12 | OCR1A = (uint8_t)(temp1 / 64); |
13 | OCR1B = (uint8_t)(temp2 / 64); |
14 | |
15 | delay_us(solange_du_willst); |
16 | }
|
17 | OCR1A = b; // damit erreichst du den Endwert auf jeden Fall |
18 | OCR1B = d; |
Oliver
geht nicht. da blinkt die LED an OCR1A kurz auf und dann geht die an OCR1B an und bleibt in dem zustand. naja gut, ein flackern ist zu erkennen. irgendwas tut sich da anscheinend, aber nicht das was ich wollte
>geht nicht.
Jung, das ist auch völlig ungetestet auf die Schnelle getippt. Ob der
Faktor 64 passt, keine Ahnung. Wirf halt den Debugger an, und schau
nach, was schief geht.
Es fehlen auch noch ein paar Feinheiten - in der o.a. Form kann es beim
abdimmen passieren, daß der Zähler schon größer ist als der neue,
kleineren Wert. Dann gibt es einen Zyklus lang volle Pulle. Sinnvoll ist
da z.B. ein Update der OCRx-Register synchron zum Timer, z.B. im
Timer-OVF-Interrupt.
Oliver
eh, ich habs jetzt anders gelöst... anstatt die zeit von einem schritt zum anderen zu berechnen, berechne ich doch lieber den quotienten. also wenn die blaue von 0 auf 40 dimmt und die weisse von 20 auf 0. dann mach ich 40/20 = 2 also dimm ich die blaue um 2 schritte hoch, während ich die weisse nur um einen schritt runterdimme. man sowas simples... und ich zerbrech mir die birne an sonem scheiss...
> dann mach ich 40/20 = 2
Ja, wie ich gesagt habe: in C kannst du auch rechnen ;-)
Zur Erinnerung:
1 | for (i=0; i<=20; i++) { |
2 | weiss = i; |
3 | blau = 40-i*2; // hier ist der Faktor 2 |
4 | :
|
5 | :
|
>man sowas simples... und ich zerbrech mir die birne an sonem scheiss...
Dann dimm mal die eine von 30 auf 0, und die andere von 20 :-)
Oliver
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.