7 Segment Laufschrift

  • Frohe Ostern

Janiiix3

Aktives Mitglied
28 Sep 2013
1.293
10
38
Hannover
Sprachen
C, 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 ;)
 

Dirk

Administrator
Teammitglied
28 Jan 2007
4.241
127
63
Mittelhessen, Giessen
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).
 

Janiiix3

Aktives Mitglied
28 Sep 2013
1.293
10
38
Hannover
Sprachen
C, 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 :(
 

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3.143
58
48
Hennigsdorf
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.
 

Janiiix3

Aktives Mitglied
28 Sep 2013
1.293
10
38
Hannover
Sprachen
C, 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.. ).
 

addi

Mitglied
2 Sep 2013
115
4
18
Hamminkeln
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
 

TommyB

Premium Benutzer
17 Mai 2010
1.764
63
48
35
127.0.0.1 ;)
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.
 
  • Like
Wertungen: Janiiix3

Janiiix3

Aktives Mitglied
28 Sep 2013
1.293
10
38
Hannover
Sprachen
C, C#
@TommyB genau so sollte das aussehen. Das muss ich jetzt irgendwie auf den Controller übertragen bekommen, sprich in C umsetzen.
 

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3.143
58
48
Hennigsdorf
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.
 
Zuletzt bearbeitet:

Janiiix3

Aktives Mitglied
28 Sep 2013
1.293
10
38
Hannover
Sprachen
C, C#
Wenn Du das ganze in einer Schleife mit inkrementierenden/dekrementierenden x durchführst, scrollt die Darstellung.
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...
 
Zuletzt bearbeitet:

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3.143
58
48
Hennigsdorf
Sprachen
BascomAVR, Assembler
Wenn ich das so machen würde, würde ich doch in einen Bereich kommen der für mein "Array" nicht mehr reserviert ist
Genau deswegen mußt Du Dich...
noch um die Leerzeichen kümmern [muß] (immer dann, wenn die Summe kleiner null oder Größer als die Arraylänge wird)
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.
 

Janiiix3

Aktives Mitglied
28 Sep 2013
1.293
10
38
Hannover
Sprachen
C, 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);
        } 
    }
}
 

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3.143
58
48
Hennigsdorf
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?
 
  • Like
Wertungen: TommyB

Janiiix3

Aktives Mitglied
28 Sep 2013
1.293
10
38
Hannover
Sprachen
C, C#
Die erste For-Schleife endet falsch.
Und das delay in Zeile 39 ist auch schlecht platziert, oder?
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.
 

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3.143
58
48
Hennigsdorf
Sprachen
BascomAVR, Assembler
Was endet falsch?
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

natürlich noch ungünstig ist, ist die "while(1)"
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.
 

TommyB

Premium Benutzer
17 Mai 2010
1.764
63
48
35
127.0.0.1 ;)
Sprachen
Assembler, LunaAVR, VB.Net, Python, C#
Die erste For-Schleife endet falsch.
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

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)