Forum: Mikrocontroller und Digitale Elektronik Atmega 8, 2 mal 74HC595, 16 LEDs , alles zu langsam


von Attila C. (attila)


Angehängte Dateien:

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

von Matthias (Gast)


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

von Attila C. (attila)


Lesenswert?

Matthias: Gerne! Aber wie? Ich krieg es einfach nicht gebacken.

von MaWin (Gast)


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...
}

von Attila C. (attila)


Lesenswert?

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 :-(

von Attila C. (attila)


Angehängte Dateien:

Lesenswert?

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?

von Josef D. (jogedua)


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).

von Josef D. (jogedua)


Lesenswert?

und wenn der µC zu langsam ist: es gibt pincompatible bis 20MHz!

von Attila C. (attila)


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.

von Attila C. (attila)


Lesenswert?

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.

von Frank K. (fchk)


Lesenswert?

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

von Josef D. (jogedua)


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 ...

von Oliver J. (skriptkiddy)


Lesenswert?

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

von Attila C. (attila)


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!

von Josef D. (jogedua)


Lesenswert?

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