Forum: Mikrocontroller und Digitale Elektronik 7Segment-Anzeige im Multiplexbetrieb - Problem: "Mitleuchten" von anderen Segmenten


von Ersan (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute!

Ich habe ein kleines Problemchen.

Im angehängten Bild seht ihr meine Schaltung. Das selbst erstellte 
Bauteil ist eine 4x 7-Segment-Anzeige, welche gemultiplext wird. Dazu 
kommen noch zwei LEDs und zwei Ausgänge. Die Ausgänge sind egal. Problem 
habe ich hauptsächlich mit den LEDs.

Die Anzeige und die LEDs werden 1/6 gemultiplext. 1/6, weil die Anzeige 
vier Stellen hat und dazu noch extra Punkte, welche z.B. ein ° 
darstellen können. Die Anzeige hat also insgesamt 5 Anoden, dazu noch 
die Anoden der LEDs.

Also schalte ich nacheinander durch: Stelle 1, 2, 3, 4, Punkte, LEDs.

Das Problem ist jetzt, dass die LEDs leicht mitzuleuchten scheinen. Das 
tun sie aber nur, wenn eben auch das entsprechende Segment, mit denen 
sie sich die Kathode teilen, an ist. Zeitgleich sind die Anoden aber 
nicht an! Es scheint vielmehr so, als wenn das umschalten der Anoden und 
Kathoden nicht zeitgleich erfolgt.

Vermutung: Segment (Kathode Stelle und LED) war bei Stelle an, jetzt 
wird auf LED umgeschaltet und die Anode der LED ist schon an, während 
die Kathode noch nicht vollständig umgeschaltet ist. Oder andersherum: 
Kathoden sind schon umgeschaltet, aber der Transistor schaltet nicht 
schnell genug aus.

Ähnlich ist es auch mit den Punkten, da aber nicht so stark.


Weiß jemand, ob es daran liegen könnte?

von Joe (Gast)


Lesenswert?

Alles mit einem Oszi prüfen.

Um ein Ausschalten der Transistoren sicher zu stellen noch zusätzlich 
eine Widerstand (10k) von den Basen gegen 5V einbauen.

Joe

von Karl H. (kbuchegg)


Lesenswert?

Ersan schrieb:

> Das Problem ist jetzt, dass die LEDs leicht mitzuleuchten scheinen. Das
> tun sie aber nur, wenn eben auch das entsprechende Segment, mit denen
> sie sich die Kathode teilen, an ist. Zeitgleich sind die Anoden aber
> nicht an! Es scheint vielmehr so, als wenn das umschalten der Anoden und
> Kathoden nicht zeitgleich erfolgt.

Das wird auch nie zeitgleich erfolgen.
Der Trick besteht darin, dass du im Multiplexcode als allererstes erst 
mal eine Anzeigestelle dunkel schaltest, in dem du alle 
Anodentransistoren sperrst.
Danach tust du alles was du brauchst um das Muster für das nächste 
Segment zu bestimmen und an die Kathoden auszugeben.
Und erst dann aktivierst du diese Stelle durch einschalten des richtigen 
Anoden Transistors.

> Weiß jemand, ob es daran liegen könnte?

Es liegt in deiner Programmierung. Es ist ein reines 
Reihenfolgenproblem, in welcher Reihenfolge du welche Aktionen machst 
und welche Aktionen du vermeintlich glaubtest einsparen zu können.

von Ersan (Gast)


Angehängte Dateien:

Lesenswert?

Joe schrieb:
> Alles mit einem Oszi prüfen.

Jo, hab ich gerade. Das Resultat im Anhang. Woran liegt das? Wieso geht 
der PNP so langsam aus?

von Ersan (Gast)


Lesenswert?

Aso, sorry. Oben ist das Signal an der Basis und darunter das am 
Kollektor.

von Peter D. (peda)


Lesenswert?

Ersan schrieb:
> Wieso geht
> der PNP so langsam aus?

Miller-Kapazität.

Nimm für T1..6 NPNs in Kollektorschaltung.
R4 .. 9 entfallen dann.

Peter

von Ersan (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Der Trick besteht darin, dass du im Multiplexcode als allererstes erst
> mal eine Anzeigestelle dunkel schaltest, in dem du alle
> Anodentransistoren sperrst.

OK, das kann ich natürlich machen. Heißt bei mir aber, dass ich extra 
nochmal 16 Bit reintakten muss, nur um die Anzeigen dunkel zu schalten. 
Sollte ich dass dann stets vor dem neuen Ausgeben der Daten machen? Also 
quasi stets 32 bit hinschicken?

Karl Heinz Buchegger schrieb:
> Es liegt in deiner Programmierung.

Das wäre natürlich prima, wenn es dadurch zu beheben ist. Ohne jetzt 
längere Dunkelphasen erzeugen zu müssen. Wenn ich beispielsweise immer 
eine Dunkelphase mit einbauen würde, dann würde sich die "Ein"-Zeit ja 
noch halbieren. Das ist ja auch nicht Sinn der Sache.

Also immer 32 bit senden scheint mir da sinnvoller. Die Anoden kann ich 
so ja nicht abschalten.

von Joe (Gast)


Lesenswert?

Die Transistoren schalten zu langsam ab, das ist richtig.

Probiere doch mal den Spannungsteiler mit 10k gegen +5V. Das reduziert 
auch die verbleibende Ladung auf der Basis und führt zu einem 
schnelleren Abschalten.

Joe

von Karl H. (kbuchegg)


Lesenswert?

Ersan schrieb:

> OK, das kann ich natürlich machen. Heißt bei mir aber, dass ich extra
> nochmal 16 Bit reintakten muss, nur um die Anzeigen dunkel zu schalten.
> Sollte ich dass dann stets vor dem neuen Ausgeben der Daten machen? Also
> quasi stets 32 bit hinschicken?

Darauf läufts bei deinem Hardwrae aufbau hinaus.


>> Es liegt in deiner Programmierung.
>
> Das wäre natürlich prima, wenn es dadurch zu beheben ist.

Da habe ich jetzt allerdings dein Oszi Bild noch nicht gesehen. Die 
fallenden Flanken sind in der Tat sehr lang.

von Ersan (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Nimm für T1..6 NPNs in Kollektorschaltung.

OK, einen Basiswiderstand brauche ich dann nicht? Stellt der Strom 
dadurch dann automatisch ein? Dann hätte ich ca. 4,3V am Emitter 
anliegen, richtig? Ist der Basisstrom dann automatisch genau so hoch, 
wie der Strom im Kollektor-Emitter-Zweig / Verstärkungsfaktor?

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Da habe ich jetzt allerdings dein Oszi Bild noch nicht gesehen. Die
> fallenden Flanken sind in der Tat sehr lang.

Für das Tutorial hab ich BC328 eingesetzt mit 1k Basiswiderstand. Selbst 
bei Full-Speed Multiplexen gab es da kein Geisterleuchten.
AVR-Tutorial: 7-Segment-Anzeige

von Ersan (Gast)


Lesenswert?

Joe schrieb:
> Probiere doch mal den Spannungsteiler mit 10k gegen +5V.

Das macht exakt 0 Unterschied.

von Ersan (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> BC328 eingesetzt mit 1k Basiswiderstand

Selbst mit 1k kein Unterschied

von Ersan (Gast)


Lesenswert?

So, also ich werde jetzt 32Bit senden. Neues Problem...was ist an meinem 
Quelltext falsch?
1
void sr_bitbang_data_out( void )
2
{
3
  uint8_t  bit_counter;
4
  uint8_t  mode_counter = 0;
5
  uint16_t output_data;
6
7
  do
8
  {
9
    if( mode_counter == 0 )
10
    {
11
      output_data = ( sr_control.next_display_data | ANODE_MATRIX );
12
    }
13
    else
14
    {
15
      output_data = sr_control.next_display_data;
16
    }
17
18
    for( bit_counter = 0; bit_counter < 16; bit_counter++ )
19
    {
20
      if( output_data & 0x8000 )
21
      {
22
        SHIFT_REG_DATA_PORT |= SHIFT_REG_DATA_PIN;
23
      }
24
      else
25
      {
26
        SHIFT_REG_DATA_PORT &= ~SHIFT_REG_DATA_PIN;
27
      }
28
29
      SHIFT_REG_CLOCK_PORT |=  SHIFT_REG_CLOCK_PIN;
30
      SHIFT_REG_CLOCK_PORT &= ~SHIFT_REG_CLOCK_PIN;
31
32
      output_data <<= 1;
33
    }
34
35
    SHIFT_REG_LATCH_PORT |=  SHIFT_REG_LATCH_PIN;
36
    SHIFT_REG_LATCH_PORT &= ~SHIFT_REG_LATCH_PIN;
37
38
    mode_counter++;
39
  } while( mode_counter < 2 );
40
}

Ich wollte mit mode_counter == 0 erstmal alle Anoden im SR ausschalten 
und dann im zweiten Druchgang, wo mode_counter dann 1 ist, die richtigen 
Daten.

Aber der Compiler geht zweimal in den else-Zweig bei 
mode_counter-Abfrage. Compiler ist CCS.

von Ersan (Gast)


Lesenswert?

An dieser Stelle
1
output_data = ( sr_control.next_display_data | ANODE_MATRIX );

funktioniert auch RUN TO LINE nicht

von Karl H. (kbuchegg)


Lesenswert?

Ersan schrieb:

> Aber der Compiler geht zweimal in den else-Zweig bei
> mode_counter-Abfrage. Compiler ist CCS.

Da wird dir wohl der Optimizer einen Streich gespielt haben und die 
beiden Zweige weitgehend zusammengezogen haben. Sind ja auch weitgehed 
gleich, lediglich im einen Fall wird noch ANODE_MATRIX eingeodert.

von Peter D. (peda)


Lesenswert?

Ersan schrieb:
> So, also ich werde jetzt 32Bit senden.

Wäre bei Kollektorschaltung nicht nötig, die ist fix genug auch ohne 
Pause. Da kannst Du Segmente und Digit gleichzeitig ändern.


Peter

von Karl H. (kbuchegg)


Lesenswert?

Im übrigen hätte ich das gar nicht so gemacht
1
void sr_bitbang( uint16_t output_data )
2
{
3
  uint8_t  bit_counter;
4
5
  for( bit_counter = 0; bit_counter < 16; bit_counter++ )
6
  {
7
    if( output_data & 0x8000 )
8
    {
9
      SHIFT_REG_DATA_PORT |= SHIFT_REG_DATA_PIN;
10
    }
11
    else
12
    {
13
      SHIFT_REG_DATA_PORT &= ~SHIFT_REG_DATA_PIN;
14
    }
15
16
    SHIFT_REG_CLOCK_PORT |=  SHIFT_REG_CLOCK_PIN;
17
    SHIFT_REG_CLOCK_PORT &= ~SHIFT_REG_CLOCK_PIN;
18
19
    output_data <<= 1;
20
  }
21
22
  SHIFT_REG_LATCH_PORT |=  SHIFT_REG_LATCH_PIN;
23
  SHIFT_REG_LATCH_PORT &= ~SHIFT_REG_LATCH_PIN;
24
}
25
26
void sr_bitbang_data_out( void )
27
{
28
  sr_bitbang( sr_control.next_display_data | ANODE_MATRIX );
29
  sr_bitbang( sr_control.next_display_data );
30
}


Aber hör auf Peter. Der hat von Hardware mehr Ahnung als ich.

von Ersan (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Da wird dir wohl der Optimizer einen Streich gespielt haben und die
> beiden Zweige weitgehend zusammengezogen haben.

Ok, hab grad mal die Optimierungen ausgeschaltet, dann geht er rein.

Karl Heinz Buchegger schrieb:
> Sind ja auch weitgehed
> gleich, lediglich im einen Fall wird noch ANODE_MATRIX eingeodert

Aber dann sind sie doch nicht gleich. Wenn der sowas wegoptimiert, dann 
funktioniert doch mein Programm nicht mehr??!!

von Karl H. (kbuchegg)


Lesenswert?

Ersan schrieb:

> Aber dann sind sie doch nicht gleich. Wenn der sowas wegoptimiert, dann
> funktioniert doch mein Programm nicht mehr??!!


Der optimiert es ja nicht 'weg'!

Der optimiert es nur so, dass der entstehende Code eben keine 1:1 
Entsprechung mehr mit deinem C-Code hat. Funktional kommt dasselbe raus. 
Heisst: Dein Programm macht schon noch das, was du hingeschrieben hast. 
Nur macht es das eben ein wenig anders (schneller) als so wie du das 
hingeschrieben hast. Sonst bräuchte man ja keinen Optimizer, wenn dann 
sowieso wieder dasselbe rauskommen soll, wie du das hingeschrieben hast.

von Ersan (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Im übrigen hätte ich das gar nicht so gemacht

OK, das sieht natürlich besser aus.

Peter Dannegger schrieb:
> Wäre bei Kollektorschaltung nicht nötig, die ist fix genug auch ohne
> Pause

Ja, dann muss ich wohl umbauen...habe es schon gelötet. Trotzdem werde 
ich jetzt erstmal das Resultat der Dunkelzeit abwarten...

von Ersan (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Nur macht es das eben ein wenig anders (schneller) als so wie du das
> hingeschrieben hast.

Also kann ich das dann nur nicht mehr debuggen, aber es bleibt von der 
Funktion her gleich?

von Ersan (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Aber hör auf Peter. Der hat von Hardware mehr Ahnung als ich.

Ja, ich nehme mir das auf jeden Fall auch zu Herzen. Kann mir denn dann 
nochmal jemand das hier erklären:

Ersan schrieb:
> OK, einen Basiswiderstand brauche ich dann nicht? Stellt der Strom
> dadurch dann automatisch ein? Dann hätte ich ca. 4,3V am Emitter
> anliegen, richtig? Ist der Basisstrom dann automatisch genau so hoch,
> wie der Strom im Kollektor-Emitter-Zweig / Verstärkungsfaktor?

von Peter D. (peda)


Lesenswert?

Ersan schrieb:
> Stellt der Strom
>> dadurch dann automatisch ein? Dann hätte ich ca. 4,3V am Emitter
>> anliegen, richtig? Ist der Basisstrom dann automatisch genau so hoch,
>> wie der Strom im Kollektor-Emitter-Zweig / Verstärkungsfaktor?

3 * Ja.

Peter

von Ersan (Gast)


Lesenswert?

Peter Dannegger schrieb:
> 3 * Ja.

Vielen Dank!

Also das Ergebnis: Es leuchtet trotzdem noch nach, auch wenn ich erst 
alles einmal dunkel schalte. Jetzt kommen die NPN-Transistoren ;-) Mal 
sehen

von Peter D. (peda)


Lesenswert?

Welche Multiplexfrequenz hast Du?

Bei 6-fach Mux nimmt man etwa 100Hz * 6 = 600Hz, d.h. Timerinterrupt 
1,7ms.


Peter

von Ersan (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Welche Multiplexfrequenz hast Du?

Ich muss die Multiplexfrequenz von einem Timer ableiten, der mir eine 
Hardware-PWM macht. Die ist wichtiger, als die Anzeige.  Also kann ich 
dafür nur den Overflow-Interrupt nehmen. Daraus resultiert eine Frequenz 
pro Stelle von 54Hz.

von Klaus 2. (klaus2m5)


Lesenswert?

Ersan schrieb:
> Daraus resultiert eine Frequenz
> pro Stelle von 54Hz.

Dein Scope-Bild sagt aber 440µs, also etwas über 2 kHz.

von Ersan (Gast)


Lesenswert?

Klaus 2m5 schrieb:
> Dein Scope-Bild sagt aber 440µs, also etwas über 2 kHz.

Das stimmt. Aber da ist auch kein Programm am laufen, sondern in der 
main wird nur ständig die Anzeige aktualisiert. Aber es macht auch 
keinen Unterschied, ob es (wie jetzt gerade) mit Timer läuft, oder eben 
nur in der main. Das ungewünschte Leuchten bleibt.

Die LEDs glimmen nicht, wenn das Segment bei der vorherigen Stelle nicht 
an gewesen ist. Es liegt also auf jeden Fall daran. Nur es ändert leider 
auch nichts, wenn ich beispielsweise mehrere male hintereinander alles 
lösche um die Zeit zu verzögern.

von Ersan (Gast)


Lesenswert?

So...also mit NPN leuchtet da nichts mehr nach

von Ersan (Gast)


Lesenswert?

Hat jemand von euch vielleicht die Nerven, mir kurz zu erklären, warum 
das so ist? Also weshalb NPN und PNP sich so anders verhalten?

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Der pnp geht in Emitterschaltung in die Sättigung, npn in 
Kollektorschaltung nicht. Daher ist er viel schneller wieder aus.

von Klaus 2. (klaus2m5)


Lesenswert?

Ersan schrieb:
> Hat jemand von euch vielleicht die Nerven, mir kurz zu erklären, warum
> das so ist? Also weshalb NPN und PNP sich so anders verhalten?

Das liegt vielleicht daran, dass in Kollektorschaltung der Transistor 
nicht in die Sättigung kommt, in Emitterschaltung aber schon.

Wenn das Scopebild also nicht den "echten" Betrieb darstellt, hat es 
auch keinerlei Aussagekraft. Wahrscheinlich war auch keins der Segmente 
von der anderen Seite angesteuert? Wie soll sich da die parasitäre 
Kapazität entladen?

Wer misst, misst Mist, so auch hier.

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.