-         

Seite 1 von 3 123 LetzteLetzte
Ergebnis 1 bis 10 von 27

Thema: LEDschaltung im PingPong

  1. #1
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.554

    LEDschaltung im PingPong

    Anzeige

    Hallo Alle,

    seit einiger Zeit sitze ich über einer PingPongPlatine und will die (Benutzer-)Oberfläche des Originals in C nachbauen. Geht ja unheimlich langsam, zumal ich das erste Mal Schieberegister bedienen musste.

    Einiges verstehe ich an der Schaltung nicht, ich will aber nicht gleich den Autor anschreiben und nachfragen (zu schüchtern - aber wenns nicht anders ginge . . .). Vielleicht hat jemand von euch schon darüber nachgedacht und kann mir das beantworten. Ich verstehe zu wenig von Schaltungstechnik um mir das zu erklären.
    A) Warum sind die LEDs in einer Zeile angeordnet? Zur Schaltung.
    B) Warum ist hier das zeitraubende Füttern der Schieberegister nicht mit der schnellen Variante über die SPI-Hardware realisiert worden?

    Zu A) Wenn ich mehrere LEDs in einer Reihe anknippse, dann sinkt natürlich die Helligkeit, weil der Controllerport nicht unbegrenzt Strom liefern kann. Das sehe ich auch am Pegel im Oskar. Ginge das nicht anders zu lösen?
    Habe ich da vielleicht einen Denkfehler und müsste ich die LEDs in einer Zeile EINZELN takten? Derzeit knippse ich die LEDs zeilenweise an oder aus - je nachdem, ob sie gebraucht werden oder nicht. Aber wenn ich die LEDs wirklich nur Stück für Stück schalte, wird der ganze Ablauf NOCH langsamer - siehe B). Derzeit habe ich eine Taktzeit von rund 2,5 ms für einen kompletten Durchlauf. Dabei bleibt mir zwischen den LED-Anknipps-ISRs genug Zeit für mein Hauptprogramm - ca. 50 % der CPU-Zeit.

    Zu B) Im RNWissen steht die Variante "Füllen des Portexpanders" über SPI-Hardware als DIE schnelle Lösung. Und ich muss das Ganze mühselig mit Clock-high/Clock-low hineinhacken. Fazit: die CPU-Zeit für das "restliche" Programm ist nicht so pfiffig hoch.

    Danke schon jetzt für eure Antworten.
    Ciao sagt der JoeamBerg

  2. #2
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    66
    Beiträge
    10.970
    Hallo!

    Ich verstehe leider dein Problem nicht ganz, deshalb kann ich leider nur meine Gedanken über die Schaltung äussern.

    Zitat Zitat von oberallgeier Beitrag anzeigen
    A) Warum sind die LEDs in einer Zeile angeordnet?
    Die LED's sind in Matrix geordnet und wegen fehlenden high-side Treiber am AVR angeblich nur einzeln zum Steuern vorgesehen.

    Zum B) musst du leider den Entwickler selber fragen, aus welchem Grund er das so realisiert hat.

    Über Programmiersprache C habe ich k.A.
    MfG (Mit feinem Grübeln) Wir unterstützen dich bei deinen Projekten, aber wir entwickeln sie nicht für dich. (radbruch) "Irgendwas" geht "irgendwie" immer...(Rabenauge) Machs - und berichte.(oberallgeier) Man weißt wie, aber nie warum. Gut zu wissen, was man nicht weiß. Zuerst messen, danach fragen. Was heute geht, wurde gestern gebastelt. http://www.youtube.com/watch?v=qOAnVO3y2u8 Danke!

  3. #3
    Erfahrener Benutzer Roboter Genie Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.410
    Blog-Einträge
    101
    Hallo,
    für mich ist das eine typische Schaltung fürs Multiplexing und geb mal meine Gedanken dazu ab.

    Der Schaltung nach würde ich in einer Spalte alle LEDs, die leuchten sollen, über den Controllerport mit high einschalten. Die Minus kommt für die EINE Spalte von den 4094 Schieberegistern. Entprechender Schieberegisterausgang muß also auf low liegen, alle anderen auf high. Damit wird jeder µC Pin zu einer Zeit nur mit einer LED belastet.


    Programmablauf in etwa:

    Code:
    Ein FF byte in die Schieberegister. Mit einem Strobe (high Impuls auf STR) die Daten zu den Ausgängen durchschalten.
    
    LABEL1:
    
    Alle Zeilen µC Pins auf low
    Nix leuchtet
    
    EIN low bit in die Schieberegister und mit strobe durchschalten.
    µC Pins bei denen die LEDs der ersten Spalte leuchten sollen, auf high.
    
    LEDs der ersten Spalte leuchten.
    
    LABEL2:
    
    Alle Zeilen µC Pins auf low
    EIN high bit in die Schieberegister nachschieben und mit Strobe durchschalten. Das erste low ist nun in nächster Spalte.
    Zeilen µC Pins für diese Spalten LEDs auf high.
    
    LEDs der nächsten Spalte leuchten.
    
    Weiter bei LABEL2 solange bis alle Spalten durch sind, dann nach LABEL1
    SPI könnte ich hier nicht sinnvoll verwenden, da hier die Spalten und Zeilen synchronisiert sein müssen. SPI schiebt ja immer, soweit ich weis, mindestens ein Byte raus. Bei oben beschriebenen Ablauf muß gezielt immer ein Bit raus.

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  4. #4
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    54
    Beiträge
    5.781
    Blog-Einträge
    8
    Hallo

    Habe ich da vielleicht einen Denkfehler und müsste ich die LEDs in einer Zeile EINZELN takten?
    Ich bin mir auch nicht sicher, ob ich das Problem richtig verstehe. Aber bevor du den Pong-Entwickler belästigen mußt, frag uns ;)

    Für einen schnellen Bildaufbau musst du das Pong spaltenweise ansteuern. Als Initialisierung schiebt man 12 mal eine '1' in die Schieberegister und gibt diese dann aus. Dadurch erlöschen alle LEDs, unabhängig von der Zeilenansteuerung. Nun setzt man alle Zeilenansteuerungen auf "0". Das ist die Startbedingung nach dem Einschalten.

    Für ein neues Bild startet man mit einer "0" die man in die Schieberegister schiebt und ausgibt. Dann setzt man die Zeilenansteuerung für die 1.Spalte, wartet kurz und schaltet die Zeilenansteuerung wieder aus. Für die zweite Spalte schiebt man nun eine "1" nach und gibt wieder aus. Dann setzt man das Zeilenmuster für die zweite Spalte, warten, löschen, "1" reinschieben, ausgeben, Zeilenmuster für dritte Spalte, warten, und weiter und schneller, schneller, schneller: Bild :)

    Das habe ich hier auch schon mal beschrieben:
    http://www.roboternetz.de/community/...l=1#post496795

    Hardware-SPI bringt hier keinen Vorteil, weil man die Zeilenansteuerung eh erst setzen kann, wenn die Spaltenansteuerung gesetzt ist. Dann kann man es auch selbst ausgeben: Datenbit setzen, reinschieben und ausgeben.

    Im anderen Pong-Thread verwende ich aber beide Ansteuerungen, den schnellen Spaltenweisen bei den Helligkeitsstufen und den langsameren beim LED-Sensor.

    Ich hoffe das hilft. Es ist ja mit anderen Worten das selbe was Searcher schreibt ;)

    Gruß

    mic
    Geändert von radbruch (11.03.2011 um 22:38 Uhr) Grund: Logik der Spaltenansteuerung war invertiert ;)

    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    29.05.2005
    Beiträge
    1.018
    Hallo oberallgeier,

    jetzt weisst du warum das Ding PigPong heissen müsste.
    Pig steht nämlich für zeilenweise Ausgabe und Pong für Spaltenausgabe

    Gruß vom
    Sternthaler

    P.S.: Im übrigen scheint das neue Forumsdesign auch automatisch meine echt überflüßigen Kommentare gelöscht zu haben. Bin ja nun wieder weit unter 1000.
    Lieber Asuro programieren als arbeiten gehen.

  6. #6
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.554
    Danke euch dreien für die Ausführungen.

    Zitat Zitat von radbruch Beitrag anzeigen
    ... Das habe ich hier auch schon mal beschrieben ...
    Ja, das hatte ich (leider nur) überflogen, bevor mich die Schnapsidee überkam das selbst zu machen. Und so läuft das ja auch bei mir. Die LED-Ansteuerung hatte ich mir zu Beginn meiner Überlegungen am Oskar angesehen (2-Kanal analog) und daraus Timing und Schaltweise entnommen. Die Funktion LED=an wenn A high und K low ist war dann Ausgangspunkt für die Steuerung.

    Realisiert ist die Ansteuerung der LEDs in einer ISR die alle 250 µs aufgerufen wird. Darin wird die vorhergehende Zeile ausgeschaltet, das Schieberegister mit dem aktuellen Bitmuster versorgt, aktiv geschaltet und danach die neue Zeile eingeschaltet. Frisst rund 50% CPU-Zeit und ergibt eine augenfreundliche Frequenz von 400 Hz. Meine Annahme war dabei, dass die 2000 Maschinenzyklen zwischen zwei Interrupts genug wären um IRS und Hauptprogramm abzuarbeiten. Und das funktionierte schon prächtig : die beiden Rackets laufen mit Potisteuerung brav in ihren Grenzen auf und ab.
    Code:
    // ===============================================================================
    //      Interruptroutinen
    // ===============================================================================
    // ===============================================================================
    // ===  Initialisierung der Ports auf ATMEGA8 AU auf Vektor 10 (1-19) TIMER0 OVF
    //                      Timer/Counter0 Overflow mit ###>>> 250 µs bei 8 MHz
    //TCCR0 |= (1<<CS01);           // 1/8  Prescaler, 250 µs bei 8 MHz
                                    // entsprechend 250*8 = 2000 Maschinenzyklen
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     ISR (TIMER0_OVF_vect)          // ISR schaltet LED der Reihe nach
     {                              //
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      SetBit (PORTD, 3);            // Zeitnahmeblink ein
      Izeit_1  ++;                  // Boardzeit hochtickern
      if (Izeit_1 == 4001) Izeit_1 = 1;   // ... und eingrenzen
      TC  ++;                       // ISR-Timercount incrementieren
      if (TC == 11) TC  = 1;        // ... und eingrenzen
                                    //
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    //      Es beginnt die Schalterei der LEDs, Zeile für Zeile,
    //      Zuerst "alte Zeile" ausschalten (case), danach Zeilenmuster einlesen
    // - - - - - - - - - - - - - - -
      switch (TC) {                 //
      case 1:                       //
        ClrBit (PORTB, 1);          // Zeile 0 aus - letzte Zeile
        break;                      // switch verlassen
      case 2:                       //
        ClrBit (PORTC, 0);          // Zeile 1 aus-
        break;                      // switch verlassen
      case 3:                       //
        ClrBit (PORTC, 1);          // Zeile 2 aus-
        break;                      // switch verlassen
      case 4:                       //
        ClrBit (PORTC, 2);          // Zeile 3 aus-
        break;                      // switch verlassen
    // - - - - - - - - - - - - - - -
      case 5:                       //
        ClrBit (PORTC, 3);          // Zeile 4 aus-
        break;                      // switch verlassen
      case 6:                       //
        ClrBit (PORTD, 4);          // Zeile 5 aus-
        break;                      // switch verlassen
      case 7:                       //
        ClrBit (PORTD, 5);          // Zeile 6 aus-
        break;                      // switch verlassen
      case 8:
        ClrBit (PORTD, 6);          // Zeile 7 aus-
        break;                      // switch verlassen
      case 9:
        ClrBit (PORTD, 7);          // Zeile 8 aus-
        break;                      // switch verlassen
      case 10:
        ClrBit (PORTB, 0);          // Zeile 9 aus-
        break;                      // switch verlassen
      default:
        break;
      }                             // Ende switch (TC), Zeile TC ausschalten
    // - - - - - - - - - - - - - - -
    //      "Alte Zeile" wurde ausgeschaltet, jetzt aktuelles Zeilenmuster einlesen
    //      Aktuell ist die Zeile TC
                                            //
      for (LPp = 4; LPp < 16; LPp++)
      {                                     //
        if (IsBitSet (L[TC], LPp))          // 
        { ClrBit (PORTB, dta); }            // Data low  <=> LED on
        else { SetBit (PORTB, dta); }       // Data high <=> LED off
        ClrBit (PORTB, clk);                // Clock low
        SetBit (PORTB, clk);                // Clock high
      }                             // Ende for (LPp = 0; LPp == 7; LPp++)
                                    //
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    //      Neue Zeilen einschalten mit case TC, danach strobe auf Schieberegister
    // - - - - - - - - - - - - - - -
      switch (TC) {                 //
      case 1:                       //
        SetBit (PORTC, 0);          // Zeile 1 ein - erste Zeile
        break;                      // switch verlassen
      case 2:                       //
        SetBit (PORTC, 1);          // Zeile 2 einschalten
        break;                      // switch verlassen
      case 3:                       //
        SetBit (PORTC, 2);          //
        break;                      //
      case 4:                       //
        SetBit (PORTC, 3);          //
        break;                      //
    // - - - - - - - - - - - - - - -
      case 5:                       //
        SetBit (PORTD, 4);          // Zeile 5 einschalten
        break;                      // switch verlassen
      case 6:                       //
        SetBit (PORTD, 5);          //
        break;                      //
      case 7:                       //
        SetBit (PORTD, 6);          //
        break;                      //
      case 8:                       //
        SetBit (PORTD, 7);          //
        break;                      //
      case 9:                       //
        SetBit (PORTB, 0);          //
        break;                      //
      case 10:                      //
        SetBit (PORTB, 1);          // Zeile 0 einschalten
        break;                      // switch verlassen
      default:
        break;
      }                             // Ende switch (TC), Zeile TC einschalten
    // - - - - - - - - - - - - - - -
    //      Neue Zeilen sind eingeschaltet, jetzt strobe
                                    //
      ClrBit (PORTB, str);          // Strobe low
      SetBit (PORTB, str);          // Strobe high
                                    // Ende Ausgabe für Zeilen
    // - - - - - - - - - - - - - - -
        ClrBit (PORTD, 3);            // Zeitnahmeblink aus
        //  Zeitnahme am 20. Feb. 2011: Routine x10 benötigt 
      return;                       // Ende ISR
     }                              //
    // ===============================================================================
    So - aufgefallen ist mir dabei, dass mehrere LEDs in einer Reihe leuchten können - ist ja klar, weil mehrere eben mehr Strom brauchen als eine *ggg*. Einfachstes Beispiel: beide Schläger stehen auf gleicher Höhe, es leuchten zwei LEDs in einer Reihe und damit sieht man ein klitzekleines Einbrechen der Helligkeit. Das stimmt ja auch mit einfachsten Überlegungen überein. Es ist kaum merklich - aber ich wollte wissen, ob diese Matrixfahrweise eben die LEDs einzeln oder zeilenweise ansteuert.

    Also - zeilenweise. Und der geringe Helligkeitseinbruch ist ja auch praktisch kaum zu sehen.

    Nochmal danke für die Hilfe.
    Ciao sagt der JoeamBerg

  7. #7
    Verwende für erste Versuch erstmal fertige Quellen in "C" -- http://www.elo-web.de/elo/mikrocontr...ng/laufschrift

    Ich selbst habe das Lauflicht auf 2 Module erweitert und keine delay-Schleifen mehr drinn -- der Quellcode ist aber schon sehr gut für den Anfang.

  8. #8
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.554
    Hi Jens, willkommen im Forum. Danke für Deine Hinweise.

    Zitat Zitat von Jens_Gr
    ... für erste Versuch erstmal fertige Quellen ... laufschrift ... habe ... keine delay-Schleifen mehr drinn ...
    Hmmmm - ich will ja kein Lauflicht machen sondern das PingPong in C möglichst genau nachbauen. Mir war im Eingangspost nicht klar, ob ich die Ansteuerung richtig verstanden hatte - weil es je nach Anzahl der leuchtenden LEDs in einer Zeile Helligkeitsunterschiede gibt. Und delays hab ich eigentlich nicht in die engere Wahl gezogen, der Controller läuft sowieso müde 8 MHz.

    Im gegenwärtigen Stand - Rackets bewegen - läuft die chose gut - siehe oberes Posting; demnächst kommt der Ball ins Spiel.
    Ciao sagt der JoeamBerg

  9. #9
    Benutzer Stammmitglied Avatar von funk3r
    Registriert seit
    13.10.2009
    Ort
    Niedernhall
    Beiträge
    41
    Hier gibt es eine Version in C
    http://blogs.zobniow.net/micro/2010/...onradde-board/

    @Laufschrift:
    Wie erweitert man das auf mehrere Module?
    Gibt es dazu fertigen Code?
    Grüßle Jo
    ______________
    ><(((°> Son of God through Jesus Christ his Son <°)))><
    Mein Blog: funk3r.de

  10. #10
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.554
    Zitat Zitat von funk3r
    Hier gibt es eine Version in C ...
    Diese Version von Piotr Platek hatte ich Anfang des Jahres getestet. Seltsamerweise lief ein eigenes Kompilat nicht sehr stabil und eine geringfügig veränderte Quelle (Starttext) lief mit wirren Zeichen und nicht reproduzierbar (irgendein Variablenüberlauf?). Die Kommentare fand ich auch etwas spärlich, jedenfalls kann ich mit meinen bescheidenen C-Kenntnissen den Ablauf nicht nachvollziehen.

    Es ist wie so oft: selbst geschrieben ist der Code meist verständlicher als abgekupfert (Ausnahmen von guten Codern gibts aber!). Daher auch meine eigenen Bemühungen - mit etwas mehr Kommentar und weniger Spaghetti.
    Ciao sagt der JoeamBerg

Seite 1 von 3 123 LetzteLetzte

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •