Hallo Mikrocontroller Leute, :) und zwar hab ich folgendes Problem ich möchte gerne LED´s ohne hilfe des PWM dimmen. Dies gelingt mir auch aber ich möcht, das sie automatisch bzw je nach programmierung heller bzw dunkler werden. Nur geht es nicht so wie ich mir das dachte. Habt ihr vllt ein Lösungsansatz? Danke im Vorraus :D Hier mein Code #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include <inttypes.h> int i; int main( void ) { uint8_t pwm_soll = 0; // gewünschter Dimmerwert 0..100 uint8_t pwm_phase = 0; // Laufwert der Schleife 0..100 DDRD |= (1<<PB5); // Pin PB0 an Port B als Ausgang while( 1 ) { for (i=0;i<=255;i++) { if( pwm_soll == pwm_phase ) { PORTD |=(1<<PB5); // active low LED aus } pwm_phase++; if( pwm_phase == i ) { pwm_phase = 0; PORTD &=~ (1<<PB5); // active low LED an } } } return 0; }
vergleiche pwm_phase nicht mit i sondern einer anderen 8Bit Variablen, die außerhalb der FOR-Schleife definiert ist, und sich innerhalb derer nicht ändert. Das müsste gehen, aber wäre dann auch komplizierter als nötig.
> Habt ihr vllt ein Lösungsansatz? Programmieren lernen. Funktionierender Code sähe so aus: uint8_t pwm_soll = 0; // gewünschter Dimmerwert 0..100 while(1) { for(i=0;i<=100;i++) // dann klappt's sogar mit den 100 { if(i<pwm_soll) | PORTD &=~ (1<<PB5); // active low LED an } else { PORTD |=(1<<PB5); // active low LED aus } } }
Also den Code den du mir gegeben hast funktioniert nicht. Trotzdem danke. Ich weiß nicht ob du genau weißt was ich meine ich möchte das die LED langsam heller bzw dunkler wird und nicht nur die Dimmstufe annimmt.
muss mich korrigieren, sollte nicht mit einer anderen Variable verglichen werden, sondern mit 0, wobei pwm_soll dann größer 0 sein sollte. MaWins code müsste gehen, obwohl da ein Schreibfehler drin ist, den du aber leicht finden könntest, wenn du die Compiler-Meldungen lesen würdest. "Fading" würde dann funktionieren wenn pwm_soll außerhalb der FOR-Schleife geändert werden würde
Michael schrieb: > Also den Code den du mir gegeben hast funktioniert nicht. Trotzdem > danke. Ich weiß nicht ob du genau weißt was ich meine ich möchte das die > LED langsam heller bzw dunkler wird und nicht nur die Dimmstufe annimmt. Dann solltest du die PWM Erzeugung von der Einstellung des aktuellen Dimmgrades unabhängig machen. Deine PWM Erzeugung basiert auf einem aktuellen Dimmwert. Dein Benutzer gibt dir einen Dimmwert vor => Sollwert und deinen aktuellenb Dimmwert (der dann die Helligkeit definiert) führst du langsam dem Sollwert nach: Ist er kleiner als der Sollwert, dann erhöhst du ihn um 1. Ist er größer als der Sollwert, dann erniedrigst du ihn um 1. Dein Benutzer kann am Rädchen drehen soviel er will, die Helligkeit geht langsam seinen Änderungen nach. Warum willst du eigentlich keine Hardware-Pwm nehmen? Würde alles enorm vereinfachen. > LED Dimmen ohne PMW am Atmega8 Du machst eine PWM! Nur machst du die in Software statt in Hardware obwohl letzter viel einfacher wäre. Angst vor Timern? Das langsame Nachführen der Helligkeit macht man ebenfalls am besten mit einem Timer. Da ist das dann ganz easy.
Naja ich hab nen LED Cube 3x3x3 gemacht. :) Und läuft eigentlich soweit ganz gut nun wollte ich halt noch das ich die LED´s dimmen kann und naja da hab ich dann bemerkt das ich die PWM schon verheizt habe :S ... deswegen das. Und war will ich ja das hier keiner am Rad dreht sondern das ich einstellen kann das die LED jetzt von AUS auf AN geht aber das halt langsam. Nun weiß ich zwar wie man die LED dimmen kann aber nicht das es Automatisch geht. Die lösungsvorschläge bis jetzt haben mir bis jetzt nicht weitergeholfen. Trotzdem danke :)
Michael schrieb: > Naja ich hab nen LED Cube 3x3x3 gemacht. :) Dann sag das das nächste mal bitte auch. Dann denken nicht alle in die falsche Richtung. > Und läuft eigentlich soweit ganz gut nun wollte ich halt noch das ich > die LED´s dimmen kann alle gemeinsam oder jede Led einzeln? Wie sieht deine Cube Ansteuerung jetzt aus? (jede LED einzeln) Grundsätzlich brauchst du für jede LED nicht nur 1 Bit, welches aussagt ob die LED ein oder aus ist, sondern einen Helligkeitswert (zb uint8_t). Dein Array, in dem die Helligkeitswerte abgelegt sind, muss es 2-mal geben. Aus dem einen holt sich die Cubeansteuerung den Helligkeitswert, den sie für diese LED realisieren soll und im anderen Array stehen die Helligkeitswerte, die du in deinem Programm vorgibst. Nach x Zeiteinheiten (zb nach einem Komplett-PWM Zyklus des Cubes) führst du die realisierten Helligkeitswerte den Vorgabewerten wie oben beschrieben nach. Wenn du nur Ein/Aus hast, welche Framerate schaffst du mit deinem Cube? Die kannst du gleich mal durch die Anzahl der gewünschten PWM STufen dividieren um abzuschätzen, ab wann das alles flackern wird.
Wie oben geschrieben mußt Du den Wert pwm_soll außerhalb der PWM-Schleife anpassen. Wenn ich Marvins PWM-Code nehme, könnte man es wie folgt ergänzen:
1 | uint8_t pwm_soll = 0; // gewünschter Dimmerwert 0..100 |
2 | while(1) |
3 | {
|
4 | for(i=0;i<=100;i++) // dann klappt's sogar mit den 100 |
5 | {
|
6 | if(i<pwm_soll) |
7 | {
|
8 | PORTD &=~ (1<<PB5); // active low LED an |
9 | }
|
10 | else
|
11 | {
|
12 | PORTD |=(1<<PB5); // active low LED aus |
13 | }
|
14 | }
|
15 | pwm_soll++; |
16 | if(pwm_soll > 100) |
17 | pwm_soll = 0; |
18 | }
|
Damit sollte die LED langsam aufdimmen und wenn sie hell ist wieder bei dunkel anfangen. Es kann sein dass es zu schnell geht, dann mußt Du pwm_soll seltener inkrementieren. Vielleicht wird Dir damit das notwendige Prinzip klar, das Karl Heinz auch schon erwähnt hat.
Ok sorry ^^ Naja wäre schon schön wenn ich alle ansteuern könnte ... könnte man halt manche Effekte besser sehen :) Ansteuerung läuft über ein atmega8 mit multiplexing ... also 3 ebenen mit jewahls 9 leds.
Michael schrieb: > Ansteuerung läuft über ein atmega8 mit multiplexing ... also 3 ebenen > mit jewahls 9 leds. In einer Interrupt-Routine? (Hoffe ich mal ganz stark)
Dann baust du die erst mal um auf Soft-PWM, so dass du für jede LED einzeln die Helligkeit einstellen kannst. Das langsame Dimmen kommt später. Erst mal muss jede LED unabhängig von allen anderen einen eigenen Helligkeitswert annehmen können. > jo klar :) Sag das nicht. Alles schon gehabt: Cube-Asteuerung in der mainloop per 'nur die einzuschaltenden LED werden auch eingeschaltet' und dann war das Geschrei gross, dass man mit dem Timing nicht hinkommt und je nachdem wieviele LED einzuschalten sind die Helligkeit abnimmt.
Hmm dumme frage SOFT PWM ? ... was soll ich denn da umstellen? und wie ? ...
Michael schrieb: > Hmm dumme frage SOFT PWM ? Na genauso wie du das oben gamcht hast. Wenn du 16 Helligkeitswerte hast, dann brauchst du auch 16 Zeitticks dafür. Eine Helligkeit 1 bedeutet, dass die LED nur 1 Zeittick lang brennt und 15 Ticks lang nicht. > ... was soll ich denn da umstellen? und wie ? > ... genau darum hab ich dich nach deiner Cubeansteuerung gefragt. Dann könnte man das ein wenig konkreter anhand von konkretem Code zeigen. Ich weiß ja nicht, wie du deinen Multiplex in die Timer-IST eingepasst hast. Dem Prinzip nach wird es ungefähr so aussehen ISR( Timer... ) { aktuelle Ebene abschalten Ebene++; if Ebene == 3 Ebene = 0 Leds der Ebene "Ebene" einschalten } und das erweiterst du noch um eine Software-PWM ISR( Timer... ) { aktuelle Ebene abschalten Ebene++; if Ebene == 3 { Ebene = 0 Pwm_counter++; if Pwm_counter == 16 Pwm_counter = 0 } Leds der Ebene "Ebene" einschalten, wenn der Pwm_Counter < Helligkeitswert dieser Led }
Darf ich dich fragen, warum du mich verarscht und du mir sagst, du machst das Multiplexing des LED-Cube in einer Timer-ISR? Das ist genau der besch.... Code, den ich weiter oben gemeint habe! Tritt ihn in die Tonne und mach erst mal die Cube Ansteuerung richtig, ehe du da was dimmen willst. Solange das nicht richtig ist, hat es keinen Sinn sich weitere Gedanken darüber zu machen.
Sorry ... dann hab ich dich falsch verstanden. Also kann ich das garnicht machen oder wie ? oder was würdest du mir jetzt empfehlen zu machen ?
Neues Programm du hast ein globales uint8_t Led[3][3] welches 1 Ebene deines Cube repräsentiert. Jedes Array-Element steht für 1 LED in dieser Ebene. Werte: 0 für LED aus, 1 für LED ein wie muss der Code aussehen, der dieses 2D Array abklappert und alle LED einer Ebene entsprechend den Werten dieses Arrays ein bzw. ausschaltet. Und zwar so, dass alle LED gemeinsam und gleichzeitig(!), also nicht gemultiplext, leuchten können. Damit gehts los.
Hmm .. wüsste ich jetzt nicht wie ich da anfangen soll ... sorry wollte dich net verarschen ... kannste vllt bisschen näher erklären .. steh da grad aufm schlauch .... danke schonmal das du so hilfsbereit bist ;)
Michael schrieb: > Hmm .. wüsste ich jetzt nicht wie ich da anfangen soll ... sorry wollte > dich net verarschen ... kannste vllt bisschen näher erklären .. steh da > grad aufm schlauch .... danke schonmal das du so hilfsbereit bist ;) Du musst ALLE Leds einer Ebene auf einen Rutsch ein/ausschalten können! In der ISR passiert dann nämlich folgendes:
1 | ISR( Timer .... ) |
2 | {
|
3 | alle momentan brennenden LED ausschalten |
4 | |
5 | Ebene++; |
6 | if( Ebene == 3 ) |
7 | Ebene = 0; |
8 | |
9 | alle Leds der Ebene 'Ebene' einschalten, sofern sie eingeschaltet werden müssen |
10 | }
|
Das ist Multiplexing über die Ebenen. Und dazu musst du abhängig vom Array, welches den logischen Zustand des Cube darstellt, eben alle Led in einer Ebene ein bzw. ausschalten können. Je nachdem, wie es das Array vorschreibt. In deiner Hauptschleife wird dann im Array eine 1 bzw. 0 eingetragen, wenn die LED leuchten soll. Tatsächlich eingeschaltet wird sie aber erst durch den Timerinterrupt, der regelmässig alle Ebenen nacheinander durchgeht und die jeweilige Ebene als ganzes anzeigt. Bis dann eben nach ein paar µs der Timerinterrupt erneut kommt und die nächste Ebene anzeigt. Immer reihum, eine Ebene nach der anderen. Und dazu brauchst du Code, der eine Ebene als ganzes bearbeiten kann. Im Endeffekt wird das Array dann ein uint8_t Led[3][3][3]; werden. Aber ich dachte mir, ein 2D Array wird dich schon vor genügend Probleme stellen, also lass ich die 3.te Dimension erst mal weg. Wie sieht dein Schaltplan aus? Ich kann mich noch dunkel erinnern, dass du da gar nicht alle LED einer Ebene gleichzeitig brennen lassen kannst. Stimmt das? Wenn das so ist, dann gehts nämlich überhaupt nicht nicht vernünftig bzw. wird horrend aufwendig bei miesen Ergebnissen. Dann muss das ganze komplett anders gemacht werden. Dann braucht man eine Liste von Leds die brennen sollen und der Interrupt muss diese Liste reihum abarbeiten. Ist besch..., geht aber nicht anders. Aber sei es wie es sei: Eines deiner Muster darf auf keinen Fall so realisiert sein, dass das Muster selbst die Portpins ansteuert. Sobald du das machst, hast du schon verloren. Ein Muster trägt in eine Datenstruktur ein, welche LED zu brennen haben und ein allgemeiner Mechanismus, der ständig im Hintergrund mitläuft, schnappt sich diese Beschreibung und bringt die LED entsprechend zum leuchten.
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.