Forum: Mikrocontroller und Digitale Elektronik Frage zu 8-kanaliger Soft-PWM


von Sascha (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
um 8 LEDs unabhängig voneinander langsam heller und wieder dunkler 
werden zu lassen, habe ich versucht, das Beispielprogramm aus dem 
Artikel Soft-PWM http://www.mikrocontroller.net/articles/Soft-PWM
(die 1. Variante) zu verstehen und zu modifizieren. Bisher habe ich es 
immerhin geschafft, den PWM-Wert für Pin D0 in einer schleife hochlaufen 
zu lassen. Aber jetzt ist meine große Frage:
Wie schaffe ich es, 8 Kanäle mit verschiedenen Geschwindigkeiten und 
Startzeiten hoch-und  runterlaufen zu lassen?
Geanau wie im Artikel verwende ich einen ATMEGA32 mit internen 8MHz.
Für hilfreiche Tipps oder Links, die anfängertauglich sind, bin ich sehr 
dankbar!

Sascha

von Karl H. (kbuchegg)


Lesenswert?

> ISR(TIMER1_COMPA_vect)
> {
>    static uint8_t pwm_cnt=0;
>    uint8_t tmp=0, i=0, j=1;

>   //const uint8_t t1[8]={27, 40, 3, 17, 150, 99, 5, 9};
>   //pwm_setting[8]=t1[8];


>   pwm_setting[0]=PWM_ch1;


Ähm.
Was hat das da drinn verloren? Das gehört da nicht her.

Du scheinst nicht kapiert zu haben, dass das Array pwm_setting die 
Helligkeiten darstellt. Willst du die LED 0 auf eine Helligkeit von 34 
haben, dann macht die Hauptschleife irgendwann

    pwm_setting[0] = 34;

und wenn die LED 3 auf eine Helligkeit von 78 gesetzt werden soll, dann 
eben

    pwm_setting[3] = 78;

etc. etc.

Und wenn in main beispielsweise LED 0 und LED 7 gegengleich gedimmt 
werden sollen, dann beispielsweise eben

....

   for( i = 0; i < 255; i++ ) {
     pwm_setting[0] = i;
     pwm_setting[7] = 255 - i;

     _delay_ms( 100 );
   }

oder was auch immer du dir an Zusammenhängen ausdenkst. Du schreibst die 
entsprechenden Zahlenwerte ins Array pwm_setting an die Index-Position 
der jeweiligen LED und der ISR Mechanismus setzt das in eine Helligkeit 
um.

von Sascha (Gast)


Lesenswert?

Vielen Dank für die schnelle Antwort,
dass im Feld "pwm_setting[]" die 8 PWM-Werte stehen war mir schon klar.
Die zwei auskommentierten Zeilen sind von Versuchen übriggeblieben. der 
Rest ist so aus dem Artikel kopiert.

Trotzdem sehe ich jetzt etwas klarer. Aber nochmal mein Beispiel:
Ich habe (erstmal nur) 2 LEDs, die erste wird langsam heller, und danach 
wieder dunkler, z.B. gesamte Periode 60s. Die zweite Led beginnt z.B. 
10s nach dem Start der ersten heller zu werden, läuft aber schneller 
hoch, so dass sie auch 10s eher wieder dunkel ist( Periode dann also 
40s).
Da will ich hin, wenn da jemand einen einfachen Lösungsansatz hat, wäre 
toll.
Ich stell mir das im Moment etwa so vor:

for(z=0;z<=360000;z++)      // das soll später auf 10h gestreckt werden, 
//(Aquarienbeleuchtung)
{
 pwm_setting[0]=z;          // 1. LED läuft sofort hoch
 if(z>=100)
   {
    pwm_setting[0]=(z-100)  // 2. LED startet nach 100*100ms=10s
   }
 my_delay (100);
}

Aber wie schaffe ich es, dass die 2. LED auch früher fertig ist?

Gruß
Sascha

von Sascha (Gast)


Lesenswert?

ich meinte natürlich in Zeile 7:
   pwm_setting[1]=(z-100)  // 2. LED startet nach 100*100ms=10s

Gruß
Sascha

von Karl H. (kbuchegg)


Lesenswert?

Sascha schrieb:

> Trotzdem sehe ich jetzt etwas klarer. Aber nochmal mein Beispiel:
> Ich habe (erstmal nur) 2 LEDs, die erste wird langsam heller, und danach
> wieder dunkler, z.B. gesamte Periode 60s. Die zweite Led beginnt z.B.
> 10s nach dem Start der ersten heller zu werden, läuft aber schneller
> hoch, so dass sie auch 10s eher wieder dunkel ist( Periode dann also
> 40s).
> Da will ich hin, wenn da jemand einen einfachen Lösungsansatz hat, wäre
> toll.


Wie praktisch immer, wenn es darum geht Zeitvorgaben zu erfüllen, führt 
der Weg über Timer bzw. weg vom Zeitdauer-Denken und hin zum Denken in 
Zeitpunkten.

Der Timer fungiert wie der Zeiger deiner Armbanduhr. Um mehrere Dinge 
'gleichzeitig' zeitlich zu variieren stellst du dir jede Sekunde neu dir 
Frage: Was genau gilt es jetzt, in dieser Sekunde, an den Ausgängen 
einzustellen.


> for(z=0;z<=360000;z++)      // das soll später auf 10h gestreckt werden,
> //(Aquarienbeleuchtung)

Und genau damit liegst du schon falsch. Sobald du hier for-Schleifen 
einsetzt um irgedwelche Verläufe zu realisieren, erleidest du 
Schiffbruch, sobald die Dinge etwas komplexer werden.


Du brauchst einen 2.ten Timer, der dir sowas wie eine 'Uhr' realisiert. 
Und aus der "Uhrzeit" musst du in der Lage sein, zb bei dir die 
Helligkeit der einzelnen LEDs zu errechnen.

ISR( ... )
{

  zb eine tatsächliche Uhrzeit weiterzählen (weil du Aquarium erwähnt
  hast

  if( Uhrzeit < 7 Uhr morgens )
    Helligkeit aller LED auf 0 setzen

  if( Uhrzeit zischen 7 Uhr und 7 Uhr + 255 Sekunden )
    Helligkeit LED 0 auf (UHrzeit - 7 Uhr) setzen

  if ....

  if( UHrzeit > 23 Uhr )
    Helligkeit aller LED auf 0 setzen

....
}

Das Prinzip sollte erkennbar sein. Du musst ZU JEDEM BELIEBIGEN 
ZEITPUNKT die Helligkeit der jeweiligen LED aus der Uhrzeit (und 
sonstigen Dingen wie zb die gerade zu diesem Tag vorliegende 
Mondstellung) ERRECHNEN können. Und wenn du das errechnen geschickt 
machst, dann ergibt sich daraus, dass zb von 7 Uhr früh bis 7:30  die 
LED von 0 bis auf 100% hochdimmen, weil aus deinen Formeln dann eben 
sich für alle dazwischen liegenden Sekunden ein jeweils geeigneter 
Dimmgrad ergibt.

Und diese Systematik kannst du dann eben auch für 200 LED 'gleichzeitig' 
machen. Denn jede LED hat ihren eigenen Formalismus, in den die Uhrezeit 
reingeht und aus dem heruaskommt, in welcher Helligkeit genau diese LED 
zu genau dieser Uhrzeit (und möglichen anderen Faktoren) zu sein hat.

von Sascha (Gast)


Lesenswert?

Danke, dann werde ich in dieser Richtung weiterlesen und 
experimentieren.
Gruß
Sascha

von Karl H. (kbuchegg)


Lesenswert?

HInzuzufügen ist noch, dass dieses Zeitpunkt-Prinzip bei dem man aus der 
Uhrzeit die Helligkeit errechnet zb bei einem Aquarium gut funktioniert.

Das muss aber nicht so sein. Es gibt auch noch andere Möglichkeiten.
Ausgangspunkt ist wieder der Timer, der eine ISR zb alle 1 Sekunde 
aufruft. Aber anstatt aus einer Uhrzeit etwas zu berechnen, kann man 
auch hergehen und sich zuvor ausrechnen, welche LED sich im 
Sekundenabstand wie verändern muss. In der ISR wird dann nur noch diese 
Vorgabe ausgeführt, indem man den Helligkeitswert dieser LED 
entsprechend der Vorgabe variiert.

Allen gemeinsam ist aber immer das Prinzip: Dimmschleifen werden durch 
einen Timer ersetzt, der in regelmässigen, immer gleichen Zeitabständen 
eine ISR aufruft. Und innerhalb der ISR gibt es dann wieder viele 
Möglichkeiten, wie es weiter gehen kann. Je nach Aufgabenstellung.

von martan (Gast)


Lesenswert?

hilfreich war für mich dieser Artikel (welche Sprache ist da egal, 
bezüglich der Technik):

http://avr.myluna.de/doku.php?id=de:multiled

von interceptor (Gast)


Lesenswert?

martan schrieb:
> hilfreich war für mich dieser Artikel (welche Sprache ist da egal,
> bezüglich der Technik):
>
> http://avr.myluna.de/doku.php?id=de:multiled

Interessante Lösung! wenn ich das richtig verstanden habe, werden die 
einzelnen LED-Kanäle nach ihrer Pulsweite aufsteigend sortiert und 
gleiche Pulsweiten verschiedener Kanäle zusammengefasst. Die ISR läuft 
mit einer festen Frequenz und es werden alle gesammelten Einträge 
durchlaufen und gesetzt/gelöscht. Das Ganze ist also unabhängig von der 
Anzahl der Kanäle, simpel und genial.

Wie heißt dieser Algorithmus? war mir bisher unbekannt.

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
Noch kein Account? Hier anmelden.