• Willkommen im Geoclub - dem größten deutschsprachigen Geocaching-Forum. Registriere dich kostenlos, um alle Inhalte zu sehen und neue Beiträge zu erstellen.

Problem mit der Helligkeit bei 7Seg multiplexing.

peter51d

Geocacher
Ich habe da mal eine Frage an unsere Atmel Experten.

Gibt es auf dem Mega8 Port Kombinationen, die besonders "gut" zusammen arbeiten?

Hintergrund ist folgendes "Problem":
Ich möchte zwei 7 Seg Anzeigen mit einem Mega 8 ansteuern. Dazu multiplexe ich so wohl die Anoden und die gemeinsame Kathode der Anzeigen.

Die Anoden beider Anzeigen sind am PortB angeschlossen. Die Kathode der einen Anzeige hängt an PortD.6
die andere an PortD.7

Es gibt pro Anzeige einen Wiederstand der an der Kathode angeschlossen ist.

Programmablauf :
Kathode Anzeige eins auf GND schalte, nach einander die einzelnen Ports von B in der entsprechenden Reihenfolge auf eins und wieder auf null setzen.
Dann Kathode Anzeige eins auf eins und Kathode Anzeige zwei auf GND. Dann wieder die Anoden einzelnd ansteuern.
Und wieder von vorne.

Im Prinzip klappt das so weit.

Nur irgendwie habe ich bei der Anzeige, deren Kathode über PortD.6 geschaltet wird immer ein Segment, das deutlich heller Leuchtet.

Die Anzeigen kann ich ausschliessen.
Beim Tauschen der Anzeigen wander der Fehler nicht mit.

Der Mega selber dürfte es auch nicht sein.
Es sei denn, drei verschieden haben den gleichen Fehler.

Der Fehler wandert aber mit, wenn ich die Ports D.6 und D.7 Tausche.

Es scheind eine bestimmte Port Kombination zu sein.
Es betrifft bei Zahlen die eine oberen Querbalken haben die Kombination. D.6/B.1 und bei Zahlen ohne oberen Querbalken die Kombination D.6/B.2 .

Anbei noch der Code.
Bitte nicht lästern, ist das erste mal das ich mich mit Multiplexing beschäftige.

Code:
'--------------------------------------------------------------
'            mega8.bas
'    7 Segment mit gemeinsamer Kathode Multiplex test
'--------------------------------------------------------------
$regfile = "m8def.dat"
$crystal = 1000000
'the internal oscillator of 1 Mhz was choosen in the fusebits

Config Portb = Output                                       'Anoden 7 Segmentanzeige
Config Portd = Output                                       'Kathode 7 Segmentanzeige
Dim A As Word


Do
   For A = 1 To 20000                                       'dauer der Anzeige
   Portb = &B00000000                                       'anzeige dunkel steuern
   Portd = &B11111111
   Portd = &B01111111                                       '7 Segmentmodul auswählen
   Gosub Eins                                               'Sprunganweisung für Anodenansteuerung
   Portb = &B00000000
   Portd = &B11111111
   Portd = &B10111111
   Gosub Null
   Next A
   Portb = &B00000000
   Waitms 500

   For A = 1 To 20000                                       'zweite Zahl
   Portb = &B00000000
   Portd = &B11111111
   Portd = &B01111111
   Gosub Drei
   Portb = &B00000000
   Portd = &B11111111
   Portd = &B10111111
   Gosub Zwei
   Next A
   Portb = &B00000000
   Waitms 500

   For A = 1 To 20000
   Portb = &B00000000                                       'dritte Zahl
   Portd = &B11111111
   Portd = &B01111111
   Gosub Fuenf
   Portb = &B00000000
   Portd = &B11111111
   Portd = &B10111111
   Gosub Vier
   Next A
   Portb = &B00000000
   Waitms 500

   For A = 1 To 20000
   Portb = &B00000000                                       'vierte Zahl
   Portd = &B11111111
   Portd = &B01111111
   Gosub Sieben
   Portb = &B00000000
   Portd = &B11111111
   Portd = &B10111111
   Gosub Sechs
   Next A
   Portb = &B00000000
   Waitms 500

   For A = 1 To 20000                                       'fünfte Zahl
   Portb = &B00000000
   Portd = &B11111111
   Portd = &B01111111
   Gosub Neun
   Portb = &B00000000
   Portd = &B11111111
   Portd = &B10111111
   Gosub Acht
   Next A
   Portb = &B00000000
   Waitms 500

   'Portb = &B00000000                                       'sechste Zahl
   'Portd = &B11111111
   'Portd = &B01111111
   'Gosub Drei
   'Portb = &B00000000
   'Portd = &B11111111
   'Portd = &B10111111
   'Gosub Vier
   'Next A
   'Portb = &B00000000
   'Waitms 500

   'For A = 1 To 20000                                       'siebte Zahl
   'Portb = &B00000000
   'Portd = &B11111111
   'Portd = &B01111111
   'Gosub Sechs
   'Portb = &B00000000
   'Portd = &B11111111
   'Portd = &B10111111
   'Gosub Sieben
   'Next A
   'Portb = &B00000000
   'Waitms 500

   'For A = 1 To 20000                                       'achte zahl
   'Portb = &B00000000
   'Portd = &B11111111
   'Portd = &B01111111
   'Gosub Eins
   'Portb = &B00000000
   'Portd = &B11111111
   'Portd = &B10111111
   'Gosub Fuenf
   'Next A
   'Portb = &B00000000
   'Waitms 500

Loop
End

Null:

   Portb = &B01000000
   Portb = &B00100000
   Portb = &B00010000
   Portb = &B00001000
   Portb = &B00000100
   Portb = &B00000010
   Return

Eins:

   Portb = &B00001000
   Portb = &B00000100
   Return
Zwei:

   Portb = &B10000000
   Portb = &B00100000
   Portb = &B00010000
   Portb = &B00000100
   Portb = &B00000010
   Return

Drei:

   Portb = &B10000000
   Portb = &B00010000
   Portb = &B00001000
   Portb = &B00000100
   Portb = &B00000010
   Return

Vier:

   Portb = &B10000000
   Portb = &B01000000
   Portb = &B00001000
   Portb = &B00000100
   Return

Fuenf:

   Portb = &B10000000
   Portb = &B01000000
   Portb = &B00010000
   Portb = &B00001000
   Portb = &B00000010
   Return

Sechs:

   Portb = &B10000000
   Portb = &B01000000
   Portb = &B00100000
   Portb = &B00010000
   Portb = &B00001000
   Portb = &B00000010
   Return

Sieben:

   Portb = &B00001000
   Portb = &B00000100
   Portb = &B00000010
   Return

Acht:

   Portb = &B00001000
   Portb = &B01000000
   Portb = &B00100000
   Portb = &B00010000
   Portb = &B10000000
   Portb = &B00000100
   Portb = &B00000010
   Return

Neun:

   Portb = &B10000000
   Portb = &B01000000
   Portb = &B00010000
   Portb = &B00001000
   Portb = &B00000100
   Portb = &B00000010
   Return

Ach so, die Anzeigen sind: Kingbright SC39-11SRWA, Kathodenwiederstand habe ich z.Z.470Ohm drin und das ganze wird von einem Labornetzteil mit 4V gespeist.

Würde mich freuen, wenn hier jemand eine Erklärung dafür hätte.
 

chrysophylax

Geomaster
Oh, spannender Realisierungsansatz... "Vom Prinzip her verstanden und richtig umgesetzt, aber über ein paar unangenehme Details der Realität gestolpert".

Mulitplexen funktioniert nur dann, wenn alle "Zeitschlitze", in denen ein Bitmuster auf der Anzeige steht, EXAKT gleich lang sind. Im Prinzip von so exakt, dass es durchaus sinnvoll ist, einzelne Prozessortakte auszuzählen und notfalls mit NOPs auszutarieren, wenn bestimmte Teile der MUXerei unsymmetrisch sind oder es Schritte geben kann, die eine andere Länge als andere haben.

In deinem Fall heißt das, dass jede "Bit-Kombi" (Ausgewählte Kathode über Port D, einzeln ausgewählte Anode über Port B) genauso lang anstehen muss wie jede andere Bit-Kombi, sonst erscheinen Kombis, die länger anstehen heller als Kombis, die dunkler anstehen.

Das "Einfache Problem": Je nachdem, wie viele Segmente in deinen Ziffern leuchten, hast du unterschiedliche Anzahlen von "Leuchtschritten" pro angezeigter Ziffer. Paradebeispiel: Die Ziffer "1" braucht nur 2 Schritte, die Ziffer "8" braucht 7 Schritte. Im Prinzip müsstest du die "unbenutzten Segmente" mit Portb=&b00000000 auffüllen, damit die Zeitdauer, die dein Programm zu Anzeigen einer 1 braucht genauso lang ist wie die Zeitdauer, die es zum Anzeigen einer 8 braucht.
Ich vermute mal ins Blaue, dass im Moment Einsen auf deiner Anzeige immer noch heller erscheinen als Achter - auch wenns nicht viel ist.

Das "komplizierte Problem": Wenn du innerhalb einer anzuzeigenden Ziffer auf das nächste Segment wechselst, geht das relativ schnell. ("Portb = &bDingens", direkt hintendran "Portb=&bBummens"). Wenn du allerdings mit der "Anzeige" durch bist, dann bleibt das letzte genutzte Segment immer erheblich länger stehen als alle anderen davor, weil der Prozessor dann erstaunlich lange damit beschäftigt ist Befehle wie "Return" und "Next A" auszuführen, die zwar Rechenzeit brauchen, während derer Ausführung sich aber nichts an den Ausgangspörtern ändert und die Anzeige daher im letzten ausgegebenen Bit-Zustand stehenbleibt.

Und oh Wunder, das passt exakt zu deiner Fehlerbeschreibung "B1 oder B2" - die jeweils letzten Befehle, die du auf Port B rauswirfst, sind entweder
Code:
 Portb = &B00000100
oder
Code:
  Portb = &B00000010
je nach anzuzeigender Ziffer. B2 an oder B1 an.

An diesem Problem kannst du "umsetzungsbeding" auch nur relativ wenig ändern. Ein Würgaround wäre, JEDE "Zeige-Ziffer-An"-Unterroutine auf exakt 8 Portbefehle aufzubohren: Benutzte Segmente auf 1, unbenutzte auf 0, und als Letztes auch noch mal 0.
Dann erscheinen alle deine Ziffern gleich hell und auch alle Segmente haben exakt die gleiche Einschaltdauer. Nachteil: Du verschenkst "mögliche nutzbare Helligkeit", weil während der Zeit, in der dein Programm mit "Mathematik" und "Hin- und Zurückspringen" beschäftigt ist, gar kein Segment leuchtet.

Die einzige alternative Umsetzung wäre der klassische Ansatz, Multiplexen grundsätzlich nur in einem Timer-Interrupt zu realisieren. Ganze ehrlich: Das ist der Einzige, der sauber funktioniert. Ob und wie man in Basis-Koma einen Timer-Interrupt hinwürgt hab ich allerdings keine Ahnung, aber ich vermute mal, das artet in erheblichen Aufwand aus.

Um das Ganze abzuschließen: Ich meine "spannend" durchaus im positiven Sinne, weil als Mensch der sich regelmässig mit sowas rumschlägt und irgendwann mal gelernt hat, dass und warum Standard-Lösungsansätze so gut funktionieren kommt man nie auf so Ideen. Und nur, weil solche Ideen nicht perfekt funktionieren (sondern eben nur funktionieren) heißt das nicht, dass man nicht zumindest mal ein wenig Zeit und sei es zum eigenen Erkenntnisgewinn damit verbringen sollte - lernen kann man immer noch was. Und Andererseits: Vieles, was bei professioneller Anwendung zum Hochrollen von Fußnägeln führt, kann für Hobbyisten durchaus ausreichen.

Wenn es eins gibt, was ich von der Atmel-Welt gelernt habe, so ist es zu erkennen und zu akzeptieren, dass Lösungen, die software- oder elektrotechnisch noch so hingewürgt erscheinen häufig durchaus sowohl Menschen zufriedenstellen als auch irgendwie ihre Aufgabe erfüllen - und mehr ist nicht gefordert. Da kann etwas noch so gebastelt, gewürgt, vorbei an allen Datenblättern und technischen Spezifikationen sein: Wenn es halbwegs die Anforderungen seines Erstellers erfüllt, dann ist es ok. Eleganz und formalelektronische Korrektheit ist bei Atmel-Hobby-Fricklern nur Kür und keine Pflicht.
Das zu erkennen und akzeptieren und tolerieren zu lernen hat bei mir ziemlich lange gedauert ;)

chrysophylax.
 
OP
peter51d

peter51d

Geocacher
Danke für die Antwort chrysophylax.

Ich habe heute morgen noch ein wenig probiert und habe dabei auch gemerkt, das es ein Software Problem sein muss.
Ist halt mein erster Versuch.

Du hast schon recht, wenn man es richtig machen will, arbeitet man bei solchen sachen mit Timer Interrupts.
Da stecke ich aber auch nicht tiefer drin, erst recht nicht in diesem Fall.
Ist halt ein AnfängerEinfachMalAusprobierenMalSehenWasPassiert Programm.

Aber das Problem wird wohl, wie du schreibst in den Rücksprungzeiten liegen.
Werden erst mal probieren, die Anzeige nach dem letzem Segment dunkel zu steuern. mal sehen was passiert.

Einen HelligkeitsUnterschied zwischen z.B. 8 und 1 kann ich im Moment allerdings nicht sehen.

Ich sag noch mal bescheid, was dabei raus gekommen ist.
 
OP
peter51d

peter51d

Geocacher
Danke für deine Antwort Kappler.

Die Seite kenne ich auch.

Das Problem ist nicht der Timer als solcher.
habe schon mit Timern gearbeitet, zur zyklischen Messwerterfassung.

Nur beim Multiplexen ist es schon etwas komplexer mit dem Timer zu arbeiten, als nur mal schnell in der ISR einen Messgeber ab zu fragen.

Deshalb habe ich erst mal versucht, one Timer zu arbeiten um zu sehen, wie es generell geht.

Ich werde nachher noch mal was probieren, und wenn das auch nicht geht, werde ich wohl um Timergesteuertes Multiplexen nicht hin kommen.
 
OP
peter51d

peter51d

Geocacher
So, habe jetzt mal die Anzeige nach dem die Segmente der Ziffer durch sind dunkel gesteuert.
Damit waren alle Segmente schon mal gleichhell. Schon erstaunlich, was ein paar Takte da ausmachen. Hätte ich so nicht erwartet.
Um das ganze noch etwas heller zu bekommen, die Kathodenwiederstände von 470Ohm auf 150Ohm verkleinert. Ist Strommässig immer noch voll im grünen Bereich, sowohl für die Anzeige wie auch für den Atmel.
Und zusätzlich die Leuchtdauer der einzelnen Segmente erhöht. Einfach, schmutzig und wie chrysophylax sagen würde "Hingewürgt" ;) mit 100µs Wartezeit noch jedem Segment.

Hier noch mal der Code.
Da können unsere Profis hier sich noch etwas gruseln, ist ja Halloween. :hexenflug:

Code:
'--------------------------------------------------------------
'            mega8.bas
'    7 Segment mit gemeinsamer Kathode Multiplex test

Danke für eure Hilfe. :p 
'--------------------------------------------------------------
$regfile = "m8def.dat"
$crystal = 1000000
'the internal oscillator of 1 Mhz was choosen in the fusebits

Config Portb = Output                                       'Anoden 7 Segmentanzeige
Config Portc = Output                                       'Kathode 7 Segmentanzeige
Dim A As Word


Do
   For A = 1 To 2000                                        'dauer der Anzeige
   Portb = &B00000000                                       'anzeige dunkel steuern
   Portc = &B11111111
   Portc = &B11101111                                       '7 Segmentmodul auswählen
   Gosub Eins                                               'Sprunganweisung für Anodenansteuerung
   Portb = &B00000000
   Portc = &B11111111
   Portc = &B11011111
   Gosub Null
   Next A
   Portb = &B00000000
   Waitms 500

   For A = 1 To 2000                                        'zweite Zahl
   Portb = &B00000000
   Portc = &B11111111
   Portc = &B11101111
   Gosub Drei
   Portb = &B00000000
   Portc = &B11111111
   Portc = &B11011111
   Gosub Zwei
   Next A
   Portb = &B00000000
   Waitms 500

   For A = 1 To 2000
   Portb = &B00000000                                       'dritte Zahl
   Portc = &B11111111
   Portc = &B11101111
   Gosub Fuenf
   Portb = &B00000000
   Portc = &B11111111
   Portc = &B11011111
   Gosub Vier
   Next A
   Portb = &B00000000
   Waitms 500

   For A = 1 To 2000
   Portb = &B00000000                                       'vierte Zahl
   Portc = &B11111111
   Portc = &B11101111
   Gosub Sieben
   Portb = &B00000000
   Portc = &B11111111
   Portc = &B11011111
   Gosub Sechs
   Next A
   Portb = &B00000000
   Waitms 500

   For A = 1 To 2000                                        'fünfte Zahl
   Portb = &B00000000
   Portc = &B11111111
   Portc = &B11101111
   Gosub Neun
   Portb = &B00000000
   Portc = &B11111111
   Portc = &B11011111
   Gosub Acht
   Next A
   Portb = &B00000000
   Waitms 500

   For A = 1 To 2000
   Portb = &B00000000                                       'sechste Zahl
   Portc = &B11111111
   Portc = &B11101111
   Gosub Acht
   Portb = &B00000000
   Portc = &B11111111
   Portc = &B11011111
   Gosub Acht
   Next A
   Portb = &B00000000
   Waitms 500

   For A = 1 To 2000                                        'siebte Zahl
   Portb = &B00000000
   Portc = &B11111111
   Portc = &B11101111
   Gosub Acht
   Portb = &B00000000
   Portc = &B11111111
   Portc = &B11011111
   Gosub Eins
   Next A
   Portb = &B00000000
   Waitms 500

   'For A = 1 To 2000                                       'achte zahl
   'Portb = &B00000000
   'Portc = &B11111111
   'Portc = &B11101111
   'Gosub Eins
   'Portb = &B00000000
   'Portc = &B11111111
   'Portc = &B11011111
   'Gosub Fuenf
   'Next A
   'Portb = &B00000000
   'Waitms 500

Loop
End

Null:

   Portb = &B01000000                                       'ansteuerung der einzelnen Segmente je nach Ziffer
   Waitus 100                                               'Wartezeit mit eingeschaltetem Segment
   Portb = &B00100000
   Waitus 100
   Portb = &B00010000
   Waitus 100
   Portb = &B00001000
   Waitus 100
   Portb = &B00000100
   Waitus 100
   Portb = &B00000010
   Waitus 100
   Portb = &B00000000                                       'anzeige dunkel steuern, damit sie gleichmässig erscheint
   Return

Eins:

   Portb = &B00001000
   Waitus 100
   Portb = &B00000100
   Waitus 100
   Portb = &B00000000
   Return
Zwei:

   Portb = &B10000000
   Waitus 100
   Portb = &B00100000
   Waitus 100
   Portb = &B00010000
   Waitus 100
   Portb = &B00000100
   Waitus 100
   Portb = &B00000010
   Waitus 100
   Portb = &B00000000
   Return

Drei:

   Portb = &B10000000
   Waitus 100
   Portb = &B00010000
   Waitus 100
   Portb = &B00001000
   Waitus 100
   Portb = &B00000100
   Waitus 100
   Portb = &B00000010
   Waitus 100
   Portb = &B00000000
   Return

Vier:

   Portb = &B10000000
   Waitus 100
   Portb = &B01000000
   Waitus 100
   Portb = &B00001000
   Waitus 100
   Portb = &B00000100
   Waitus 100
   Portb = &B00000000
   Return

Fuenf:

   Portb = &B10000000
   Waitus 100
   Portb = &B01000000
   Waitus 100
   Portb = &B00010000
   Waitus 100
   Portb = &B00001000
   Waitus 100
   Portb = &B00000010
   Waitus 100
   Portb = &B00000000
   Return

Sechs:

   Portb = &B10000000
   Waitus 100
   Portb = &B01000000
   Waitus 100
   Portb = &B00100000
   Waitus 100
   Portb = &B00010000
   Waitus 100
   Portb = &B00001000
   Waitus 100
   Portb = &B00000010
   Waitus 100
   Portb = &B00000000
   Return

Sieben:

   Portb = &B00001000
   Waitus 100
   Portb = &B00000100
   Waitus 100
   Portb = &B00000010
   Waitus 100
   Portb = &B00000000
   Return

Acht:

   Portb = &B00001000
   Waitus 100
   Portb = &B01000000
   Waitus 100
   Portb = &B00100000
   Waitus 100
   Portb = &B00010000
   Waitus 100
   Portb = &B10000000
   Waitus 100
   Portb = &B00000100
   Waitus 100
   Portb = &B00000010
   Waitus 100
   Portb = &B00000000
   Return

Neun:

   Portb = &B10000000
   Waitus 100
   Portb = &B01000000
   Waitus 100
   Portb = &B00010000
   Waitus 100
   Portb = &B00001000
   Waitus 100
   Portb = &B00000100
   Waitus 100
   Portb = &B00000010
   Waitus 100
   Portb = &B00000000
   Return

und noch ein kleines Video in DeinerRöhre:7 Segment auf Steckbrett
 
Oben