Atmega 8, 2 mal 74HC595, 16 LEDs , alles zu langsam

OP #2626308
Lesenswert?

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
Angehängte Dateien:
Gast #2626312
Lesenswert?

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
Gast #2626371
Lesenswert?

> 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...
}
#2626611
Lesenswert?

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).
OP #2626621
Lesenswert?

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.
#2626645
Lesenswert?

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 ...
OP #2626661
Lesenswert?

@ 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!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren