7 Segment Laufschrift

Dieses Thema im Forum "Software" wurde erstellt von Janiiix3, 8. Juni 2018.

  1. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Bei dem ganzen "Scroll Kram" fehlt mir irgendwie die Logik.
    Ich habe mir selber eine 7 Segmentanzeige mit LED´s gebaut und dieses dann vergossen.
    Das ganze wird über einen Portexpander (I2C) angesteuert. Funktioniert auch wunderbar.
    Die einzelnen Digits ( 4 Stk. ) werden über "disp.dig[0].. disp.dig[3]" mit Informationen gefüttert.
    Es sollen lediglich Zahlen durch die Anzeige rasen ( von rechts nach links.. ).
    Mir fehlt es total an der Logik!
    Wie gehe ich vor?

    An alle schon mal ein schönes Wochenende ;)
     
  2. Dirk

    Dirk Administrator
    Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.198
    Zustimmungen:
    119
    Punkte für Erfolge:
    63
    Sprachen:
    C, Assembler, Pascal, C++, PHP, Java
    Hi Jan,

    in "disp.dig[0].. disp.dig[3]" werden dann sicherlich die Segmentdaten für die 7-Segmentanzeigen enthalten sein.

    Deine Variable wird also zuvor in vier BCD Zahlen zerlegt, Einer, Zehner, Hunderter und Tausender.
    Jede BCD Zahl wird dann nach Siebensegment dekodiert (der Dekoder ist abhängig vom Anschluss deiner Anzeigen an den/die Portexpander).

    Das funktioniert ja anscheinend.

    Wenn du scrollen möchtest, musst du doch einfach nur die vier siebensegment-dekodierten BCD Werte in einer anderen Reihenfolge in die Variablen "disp.dig[0].. disp.dig[3]" kopieren. Ich würde mir hier eine Funktion schreiben, die mir das automatisch macht, mit einem Parameter Index für die Position der Einerstelle (zB).
     
  3. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Moin Dirk,

    Einzelne Zeichen kann ich schon durch das Display "scrollen" ( von rechts nach links )..


    CodeBox C und C++
    const char msg[] = "0123456789";
    
    void scrollMessage( const char *msg )
    
    {
    while( *msg )
    {
    for ( [I]uint8_t[/I] i = 0 ; i < 4 ; i++ )
    {
    disp.dig[ 3 - i ] = *msg - '0';
    [I]_delay_ms[/I](150);
    disp.dig[ 3 - i ] = 11;
    }msg++;
    }
    
    }
    

    Dann hört es aber auch schon auf :(
     
  4. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.979
    Zustimmungen:
    45
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Wie wäre folgende Idee:
    Die Botschaft liegt als Array (String) bereits in Segmentkodierter Form vor.
    Du implementierst einen Zyklenzähler (jeder Schritt bzw jedes Bild).
    Die Segmentanzeigen sind auch nummeriert.
    In jedem Zyklus sendest Du an jede Anzeige Botschaft(Segmentnummer+Zykluszahl). Landet dieser Index außerhalb der Botschaft, ist das Zeichen " " zu senden.
     
  5. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Was meint ihr jetzt mit "Segmentkodierter Form"?
    Also ich habe bereits mein ganzen Zeichensatz angelegt und kann diesen gezielt auf die einzelnen Digits werfen.

    z.B so


    CodeBox C und C++
    disp.dig[0] = 0
    disp.dig[1] = 1
    disp.dig[2] = 2
    disp.dig[3] = 3
    

    Kann ich die Werte auf der Anzeige darstellen.
    Nun brauche ich noch eine Funktion ( wie @Dirk schon oben geschrieben hatte, die mir die ganzen Zeichen in das Array knallt ).
    Dabei fehlt mir jeglicher Ansatz wie ich das als Laufschrift realisieren soll ( das logische denken fehlt mir irgendwie.. ).
     
  6. addi

    addi Mitglied

    Registriert seit:
    2. September 2013
    Beiträge:
    105
    Zustimmungen:
    3
    Punkte für Erfolge:
    18
    Sprachen:
    BascomAVR, C, Assembler
    Hmm..
    Auch wenn es etwas ot ist, wie wärs mit hintereinandergeschalteten spi schieberegistern z.b. sn74xx165.
    Da brauch man 'nur' rausschieben.
    73 addi
     
  7. TommyB

    TommyB Premium Benutzer

    Registriert seit:
    17. Mai 2010
    Beiträge:
    1.703
    Zustimmungen:
    57
    Punkte für Erfolge:
    48
    Sprachen:
    Assembler, LunaAVR, VB.Net, Python, C#
    Du meinst so in etwa?




    CodeBox BascomAVR
    Friend Module App
    
        Friend Sub Main()
    
            Const Value As String = "Hallo Welt"        ' Text zum Anzeigen
            Const Width As Integer = 4                        ' Anzahl Stellen im Display
    
            Dim VRAM(Width - 1) As Char                    ' Display "Speicher"
            Dim Pos As Integer                                    ' Gescrollte Position
            Pos = -Width
    
            ' Hauptschleife
            Do
    
                ' VRAM beschreiben
                For RamPos = 0 To Width - 1
                    If Pos + RamPos < 0 Then ' Linke Leerzeichen
                        VRAM(RamPos) = " "c
                    ElseIf Pos + RamPos > Value.Length - 1 Then    ' Rechte Leerzeichen
                        VRAM(RamPos) = " "c
                    Else ' Innerhalb echtem Wert
                        VRAM(RamPos) = Value(Pos + RamPos)
                    End If
                Next
    
                ' Position aktualisieren
                If Pos = Value.Length + Width Then
                    Pos = -Width
                Else
                    Pos += 1
                End If
    
                ' Ausgeben
                Console.CursorTop = 0
                Console.CursorLeft = 0
                Console.Write(VRAM)
                Console.Write("    Pos=" & Pos & "   ")
    
                ' Etwas warten (500ms)
                Threading.Thread.Sleep(500)
    
            Loop
    
        End Sub
    
    End Module
    


    So würde man es in der PC Entwicklung natürlich nie umsetzen, ich hab mich an die Gegebenheiten eines Controllers gehalten. Ist zwar VB.Net, aber das Prinzip sollte klar sein.

    Aber wie immer: Viele Wege führen nach Rom.
     
    Janiiix3 gefällt das.
  8. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    @TommyB genau so sollte das aussehen. Das muss ich jetzt irgendwie auf den Controller übertragen bekommen, sprich in C umsetzen.
     
  9. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.979
    Zustimmungen:
    45
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Um vier Zeichen fix (fest) auf den Anzeigen auszugeben, sagen wir mal "1234", gibst Du auf die erste Anzeige "1", auf die zweite "2", auf die dritte "3" und auf die letzte "4"aus.
    Zb so:
    Du hast das Array mit den Einträgen {1,2,3,4} und gibst an Anzeige1 Array(1), an Anzeige2 Array(2) usw aus.
    Das ganze zu verschieben, benötigst Du einen Offset - nennen wir ihn x
    Anzeige1 Array(1+x), Anzeige2 Array(2+x), Anzeige3 Array(3+x)… mit x=1 würde also "234 " erscheinen, mit x=-1 " 123" (wobei man sich noch um die Leerzeichen kümmern muß (immer dann, wenn die Summe kleiner null oder Größer als die Arraylänge wird)).

    Wenn Du das ganze in einer Schleife mit inkrementierenden/dekrementierenden x durchführst, scrollt die Darstellung.

    Statt der Zahlen werden Bitmuster an die LED-Segmente gesendet - Du hast also 'ne Tabelle mit Zehn Bytes (und dem fürs Leerzeichen). Das Array referenziert nun den konkreten Eintrag in der Tabelle.

    Nachtrag: statt den Offset zu inkrementieren/dekrementieren, kannst Du in der Schleife auch mit dem ADC ein Potentiometer digitalisieren, und das Ergebnis als Offset verwenden. Dann würdest Du mit dem Poti quasi die Botschaft hin- und herschieben.
     
    #9 LotadaC, 8. Juni 2018
    Zuletzt bearbeitet: 9. Juni 2018
  10. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Du meinst.:


    CodeBox C und C++
    for ( uint8_t i = 0 ; i < 4 ; i++ )
    {
         disp.dig[0-i] = 1;
         disp.dig[1-i] = 2;
         disp.dig[2-i] = 3;
         disp.dig[3-i] = 4;
    }
    

    verstehe ich das richtig?
    Wenn ich das so machen würde, würde ich doch in einen Bereich kommen der für mein "Array" nicht mehr reserviert ist. Ist doch arg fahrlässig...
     
    #10 Janiiix3, 9. Juni 2018
    Zuletzt bearbeitet: 9. Juni 2018
  11. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.979
    Zustimmungen:
    45
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Genau deswegen mußt Du Dich...
    Nein.
    disp.dig[0..3] sind Deine vier digits, korrekt?
    Und mit einer Zuweisung (disp.dig[n]=x) kannst Du auf einem (n) digit 'ne Ziffer (x) oder 'n leer darstellen, korrekt?

    Statt die Ziffer direkt zuzuweisen ist Dein Ziel, einen Teil einer Botschaft darzustellen - eben das Zeichen an Stelle y der Botschaft.
    y ist also Dein Offset.
    Digit[0] wäre also Botschaft[0+y] zuzuweisen, Digit[1] Botschaft[1+y] (wobei Du eben prüfen mußt, ob dieser Index in der Botschaft existiert - ansonsten weist Du das Leerzeichen zu).

    Wenn Du y änderst und danach das ganze neu ausgibst, verschiebt sich der angezeigte Teil der Botschaft genau um diesen Offset.
     
  12. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Ich habe mich mal mit @TommyB kurz geschlossen und seine Version versucht in "C" umzusetzen.
    Leider haut das nicht so hin wie bei ihm in vB.net. Sieht jemand woran es liegen könnte?



    CodeBox C und C++
    void scrollMessage( char *str )
    {
        char msg[] = "123456789";
        const uint8_t width = 4;
        char vram[width];
        int8_t pos = 0;
        pos -= width; 
      
        while (1)
        {
            for ( int8_t ramPos = 0 ; ramPos < width ; ramPos++ )
            {
                if ( (pos + ramPos) < 0 )
                {
                    vram[ramPos] = 11; // Leerzeichen
                }
                else if ( (pos + ramPos) > strlen(msg)  )
                {
                    vram[ramPos] = 11; // Leerzeichen
                }
                else
                {
                    vram[ramPos] = msg[ pos + ramPos ] - '0';
                }
          
                if( pos == strlen(msg) + width )
                {
                    pos = -width;
                }
                else
                {
                    pos += 1;
                }
            } 
          
            for ( uint8_t i = 0 ; i < 4 ; i++ )
            {
                disp.dig[i] = vram[i];
                _delay_ms(250);
            } 
        }
    }
    
     
  13. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.979
    Zustimmungen:
    45
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Die erste For-Schleife endet falsch.
    Und das delay in Zeile 39 ist auch schlecht platziert, oder?

    Aber warum so kompliziert?
    Derzeit hast Die die Originalmessage (in Zeile 3 definiert).
    In der ersten For-Schleife kritzelst Du Dir davon einen Teil auf einen Schmierzettel (vram - ab Zeile 11).
    Dann verschiebst Du den Offset (if-else ab Zeile 26, für den nächsten Durchlauf (der ersten For-Schleife)).
    In der letzten For-Schleife (Zeile 36ff) übermittelst Du, was Du auf dem Schmierzettel hast.

    Wozu der Schmierzettel? Warum knallst Du das nicht gleich in der ersten Schleife auf die vier Digits?
     
    TommyB gefällt das.
  14. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Was endet falsch?
    Das "_delay" war in der Tat falsch plaziert.

    Das mit dem "vram" stimmt natürlich auch. Habe es direkt so von @TommyB Variante übernommen. Ist jetzt draußen.
    Hier die aktuelle Version.



    CodeBox C und C++
    void scrollMessage( char *str )
    {
       char msg[] = "123456789";
       const uint8_t width = 4;
       
       int8_t pos = 0;
       pos -= width;   
       
       while (1)
       {
           for ( int8_t ramPos = 0 ; ramPos < width ; ramPos++ )
           {
               if ( (pos + ramPos) < 0 )
               {
                   disp.dig[ramPos] = 11; // Leerzeichen
               }
               else if ( (pos + ramPos) > strlen(msg) )
               {
                   disp.dig[ramPos] = 11; // Leerzeichen
               }
               else
               {
                   disp.dig[ramPos] = msg[ (pos + ramPos) ] - '0';
               }
           
               if( pos == ( strlen( msg ) + width ) )
               {
                   pos = -width;
               }
               else
               {
                   pos += 1;
               }
           }   
           
           _delay_ms(1000);   
       }
    }
    


    Was natürlich noch ungünstig ist, ist die "while(1)" diese muss später noch raus, sonst werden keine anderen Texte durch flitzen.
     
  15. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.979
    Zustimmungen:
    45
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Die erste (bzw jetzt einzige) For-Schleife. Thomas hatte sie mit VRAM beschreiben kommentiert.
    NACH der Schleife hat er mit IF..Else..end die Position aktualisiert (den Offset verschoben).
    Das steckt bei Dir IN der For-Schleife. Du inkrementierst also pos mit jedem Digit statt einmal pro Frame.

    Klammercode-Fehler:p

    eher das Delay.
    Sinniger wäre, 'n Sekundentick zu generieren, und dieses in der Hauptschleife zu pollen, und nur einmal pro Sekunde das ganze durchgehen lassen.

    Dann kannst Du im restlichen Programm andere Nachrichten Empfangen zB vom UART, irgendwelchen Sensoren oder was auch immer, und diese Deiner Message zuweisen.
     
  16. TommyB

    TommyB Premium Benutzer

    Registriert seit:
    17. Mai 2010
    Beiträge:
    1.703
    Zustimmungen:
    57
    Punkte für Erfolge:
    48
    Sprachen:
    Assembler, LunaAVR, VB.Net, Python, C#
    Oh, ist mir gar nicht aufgefallen... Naja, ich und C :rolleyes:

    Deswegen schreib ich auch immer hinter } was geschlossen wird.


    CodeBox C und C++
    } // End If

    In Python genau so. Nur ist es da noch fieser weil es da kein Ende gibt, das wird anhand der Einrückung ermittelt.
    Alles Scheunentore für Flüchtigkeitsfehler...
     
  • Über uns

    Unsere immer weiter wachsende Community beschäftigt sich mit Themenbereichen rund um Mikrocontroller- und Kleinstrechnersysteme. Neben den Themen Design von Schaltungen, Layout und Software, beschäftigen wir uns auch mit der herkömmlichen Elektrotechnik.

    Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  • Coffee Time

    Unser makerconnect-Team arbeitet hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und unser eigener makerconnekt-Server regelmäßig gewartet wird. Wir nehmen das Thema Datensicherung und Datenschutz sehr ernst und sind hier sehr aktiv, auch sorgen wir uns darum, dass alles Drumherum stimmt!

    Dir gefällt das Forum und die Arbeit unseres Teams und du möchtest es unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft, unser Team freut sich auch über eine Spende für die Kaffeekasse :-)
    Vielen Dank!
    Dein makerconnect-Team

    Spende uns! (Paypal)
  1. Diese Seite verwendet Cookies, um Inhalte zu personalisieren und die Seite optimal für dich anzupassen. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden