PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ATMega und 12 PWM Kanäle



zwanzischmark
14.02.2008, 08:37
Hallo,

die Frage gab es sicher schomal, aber manchmal tut man sich mit Suchbegriffen schwer....

Ich brauche also 12 PWM Kanäle um LEDs anzusteuern. Ich glaube Hardwaremässig gibt es maximal 10. Der Controller hat nur die Aufgabe die Werte für die jeweilige Helligkeit zu empfangen und die PWMs zu steuern.
Wieviele kann man softwaremässig betreiben, oder was ist die beste Lösung?

mfg Paul

wkrug
14.02.2008, 09:49
Es wäre gut, wenn Du uns posten würdest welcher ATMEGA es denn ist, denn davon gibt es ne ganze Menge.
Wie viele PWM's ansteuerbar sind, hängt von mehreren Faktoren ab.

Taktfrequenz, Codelänge, Codequalität , Anzahl der Kanäle, gewünschte Auflösung.

In Hardware kann z.B. ein ATMEGA8 3 PWM's realisieren und das mit Frequenzen bis weit in den kHz Bereich hinein.

In Software sind theoretisch so viele PWM's möglich wie Du Ausgangspins zur verfügung hast. Allerdings ist da bei 200Hz der Ofen so ziemlich aus.

So eine Software PWM ist für den Controller eine ziemliche Belastung, weil er sehr viel in Timer Interruptroutinen rumhängt und somit für das Hauptprogramm nicht mehr viel Zeit bleibt.

Die PWM Routine würde ich versuchen in Assembler zu realisieren um Rechenzeit zu sparen.
Der Controller sollte so hoch getaktet werden wie nur irgend möglich, also einen nehmen, der auch für 20MHz noch spezifiziert ist. Dadurch kann man für Soft PWM ( Timer ) höhere Prescaler Raten einstellen, was mehr Rechenzeit für die Hauptroutine bei brauchbaren PWM Frequenzen bringt.

Du solltest deinen Code auf jeden Fall im Simulator testen, sonst kann es Dir passieren, das der Controller überhaupt nicht mehr aus der Interruptroutine raus kommt, weil bis zur Abarbeitung der Interruptroutine der nächste Interrupt schon wieder ansteht.

Die Frage nach Soft PWM wurde hier im Forum schon sehr oft gestellt, da sollte für jede Programmiersprache ein passendes Codeschnipsel zu finden sein.

zwanzischmark
14.02.2008, 10:32
es wurde noch kein Controller dafür ausgewählt, weil ich ja nicht wusste ob es softwaremässig möglich ist 12 Kanäle zu betreiben. Wie gesagt handelt es sich um LEDs da ist die Auflösung nicht ganz so wichtig. Das es hier Lösungen für Software PWM gibt ist mir schon klar. Die Frage ist generell ob es möglich ist oder ob es z.B. besser ist einen µC zu nehmen der schon 10 Hardware PWM hat und die fehlenden zwei über Software zu realisieren.

Die Frage ist also einfach was die beste/einfachste/sinnvollste Möglichkeit ist 12 PWM Kanäle zu realiseren.

python_rocks
14.02.2008, 10:42
Ich brauche also 12 PWM Kanäle um LEDs anzusteuern.
Hallo Paul!

Hier ist ein Beispiel für Software-PWM mit drei LEDs. Das lässt sich aber leicht auf 12 LEDs erweitern. Trotzdem würde ich dann dem µC nicht mehr viel zusätzliche Arbeit zumuten.

http://paste.pocoo.org/show/24597/

Und hier ein Beispiel, in dem mit Tastern die Helligkeit geregelt wird.

http://paste.pocoo.org/show/24590/

Und weils so viel Spaß macht. Hier noch ein Beispiel, in dem man die Helligkeit mit einem Poti einstellen kann.

http://paste.pocoo.org/show/24605/

mfg
Gerold
:-)

PS:


Der Controller hat nur die Aufgabe die Werte für die jeweilige Helligkeit zu empfangen und die PWMs zu steuern.
Das dürfte noch machbar sein. Ich sehe kein großes Problem darin. Wenn die Daten über die UART kommen, dann würde ich keine zu hohe Baudrate einstellen und UART mit CONFIG SERIALIN auf BUFFERED stellen. Dann schafft der ATmega das schon. Aber du solltest den ATmega8 mindestens mit den internen 8 Mhz oder besser mit externe 16 Mhz takten.

.

Ceos
14.02.2008, 12:11
kannst ja mal folgendes ausprobieren, da hast du 0 code in der main routine aber die auslastung ist schon heftig (hab ich aufm ATMEGA8 @8MHz intern geschrieben)

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/timer.h>
#include <avr/signal.h>
#include <avr/sleep.h>

#define ON 1
#define OFF 0
#define ULONG_MAX 199

volatile unsigned char OFVal;
unsigned char LED1Duty;
unsigned char LED1Stat;




SIGNAL(SIG_OUTPUT_COMPARE2)
{
if (OFVal++ == 200) OFVal = 0;
LED1Duty = (ADC*10)/(1024/10)-1;
if (LED1Stat == OFF && (ULONG_MAX-LED1Duty) == OFVal)
{
PORTB |= BV(PB1);
LED1Stat = ON;
}
if (LED1Stat == ON && ULONG_MAX-(ULONG_MAX-LED1Duty) == OFVal)
{
PORTB &= ~BV(PB1);
LED1Stat = OFF;
}
}

int main(void)
{
cli();
OFVal = 0;
DDRB = BV(PB1)|BV(PB2)|BV(PB3)|BV(PB4);
TIMSK = BV(OCIE2)|BV(TOIE2); //TOIE2 musste ich mit einschalten hat sonst nciht fuinktioniert (komisch ....)
TCNT2 = 0;
OCR2 = 100; //damit kannste die auflösung einstellen 100% sind wegen der ADC formel notwendig
TCCR2 = BV(WGM21)|BV(CS20); //CTC modus, prescaler 1
LED1Duty = 1;
LED1Stat = OFF;
ADCSRA = BV(ADFR) | BV(ADPS2) | BV(ADPS1); // ADC einstellungen
ADMUX = BV(REFS0);
ADCSRA |= BV(ADEN);
ADCSRA |= BV(ADSC);
sei();
while(1) ;
}

die duty berechne ich in der ISR weil ich mir den ADC wert zum eistellen geholt habe, kannste aber theoretisch zwischen 0 und 100 variieren.
Wenn du OCR2 auf 256 stellst sollte mehr rechenzeit frei werden, aber die frequenz sinkt dann, musste einfach mal rumprobieren

PS: Bitte um kommentare zur optimierung des code

Hubert.G
14.02.2008, 12:41
Der ATmega2560 hat laut Datenblatt mehr als 12 HardwarePWM-Kanäle. Ob es für LED-Ansteuerung nicht etwas übertrieben ist musst du selbst entscheiden.

python_rocks
15.02.2008, 09:33
Ich brauche also 12 PWM Kanäle um LEDs anzusteuern.
Hier ist ein Beispiel für Software-PWM mit drei LEDs. Das lässt sich aber leicht auf 12 LEDs erweitern. Trotzdem würde ich dann dem µC nicht mehr viel zusätzliche Arbeit zumuten.
Hallo!

Ich korrigiere!!!

Die Zeit die einem im Interrupt-Handler bleibt ist für 12 Software-PWM-Kanäle nur dann ausreichend, wenn man sehr optimiert. Das heißt, dass man sich selber um das Sichern und Wiederherstellen der Register kümmern muss (NOSAVE) und dass in der Hauptschleife kaum gearbeitet werden darf.

Das Empfangen der PWM-Werte per UART oder I²C könnte sich gerade noch ausgehen. Für mehr bleibt aber keine Zeit mehr.

Ich habe ein wenig gerechnet. Siehe: http://www.elektronik-projekt.de/thread.php?postid=44455#post44455

mfg
Gerold
:-)

zwanzischmark
15.02.2008, 12:22
so, ich bin wieder da ^^ (mein PC Netzteil hat sich gestern erstmal verabschiedet)

also was ich bis jetzt so aus euren Antworten rauslese ist es zumindest schon im kritischen Bereich.

leider sind auf der Atmel Seite irgendwie grad die Anzahl der PWM Kanäle der Controller verloren gegangen, der ATmega2560 ist aber doch etwas übertrieben.

Ich denk ich werd einen raussuchen der möglichst viele Hardware PWMs hat und den rest per Software lösen.

python_rocks
15.02.2008, 12:41
also was ich bis jetzt so aus euren Antworten rauslese ist es zumindest schon im kritischen Bereich.
Hallo Paul!

Kritisch aber nicht unmöglich. Besonders dann nicht, wenn du nur LEDs damit dimmen willst.

Sag mal, was willst du zum Ansteuern verwenden? I²C, SPI oder UART? Denn ich will mir demnächst so etwas mit I²C machen, damit ich Erfahrung mit I²C sammeln kann.

mfg
Gerold
:-)

zwanzischmark
15.02.2008, 12:55
wenn du es genau wissen willst: ich will eine modifizierte Version des Ambilight aus der elektor Bauen. Bin noch in der Grundplanung ;). Welchen Bus ich verwenden werde kann ich noch nicht sagen. Hängt auch davon ab wieviel Pins ich noch zur verfügung hab. Ein Kompletter Port wär natürlich schön, aber den werd ich nicht haben...

python_rocks
15.02.2008, 13:11
Hallo Paul!

Ich möchte mich am Wochenende an I²C versuchen und als Beispielanwendung werde ich 12 LEDs verschieden stark dimmen lassen. Vielleicht haut es hin. Und vielleicht kannst du das dann übernehmen um den ATmega8 als I²C-LED-Dimmer zu verwenden. Mal sehen...

mfg
Gerold
:-)

Besserwessi
15.02.2008, 15:44
Für 10 Kanäle kann es wirklich nötig sein die ISR Routine in Assembler zu schreiben. Ist aber zumindest bei 8 Bit Auflösung nicht lang. Der wesentliche Teil sind Befehle nach dem Muster
LD r1,x+
cp r1,r2
rol
für jeden Kanal.

Das wird trotz optimierung eine relativ lange ISR Routine, sodass man zumindest nichts wirklich zeitkritischen nebenbei machen kann.

wkrug
15.02.2008, 19:42
Ich hab noch ein wenig rumgerechnet und bin dann auf folgende Zahlen gekommen.
Bei 20MHz Taktfrequenz mit einem Prescaler von 8 und einem Einstellbereich von 0..127 ( 128 Helligkeitsstufen ) kann man eine PWM Frequenz von
20 MHz / 2^15 / 8 = 76,3 Hz erreichen. Das sollte somit flimmerfrei gehen.
Es können 2048 Taktzyklen, das dürften etwa 1800 Assembler Befehle sein, abgearbeitet werden bis der nächste Interrupt auftritt.

Für deine Interruptroutine werden in etwa 100..150 Befehle draufgehen, für den Rest kann das Hauptprogramm abgearbeitet werden.

Das ist eine ganze Menge. Hochkomplexe Mathematische Gleichungen möchte ich zwar so nicht lösen, aber für einen Schnittstellenhandler sollte das mehr als locker reichen.

python_rocks
15.02.2008, 20:03
I0..127
Hallo wkrug!

:-)

An 7 statt 8 Bit hatte ich noch nicht gedacht. So könnte man PWM im Interrupt-Handler belassen. Ich werde das in meine Überlegungen mit einbeziehen. Danke.

mfg
Gerold
:-)

Besserwessi
15.02.2008, 20:22
Den PWM kann man schon im Interruptshändler lassen. In Assembler solle man für jeden Kanal etwa 6-10 Zyklen brauchen, wenn die Portbits einigermaßen zusammenhängen. Bei 10 kanälen also etwa 60-100 Zyklen für die ganze ISR Routine das ist noch nicht so viel. Wenn man alle 256 Zyklen den Interrupt aufruft hätte man noch über die Hälfte der Rechenzeit übrig und käme bei 8 Bit Auflösung immer noch auf 20 MHz / 256 / 256 = 300 Hz Wiederhohlfrequenz. Flimmerfrei würden so sogar bis zu 50 LEDs gehen.

wkrug
16.02.2008, 18:38
bei 8 Bit Auflösung immer noch auf 20 MHz / 256 / 256 = 300 Hz Wiederhohlfrequenz. Flimmerfrei würden so sogar bis zu 50 LEDs gehen
Einspruch:
Du fährst mit diesen Parametern alle 256 Taktzyklen einen Timer Overflow Interrupt, wenn Du einen der 8Bit Timer verwendest.
Das sind im Günstigsten Fall ca. 250 Assembler Befehle.
Da der Einsprung und der Aussprung ja auch Rechenzeit verbrät bleibt Dir dann für die Hauptroutine fast nichts mehr übrig.

Eine Alternative wäre es noch den 16Bit Timer im Comparematch Mode mit CTC laufen zu lassen.
Damit wäre dann die PWM Frequenz, sowie die anzahl der Takte dazwischen ( voneinander abhängig ) in weiten Grenzen einstellbar.

Hir hat auch schon jemand mal eine Rotine vorgestellt, die die einzelnen Kanäle nach ihrer Pulsbreite sortiert und den Comparematch dann von einem zum nächsten Kanal weiterschaltet.
Somit können bei einem Timerdurchlauf alle gewünschten Kanäle bedient werden. Dadurch kann mit sehr hohen Prescale Raten gearbeitet werden, was Rechenzeit für das Hauptprogramm bringt.

Besserwessi
16.02.2008, 19:25
Ich komme in Assembler auf relativ wenige Zyklen (ca.60 bis vielleicht 100) für 10 Software PWM-Kanäle. Damit wird bei einem Aufruf alle 256 Zyklen nicht mal die Hälfte der Rechenzeit verbraucht. Da hier in Assembler mit dem carryflag und Shits gearbeitet wird, kann es gut sein, das die C oder Basic Compliler hier deulich langsamer sind.

Wenn es der Timer zuläßt (CTC, Prescaler oder notfalls per reload im Interrupt) kann man natürlich eine niedrigere Frequenz wählen.

python_rocks
17.02.2008, 18:43
Ich möchte mich am Wochenende an I²C versuchen und als Beispielanwendung werde ich 12 LEDs verschieden stark dimmen lassen.
Hallo!

War wohl nichts. Das Wochenende ist für andere Aktivitäten drauf gegangen. :-(

mfg
Gerold
:-)

mycroc
17.02.2008, 20:50
warscheinlich werden ja 12 Analog Ausgänge benötigt. Ich habe mal 16 Analoge so realisiert. Ein PWM Ausgang des Controlers geht an 16 (oder auch 12) eingänge mehrerer 74LS126  (3-state ausgang). An jedem Ausgang ist ein R C Glid und Anschließend ein OpAmp in verstärker schaltung, in meinem fall 2fach für 0-10V. Man kann dann einen Treieber (74LS126) über denn E eingang aktiviren über die PWM den Kondensator auf die gewünsachte spannung bringen und den treiber abschalten. Bis sich der Kondensator über den OpAmp entladen hatt, ist genügend zeit für andere aufgaben.


Elektro-Jack
11.04.2008, 20:43
Hi

ich hätte die Idee mit dem Philips Chip
PCA9532 (1,75€ bei Reichelt !!) im SMD Gehäuse

12 PWM LED Ausgänge über I2C Bus

Mus man natürlich noch ein wenig hinprogrammieren.

Gruß dirk

zwanzischmark
11.04.2008, 20:54
danke, habe es inzwischen mit MAX6967 gelöst, die gibts als sample bei maxim. 10 Kanäle und SPI Bus. Davon 3 hintereinander gehängt gibt 30 Kanäle - Super sache!