PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : "kleine" PWM für LEDs



DeadDealer
13.03.2007, 17:01
Moin :)

Möchte gerne ca 100 LEDs einzeln dimmen können. ein einzelner ATmega8 scheint mir dafür nicht geeignet, da das dimmen nicht sichtbar sein soll (f >= 60Hz). Daher kam mir die Idee, an jede LED einen kleinen AVR Chip zu klemmen, der das entsprechende PWM-Signal erzeugt und den Helligkeitswert vom großen Bruder über einen Bus erhällt.
Eine Transistor/Kondensator-Schaltung an jeder LED zum hoch- und runterfaden ist nicht genau genug, daher die Idee mit dem 1xMaster / 100xClient entstanden.
Welchen Chip könnt ihr mir da empfehlen? Ist der benannte ATmega8 als Master geeignet? Gibt es vielleicht eine andere/einfachere Möglichkeit ala BlinkenLights mit einer Dimmung (wie das auch immer aussehen soll)? Einschränkungen, z.B. niedrigere Frequenz kann ich hinnehmen ;)

uwegw
13.03.2007, 17:08
Ein AVR pro LED ist vielleicht etwas Overkill. Aber 5xMega8 mit je 20 LEDs sollte machbar sein. Ich betreibe erfolgreich 10 LEDs per Software-PWM an einem Tiny26, und der ist timermäßig wesentlich schlechter ausgestattet als der Mega8. Ich benutze dafür nur einen einzigen 8bit-Timer, der nur einen Overflow-Interrupt bietet. Er erzeugt einen Takt von etwa 16000Hz, der eine 8bit-Varible hochzählt. Dieser Zähler wird dann mit den Sollwerten für die LEDs verglichen. Somit komme ich auf etwa 62Hz Wiederholrate. Man könnte jetzt noch die Auslösung reduzieren, 64 oder 128 Stufen kann man bestimmt auch noch nicht auseinaderhalten.

Hanni
14.03.2007, 00:19
daher die Idee mit dem 1xMaster / 100xClient entstanden.

1 Master - Typ Egal
4 Slave - alles ab 32 IO Pins ist geeignet ... oder 2 Slaves - alles ab 54 IO Pins ist geeignet.

Wenn man mit etwas Köpfchen an die Sache geht kann man durchaus 500 Hz Wiederholfrequenz bei 16 MHz Takt erreichen ohne das der µC am Limit läuft.
Bei beliebig vielen Ausgabekanälen und nur einem verbratenem Timer wohl gemerkt


Allerdings möchte ich auch anmerken, das man dafür mehr als nur ein paar wenige Zeilen Code in Assembler verbrechen muss :D

Grüße,
Hanni

Hanni
14.03.2007, 19:31
Hmm .... ich glaube, jetzt habe ich jemanden Totgequatscht ....

DeadDealer
18.03.2007, 11:21
nicht totgequatscht, hab im moment nur wenig zeit, um am pc zu surfen - ich baue an einem casemodding-projekt, daher bin ich die meiste zeit in der werkstatt und schraube am rechner ;)

also die idee mit den AVRs, die mehrere LEDs ansteuern klingt nicht schlecht. aber ich brauche noch einen denkanstoß, wie man dem jeweiligen AVR beibringt, das pwm-signal nach und nach an die jeweiligen LEDs zu schicken. mit einer LED ist das ja kein Thema:


1/4 Helligkeit (#=an ; -=aus)
#####--------------- #####--------------- ##...

3/4
###############----- ###############----- ##...

zum dimmen ändert man ja einfach die an/aus zeiten. wie sähe das denn dann aus mit einem timer und z.B. 16 LEDs an einem ATmega8?

[EDIT]
Kann die Chips nur in Bascom programmieren, hab es nicht so mit Assembler oder C

Hanni
18.03.2007, 13:38
Oha, in Bascom habe ich soetwas noch nie geschrieben oder gesehen :D
Die Theorie dazu ist recht komplex aber ich versuche es trotzdem einmal rüberzubringen.

Prinzipiell stehen die Helligkeitswerte am Anfang nach Kanal sortiert im Speicher zur Verfügung.
Daraus wird eine Helligkeits -> Kanalzuordnung generiert.
Diese wird sortiert und danach zu einer nach Helligkeit sortierten Ausgabemaske zusammengepackt.

In einer Timer Routine wird eben nur jene Maske ausgegeben, wenn ein interner Zähler den jeweiligen Helligkeitswert erreicht hat.

Das aufwändigste bei mir Im Code ist die Sortier und Packroutine ... (Assembler halt).

Das Assembler Listing hier zu veröffentlichen dürfte meiner Ansicht nach recht wenig bringen, da die wenigsten hier wohl den Code wirklich verstehen würden :D

Der Code ist zwar noch nicht 100%ig optimiert, belegt aber im Flash ca 1078 Worte (mit einer rudimentären Komunikationsroutine).

DeadDealer
26.03.2007, 21:02
re :)

also ich hab mir mal folgendes überlegt in einer stillen Minute, zusammen mit dem Geschriebenen hier. Hab mir sowas Änliches auf ein Blatt gezeichnet:



LEDs ^
|
n |
... |
05 (20%) | OOoooooooo OOoooooooo OOooooo...
04 (90%) | OOOOOOOOOo OOOOOOOOOo OOOOOOO...
03 (50%) | OOOOOooooo OOOOOooooo OOOOOoo...
02 ( 0%) | oooooooooo oooooooooo ooooooo...
01 (10%) | Oooooooooo Oooooooooo Ooooooo...
|____________________________________________>
0123456789 0123456789 0123456.... Timer

Der Timer läuft von 0 bis 9 und wird dann wieder auf 0 gesetzt.
Jeder LED wird ein Wert zugewiesen. Das kann, wie in diesem Fall, dauerhaft sein, oder bei jedem Timerdurchlauf geändert werden.
Am Anfang wird jeder Ausgang auf High gesetzt. Nach jeder Timeränderung wird überprüft, ob der Timerwert den Prozentwert für die Helligkeit übersteigt. Soll eine LED also z.B. nur 30% der vollen Helligkeit haben, wird sie beim 4. Durchlauf auf Low gesetzt und beim nächsten Durchlaufbeginn wieder auf High etc etc...
In einer Schleife könnte man nun eine gewisse Anzahl n von LEDs checken lassen, wann sie ausgeschaltet werden müssen, wenn ... ja, wenn das so klappen könnte ;)
Möchte diese Idee nicht weiter verfeinern, um mehr Performance rauszukitzeln ... es geht einfach um die reine Funktion, das Programm soll in ausreichender Geschwindigkeit (flackerfrei) funktionieren und gut is. Tut es das z.B. auf einem ATmega8 @ 16MHz mit Busabfrage zwischen den Timerresets, um neue Werte zu erhalten.

[UPDATE]
Grad vor einer Stunde ist die Idee Wirklichkeit geworden ... mittels eines Atmega8 und 3 ULN2803 Treiberstufen und einem Software-Timer ( o_O ... naja, es läuft halt besser als mit Timer0 oder Timer1 ;) ) ist es mir gelungen, eine Steuerung zu realisieren, mit der man die benötigten 18 LEDs pro Platine in 100 Stufen dimmen kann, und das sogar "flimmerfrei", solange man die Platine nicht schnell hin- und herbewegt ;) Aber das Problem sollte sich mit passenden Kondensatoren auch bald erledigt haben!
Demnächst mache ich von der Sache Fotos und ein Video, ich meld mich dann wieder.