Hallo, Ich arbeite mit einem Arduino Board, das auf einem Atmel Mega8 basiert. Damit kann ich sehr einfach PWM outputs generieren, doch hat dieses Board nur 3 Ausgänge davon (wie der Atmega8 ja auch), und ich benötige derer 12. Gibt es eine Möglichkeit, das PWM Signal zu multiplexen? Ich möchte damit 12 Power LED's steuern (dimmen). Wie gesagt, mit den drei Ausgängen funktioniert alles einwandfrei. Könnte das mit einem Analog Multiplexer wie dem MC14067BCPG klappen, oder brauch ich da etwas anderes? Vielen Dank für Hilfe
Klar geht das. Du kannst auch einfach ein Undgatter dafür nehmen. Schaltungstechnisch absolut kein Problem. Hast du dir aber überlgt, dass in den Pausen, in denen einen LED nicht angesteuert ist, diese entweder An oder Aus ist? ergo: mit einem DutyCycle von 1/12 gibst du einen PWM mit einem weiteren DutyCycle drauf. Das überlagert sich ja dann...
Hi, mach' deine PWMs in Software, das geht ohne Probleme. Damit kannst du recht viele Kanäle realisieren, die Bandbreite pro Kanal wird einfach immer kleiner. Aber 12 * 1kHz oder sowas geht sicher problemlos wenn du den Controller nicht gerade mit einem Uhrenquarz (32kHz) taktest.
Ich habe versucht das mit Software zu machen, da ich aber immer mal noch Serial botschaften zum Computer senden muss, und dazwischen noch Berechnungen machen muss, gab das bloss ein geflacker, und von einem Dimmeffekt konnte nicht die Rede sein. So viel ich verstanden habe läuft der PWM auf den 3 dafür vorgesehenen Pins in einem eigenen Thread (so sinngemäss) und ist deshalb auch sehr sauber, das hat bei mir noch nicht geklappt. Deswegen dachte ich, evtl übernimmt ein externer chip mir die pwm arbeit. Oder ich verwende einen extra atmel mega 8, der sich nur um die pwm kümmert?
> gab das bloss ein geflacker Hast du das in Software über einen Timer gelöst? Das Timing wird zwar nicht ganz 100 prozentig, aber in eine Flackerorgie sollte das nicht ausarten. Vor kurzem gabs mal einen Thread hier. Im Titel war was mit 28 LED. Der beschäftigte sich mit dem Dimmen von 28 Led - also 28 PWM Kanäle.
Du kannst natürlich auch recht einfach dir nen eingenen PWM Chip machen, mit 12 PWM Registern, die autark durchlaufen und über den externen Bus gesetzt werden. Brauchst halt ein FPGA oder nen dicken CPLD dazu. (Lötarbeit) Der Code dazu ist recht simpel.
@Matthias multiplexen ist zwar theoretisch möglich, aber nicht ganz einfach. Du müßtest synchron mit dem PWM-Takt multiplexen und die LEDs mit dem 12-fachen Strom betreiben, da sie 11/12 der Zeit dunkel bleiben. Da gibt es mehrere Probleme: 1. Kannst Du den Multiplexer PWM-synchron umschalten ? (Das geht notfalls mit einem Hardware-Zähler) 2. Vertragen die LEDs den Impulsbetrieb mit 12-fachem Nennstrom ? 3. Was passiert, wenn der Multiplexer wegen eines Softwarefehlers nicht umschaltet und eine der LEDs den 12-fachen Strom permanent abbekommt ? Ich würde auch eine Software-Lösung bevorzugen. 8 Bit Auflösung sollten zum Dimmen ausreichen. Du brauchst nur einen nicht maskierten Interrupt, der per Timer etwa alle 50µs ausgelöst wird. Mit jedem Interrupt wird. 1. ein 8-Bit-Zähler hochgezählt 2. Nacheinander alle 12 Helligkeitswerte mit diesem Zähler verglichen und 3. Die jeweiligen PWM-Bits gelöscht, wenn der Zählerwert jeweils höher ist, oder gesetzt, wenn er niedriger ist. Wenn der µP schnell genug ist, kannst Du den Interruptzyklus noch verkürzen, um die Flimmerfrequenz der LEDs zu erhöhen. Bei 50µs kommst Du auf ca. 78 Hz. Jörg
Ok, danke vielmals, es klappt jetzt, wenn ich den einen Chip nur die Dimmung lassen mache... Nun versuche ich diesem Chip per PWM Signal mitzuteilen, welche Lampe er anzustellen hat. Also der wert 10 bedeutet erste lampe 20 zweite, etc. Nun hab ich bemerkt, dass wenn ich vom einen Chip ein pwm signal sende der andere bei seinem analog eingang bloss nullen und zwischendurch 101 empfängt, aber keinesfalls den Wert, den ich gesendet habe. Ich denke mal, dass ich das PWM signal glätten müsste, um es auszulesen. Wie mache ich das? ist es kompliziert? ansonsten schicke ich die Daten binär codiert über digitale pins, oder? Weiss das jemand? Vielen Dank
@Schlumpf: Der Code für einen FPGA / CPLD würde mich schon mal interessieren. @Matthias: Die Software PWM ist ansich recht simpel zu erstellen, Peter Danegger hatte dazu mal ein Codeschnippsel in der Codesamlung gepostet. Grüße, Ralf B.
>Ich denke mal, dass ich das PWM signal glätten
müsste, um es auszulesen.
Da gibt's bei ATMEL auf der Hompage und auch sonst noch ziemlich viel
Lektüre drüber. Die einfachste (und ungenaueste) Methode ist die
Glättung mittels RC-Glied. Mit nachgeschaltetem OP (Impedanzwandler)
kommt ein recht akzeptables Analogsignal 'raus. => Googeln hilft
weiter!
@Ralf: Ein PWM-Generator besteht doch im Wesentlichen aus einem Zähler und einem Vergleicher. Ist der Zählerstand kleiner Vergleichswert, dann ist der PWM-Ausgang auf 1, ist er größer, dann ist der Ausgang auf 0. Der DutyCycle wird eingestellt, indem man vom uC das Vergleichsregister setzt. Fertig ist der PWM generator... Von diesen Dingern packt man dann 12 Stück in ein FPGA, macht ein kleines Businterface dran(z.B. asynchron) und kann so ausgehend von einer Basisadresse die 12 Vergleichsregister beschreiben. Wenn alle mit der gleichen Basisfrequenz laufen sollen, kann man auch einen Zähler mit 12 Vergleichsregistern machen (spart ne Menge Ressourcen im Chip)
@Matthias: Wieso willst du das über die PWM machen? Die Chips könnten doch viel einfacher (und mit exakten digitalen Werten) über SPI kommunizieren?
@Qwerty Also ich hab noch keine LED mit SPI-Schnittstelle zum Einstellen der Helligkeit gesehen... oder was meinst du mit Chips?
Er meint wahrscheinlich, dass die beiden controller über SPI kommunizieren sollen anstatt über ein Analoges Signal.
Ach sooooo.... Ich hab mich schon gewundert :-) Hab den Post von Matthias überlesen. Sorry!
Vorschlag: bau dir aus nem Sägezahngenerator und n paar OPV's als Komperator deine Hardware PWM's auf. Als Sollwert speist du dem Komperator ne Spannung über ein digitales Poti ein, welches du über einen Bus einstellen kannst.
ja, es ist einfacher über eine digitale verbindung, das habe ich nun auch gecheckt und es klappt alles wunderbar, ausser, dass es zum teil ein Timing problem gibt bei der Kommunikation. Habe eine paralelle 4 Bit verbindung, und einen attention pin. Wenn die DatenPins gesetzt sind, geht der Attention Pin auf High, danach wird 20 Milisekunden gewartet, danach wieder der attention-Pin auf Low gesetzt. Der Andere microcontroller schaut laufend, ob der attention pin high ist, wenn ja, dann liest er die datapins aus. Zum Teil sind diese Daten aber noch im graubereich von high und low (ich verwende die analog in Pins, da die digitalen alle schon belegt sind für die Leds) und im ganzen ist eine gewisse "trägheit", woran könnte das liegen? (trägheit meint, der Pin wechselt ziemlich langsam von high auf low, so dass bei zu kurzen Wartezeiten falsche Signale entstehen) Noch vielen Dank für die Hilfe.
Hi Matthias, ich weiß ja nicht wie Deine Schaltung aussieht, aber der Mega88 hat sechs PWM Kanäle und ist pingleich mit dem Mega8. http://atmel.com/dyn/resources/prod_documents/doc2545.pdf Dann wäre ein Multiplex etwas einfacher ;) Bye, Markus
> ich verwende die analog in Pins, da die digitalen alle schon belegt > sind Kann sich irgendjemand da einen Reim drauf machen? Seit wann hat ein Mega8 ein paar analog-only Pins?
@Mathias: Die ADC-Eingänge kannst du auch ganz normal als digitale Pins benutzen. Aber im Übrigen sehe ich nicht, warum du dazu überhaupt mehrere Controller brauchst. 12x Software-PWM für LEDs ist ja nun also wirklich kein Problem. Du musst das Ganze Zeugs nur direkt in die ISR packen (Sofern ansonsten nix zeitkritisches ausgeführt werden muss), dann flackert da nix, auch nicht wenn der Controller ansonsten total ausgelastet ist. Du musst nur darauf achten, damit es sonst keine langen ISRs gibt, bzw. nach dem Einsprung in eine ISR mit niedrigerer Priorität gleich "sei" (Global interrupt enable) ausführen.
Ok, zur Klärung, ich programmiere in der Arduino Umgebung, das ist eine sehr stark vereinfachte Programmiersprache, für ein Arduino Board, das ähnlich einem BasicX alle Komponenten die der Atmega8 benötigt bereits integriert hat. Deswegen meine wohl etwas kryptisch anmutenden Beschreibungen. Danke für eure Inputs, es funktioniert jetzt ziemlich gut, und das ist das einzige Ziel
@Matthias du kannst dir analog pins natürlich auch direkt als digitalen Eingang auslesen. Dazu musst du nur direkt auf die Port Register zugreifen. Mit DigitalRead() geht das leider nicht. Wie das geht kannst du sogar genau hier, im AVR-GCC Tutorial nachlesen: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Zugriff_auf_Ports Hier siehst du, wie wie analogen Arduino Pins auf Port C gemappt sind: http://www.arduino.cc/en/Hacking/PinMapping Und das geht alles direkt mit Arduino, gerade weil es keine vereinfachte Programmiersprache, sondern reines C ist (avr-gcc C/C++). Die Arduino GUI denkt halt etwas mit und vereinfacht hier und da ein paar Sachen... abgespeckt is da aber nix.
Warum nimmst Du nicht einfach ein ödes Schieberegister mit 12 Stufen und Latch? Das kann man mit einer einzigen Leitung füttern, um die Zellen zu beschreiben. Hast mit einem Takt von 24MHz bei 4Steps immerhin 500kHz update netto. Wenn Du 25 Hz fahren wills auf 64 Stufen (mehr sieht man eh nicht) wären das 1600 updates ergo 0,03% CPU-Last fürs Schreiben. Mit dem Rechnen zusammen 0,1% geschätzt. Die 64 Stufen packst Du in 8 Bytes x 8 Bit (Bitmuster).
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.