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.
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.
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.
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:
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.