Hallo! Zum Aufbau: Es hängen jeweils 8 LED an 2 74HC595 die von einem Atmega 8 mit 8MHz angesteuert werden. Die Idee: Die LEDs sollen mit zufälligen Geschwindigkeiten auf und abblenden. Zum Programm: In der ISR wird eine Variable "Zähler" bis 255 hochgezählt um eine Soft PWM zu generieren. Bisher gibt es 8 Funkionen (Stern0 bis Stern7) die bestimmen welchen Wert die Variablen "schwelle" haben durch die definiert wird bei welchem Zählerstand der jeweilige Pin high oder low sein soll. Das ganz wird dann "verANDet" und über die Schieberegister ausgegeben. Leider muss das Ganze in der ISR stattfinden da ja das Hauptprogramm nicht wissen kann wann wann der Timer mit dem zählen fertig ist. Dadurch wird das Ganze aber super-lahm. Wie kann ich das Ausgeben an die Schieberegister ins Hauptprogramm verlegen (in der Hoffnung das dann alles schneller wird) ohne das dabei Kraut und Rüben rauskommt. Oder ist (mal wieder) der Ansatz völlig falsch? Vielen Dank
Hi! Ich hatte auch Probleme mit dem ISR, und hab es ganz einfach gelöst: lass in der ISR nur zähler laufen, und werte sie im hauptprogramm aus. damit wirst du normalerweise schneller. Viele Grüsse, Matthias
Matthias: Gerne! Aber wie? Ich krieg es einfach nicht gebacken.
> Zum Aufbau: Es hängen jeweils 8 LED an 2 74HC595 die von einem Atmega 8 > mit 8MHz angesteuert werden. Wozu brauchst du die 595, ein ATmega8 hat selbst schon mehr als 16 Ausgänge a 20mA. > ISR (TIMER2_COMP_vect) umschreiben nach Space vs. Speed: { static int8_t zaehler=0; PORTB=pwm[zaehler]; PORTD=pwmA[zaehler]; zaehler++; // läuft selbst von 255 auf 0 über } Dafür muß man die Dimmwerte vorausberechnen: uint8_t pwm[256],pwmA[256]; uint8_t stern(uint8_t i) // nee, nicht 8 mal dasselbe... { static uint8_t schwelle[8]={0,0,0,0,0,0,0,0}; static uint8_t geschw[8]={1,1,1,1,1,1,1,1}; static uint8_t direction[8]={1,1,1,1,1,1,1,1}; static uint8_t zufall[8]={1,1,1,1,1,1,1,1}; if(--geschw[i]) { if (schwelle[i]==0) //Zählrichtung bestimmen direction[i]=1; //Aufwärts else if (schwelle[i]==255) direction[i]=0; //Abwärts if (direction[i]==1) //Wenn aufwärts schwelle[i]++; //dann aufblenden else if (direction[i]==0) //Wenn abwärts schwelle[i]--; //dann abblenden if (direction[i]==0&&schwelle[i]==0) //WEnn einmal auf und abgeblendet { zufall[i]=rand()%speed+1; //Neuer zufälliger Wert für geschw, nicht über 255 geschw[i]=zufall; } else geschw[i]=zufall[i]; //Sonst mit altem Wert weiter } return schwelle[i]; } void Himmel (void) { int i,schwelle; uint8_t n,m; for(n=0;n<8;n++) // Dimmwerte vorausberechnen { schwelle=stern(n); m=1<<n; for(i=0;i<schwelle;i++) pwm[i]|=m; while(i++) pwm[i]&=~m; } for(i=0;i<256;i++) pwmA[i]=0; // alle aus... }
Hallo MaWin! Ich brauche die 595 da es später viel mehr als nur 16 LEDs werden sollen. Dein Code sieht beeindruckend aus aber leider steige ich da kaum durch. Ich bin nicht erfahren genug um es zu verstehen :-(
So ist es schon deutlich schneller allerdings letztlich immer noch zu langsam weil ich insgesamt 6 Stück 74HC595 verbauen möchte. Hat noch jemand einen Trick auf Lager? Oder ist es schlichtweg illusorisch was ich vorhabe?
Wie viel fehlt den noch, was ist zu langsam? 16-bit-Variable (int) zu verwenden, wo auch 8-bit-Variable (uint8_t) reichen (z.B. schwelle und zaehler), macht es jedenfalls auch langsamer. Ausserdem müssen Zugriffe auf 16-bit-Variable (hier z.B. zaehler) im Allgemeinen atomar gemacht werden, das volatile allein reicht da nicht (da hier das High-Byte ausserhalb der ISR aber immer 0 bleibt, geht das hier zufällig gut).
und wenn der µC zu langsam ist: es gibt pincompatible bis 20MHz!
Josef: Danke für die Tips ich werde es ausprobieren. Zu langsam heisst dass wenn die Variable "speed" auf mehr als 100 gesetzt wird die LEDs anfangen zu "flackern" was nicht am langsamen auf und abblenden liegt sondern man hat förmlich den Eindruck das man sehen kann wie die einzelnen Bits durch die Schieberegister geschoben werden.
Natürlich kann man einen schnelleren Quarz benutzen. Ich möchte nur verhindern das das Problem daran liet das mein Konzept von vornhinein Käse ist.
Wenn Du Dir die Sache vereinfachen willst, greife einfach zu einem intelligenteren LED-Treiber wie dem TLC5940. Der hat 16 Ausgänge und macht selber intern 12 Bit PWM. Du musst also nur die 16 Helligkeistwerte hineinschieben, der Baustein macht den Rest. Für mehr LEDs kannst Du mehrere von den Bausteinen kaskadieren. fchk
das Konzept habe ich nicht weiter untersucht. Es ist immer schlecht, die selben (oder ähnliche) Dinge x mal hin zu schreiben. Es ist durchaus der Mühe Wert, MaWins Vorschlag zu verstehen. 12 Mal das Gleiche passiert ja in deiner Funktion PWM: if (zaehler ... Das MUSS man anders lösen. Noch zur Geschwindigkeit: hier muss 12 mal die 16-bit-Variabla zaehler neu aus dem Speicher gelesen werden (da volatile), statt dass Register benutzt werden können. Wenn man es schon so lässt, sollte man eine lokale Variable benutzen, z.B.:
1 | int tempZaehler; |
2 | cli(); // verhindern, dass während des Kopierens die ISR dazwischen kommt |
3 | tempZaelhler= zaehler; |
4 | sei(); |
5 | |
6 | if (tempZaehler ... |
Attila Ciftci schrieb: > Natürlich kann man einen schnelleren Quarz benutzen. Ich möchte nur > verhindern das das Problem daran liet das mein Konzept von vornhinein > Käse ist. Schau dir mal das hier an: Soft-PWM
@ Frank: Das ist natürlich auch eine gute Lösung! Ich werde mir das Teil genauer ansehen! @Josef: Ich habe deinen Rat befolgt und die Variablen als uint_t definiert. Vielleicht ist es Einbildung aber es scheint deutlich besser zu laufen. Daher ist es auch nicht nötig auf "Zaehler" anders zuzugreifen da dieser ja nur 8 bit hat (oder haben muss) Das Ding vom MaWin ist halt starker Tobak für einen Anfänger. Ich verstehe es nur teilweise und so gaz unkomentiert ist es ein ziemliches Gestocher. ich bin aber dran! Vielen Dank Leute!
Attila Ciftci schrieb: > Daher ist es auch nicht nötig auf "Zaehler" anders zuzugreifen da dieser > ja nur 8 bit hat (oder haben muss) das cli(); / sei(); kannst du dir dann sparen. Die lokale Variable ist aber trotzdem sinnvoll. Zusätzlich zum Geschwindigkeitsvorteil sollte das Programm mit der lokalen Variable auch noch kürzer werden; kannst du ja mal vergleichen.
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.