Forum: Mikrocontroller und Digitale Elektronik Multiplex - einmal mehr


von Electronics'nStuff (Gast)


Lesenswert?

Hallo Zusammen.

Ich wollte mich mal bei euch informieren, wie ihr das so machen würdet:

Ich habe einen Attiny13 in Kombination mit einem CD4067BE 
Schieberegister.
Die Datenleitungen entsprechen der Portbelegung, das heisst:

PB0 (Attiny) auf Input A (Shift Register)
PB1 (Attiny) auf Input B (Shift Register)
PB2 (Attiny) auf Input C (Shift Register)
PB3 (Attiny) auf Input D (Shift Register)

Die Ausgänge des Shiftregisters (16) sind einfach nur LED's.

Nun funktioniert das ganze ganz in Ordnung, wenn ich schreibe PORTB = 
0x01; leuchtet LED 1, bei PORTB = 0x02; LED 2 und so weiter.

Nun, wenn ich mehrere LED's leuchten lassen will, muss ich ja 
abwechselnd

while (irgendwas)
{

PORTB = 0x01;
//irgend ein Delay
PORTB = 0x00;

PORTB = 0x02;
//irgend ein Delay
PORTB = 0x00;
}

Leider habe ich nach längerem rumprobieren keine gescheite Routine 
hingekriegt, gibt es da evtl. Musterlösungen wo man ein wenig abkucken 
könnte?

Gruss & Danke im Voraus

von spess53 (Gast)


Lesenswert?

Hi

>Ich habe einen Attiny13 in Kombination mit einem CD4067BE
>Schieberegister.

Der CD4067 ist ein Multiplexer/Demultiplexer, kein Schieberegister.

MfG Spess

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Electronics'nStuff schrieb:
> Die Datenleitungen entsprechen der Portbelegung, das heisst:
>
> PB0 (Attiny) auf Input A (Shift Register)
> PB1 (Attiny) auf Input B (Shift Register)
> PB2 (Attiny) auf Input C (Shift Register)
> PB3 (Attiny) auf Input D (Shift Register)
>
> Die Ausgänge des Shiftregisters (16) sind einfach nur LED's.
Gibts diese Netzliste als auch Bild (aka. Schaltplan)?

von Karl H. (kbuchegg)


Lesenswert?

Electronics'nStuff schrieb:

> Leider habe ich nach längerem rumprobieren keine gescheite Routine
> hingekriegt,

Das Zauberwort heißt, wie eigentlich in über 70% aller Fälle: Timer

Es ist im Grunde immer das gleiche Prinzip. Wenn irgendwo eine 
Zeitsteuerung im Spiel ist, dann erledigt das die ISR eines Timers.

von Electronics'nStuff (Gast)


Angehängte Dateien:

Lesenswert?

spess53 schrieb:
> Der CD4067 ist ein Multiplexer/Demultiplexer, kein Schieberegister.

Oh, shit mein Fehler. Natürlich, war ja eig. auch die Idee hinter dem 
Bauteil :)

Lothar Miller schrieb:
> Gibts diese Netzliste als auch Bild (aka. Schaltplan)?

Ja, klar. Befindet sich im Anhang.

Gruss

von Karl H. (kbuchegg)


Lesenswert?

Electronics'nStuff schrieb:
> spess53 schrieb:
>> Der CD4067 ist ein Multiplexer/Demultiplexer, kein Schieberegister.
>
> Oh, shit mein Fehler. Natürlich, war ja eig. auch die Idee hinter dem
> Bauteil :)

War eine schlechte Idee.
Mit Schieberegistern wärst du besser gefahren.

von Electronics'nStuff (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Das Zauberwort heißt, wie eigentlich in über 70% aller Fälle: Timer

Ja, aber in die ISR muss auch noch eine Routine, und die würde mich eben 
interessieren wie so was im Besten Fall aussieht. Klar, kriege ich 
irgendwas hin aber das ist bis jetzt immer ein bisschen vermurkst 
rausgekommen und ich hatte jedes Mal das Gefühl, das geht bestimmt 
einfacher.

Gruss

von Electronics'nStuff (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Mit Schieberegistern wärst du besser gefahren.

Hätte ich genommen, wenn ich ein 16-Kanal Schieberegister gefunden 
hätte.
War aus Platz- und Layoutgründen (-> 1Lagig) die bessere Alternative für 
mich.

Aber die Schaltung ist jetzt schon umgesetzt, geroutet und geätzt :) 
Also würde ich gerne mit den Bauteilen arbeiten, die jetzt auf meiner 
kleinen Platine werkeln.

Gruss

von Karl H. (kbuchegg)


Lesenswert?

Electronics'nStuff schrieb:
> Karl Heinz Buchegger schrieb:
>> Das Zauberwort heißt, wie eigentlich in über 70% aller Fälle: Timer
>
> Ja, aber in die ISR muss auch noch eine Routine

In der ISR wird abwechselnd (um bei deinem Beispiel zu bleiben)
0x01 auf den Port ausgegeben und 0x02. Bei jedem ISR Aufruf die jeweils 
andere 'Stelle' (wenn du 2 Stellen hast. Bei zb 4 dann eben nacheinander 
alle 4 durchgehen. Bei jedem Aufruf kommt die jeweils nächste Stelle.)

Das wirst du ja wohl noch hinkriegen :-)
1
uint8_t welche;
2
3
ISR( ... )
4
{
5
  if( welche == 0 )
6
    PORTB = 0x01;
7
  else
8
    PORTB = 0x02;
9
10
  welche = 1 - welche;
11
}

That's it. Das ist schon alles.

So, und jetzt auf und sich mit Timern vertraut machen
FAQ: Timer


Bei dir ist das jetzt natürlich blöd, weil du 16 'Stellen' hast. D.h. 
jede LED (so sie eingeschaltet ist) leuchtet nur 1/16 der Zeit. D.h. das 
wird ziemlich dunkel werden.

von Electronics'nStuff (Gast)


Lesenswert?

Ok, ich sehe ich bin ein wenig zu unpräzise.
Das ganze soll nachher unterschiedlich funktionieren.

Am liebsten hätte ich eine Funktion wie z.b.

light (3, 16)

Wobei die 3 für die Anzahl LED's steht und die 16 für die Zeit (in ms 
z.B.)

Weisst du wie ich es meine?
Danke für den Hinweis mit dem aber ich habe dieses Tutorial schon durch 
sowie erfolgreich eine Uhr gebaut, mit PWM gearbeitet etc.

Einen Interrupt alle 10ms (z.B.) zu erzeugen ist für mich kein Problem 
aber eine gescheite Routine habe ich nicht gefunden bis jetzt.

Gruss

von Electronics'nStuff (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> leuchtet nur 1/16 der Zeit.

Ja, das ist schon ok :) Soll auch eine Low-Current Anwendung werden.

Gruss

von Karl H. (kbuchegg)


Lesenswert?

Electronics'nStuff schrieb:
> Karl Heinz Buchegger schrieb:
>> Mit Schieberegistern wärst du besser gefahren.
>
> Hätte ich genommen, wenn ich ein 16-Kanal Schieberegister gefunden
> hätte.

Das coole an Schieberegistern wie zb einem 595 ist, dass man sie trivial 
kaskadieren kann. Braucht man 16 Pins, dann schaltet man einfach 2 Stück 
8 Bit Schieberegister hintereinander. Softwaremässig ist das immer noch 
ein 16-Bit Schieberegister. Die Software kriegt davon nichts mit, dass 
da eigentlich 2 IC an der Arbeit sind.

AVR-Tutorial
Im Abschnitt über Schieberegister.

> Aber die Schaltung ist jetzt schon umgesetzt, geroutet und geätzt :)
> Also würde ich gerne mit den Bauteilen arbeiten, die jetzt auf meiner
> kleinen Platine werkeln.

Tja. Das Problem wird werden, dass du mit deiner Lösung nicht viel 
Freude haben wirst. Ein 1:16 Multiplex ist schon hart an der Grenze, 
bzw. eigentlich drüber.

von Karl H. (kbuchegg)


Lesenswert?

Electronics'nStuff schrieb:

> Weisst du wie ich es meine?

Nein.
Was soll das ganze überhaupt werden.

von Electronics'nStuff (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Das coole an Schieberegistern wie zb einem 595 ist, dass man sie trivial
> kaskadieren kann.

Ach, das wusste ich nicht.. dachte da steckt mehr Aufwand dahinter.

Danke für den Hinweis auf den Artikel, den werde ich mir als Lesezeichen 
speicher, wenn ich das nächste mal Schieberegister benutze.

Aber trotzdem, das Problem mit dem Platz bleibt, ein 595 ist SO-16, zwei 
davon wären demnach 32 Pins, ich brauche so nur 24.

Gruss

von Electronics'nStuff (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Was soll das ganze überhaupt werden.

Ne kleine Unterbodenbeleuchtung für Gläser.
Es sollen verschiedene Muster einprogrammiert werden, die danach in 
einer Endlosschlaufe vor sich hin leuchten.

Also ich probier mich mal geschickter auszudrücken:

Ich möchte eine Funktion, in die ich eingeben kann led(3) und dann 
leuchtet led 1-3. Wenn ich eingebe led(4) leuchtet led 1-4.

Natürlich soll das Ganze immer gleich hell bleiben, d.h. eine led 
leuchtet immer mit 1/16 der leuchtkraft, unabhängig davon, ob andere 
LED's eigeschaltet wruden.

Gruss

von Karl H. (kbuchegg)


Lesenswert?

Electronics'nStuff schrieb:


> Ich möchte eine Funktion, in die ich eingeben kann led(3) und dann
> leuchtet led 1-3. Wenn ich eingebe led(4) leuchtet led 1-4.
>
> Natürlich soll das Ganze immer gleich hell bleiben, d.h. eine led
> leuchtet immer mit 1/16 der leuchtkraft, unabhängig davon, ob andere
> LED's eigeschaltet wruden.


Wenn ich deine Schaltung studiere, dann geht das gar nicht.
Und zwar deshalb nicht, weil du gar keine Möglichkeit hast, KEINE Led 
leuchten zu lassen. So wird das nichts mit einem Multiplex.

Also: so wird das nichts. Sorry.
Entweder du lebst damit, dass du immer nur 1 LED einschalten kannst, 
oder du baust deine Schaltung um.

(Im einfachsten Fall: auf eine LED verzichten, die immer dann 
'eingeschaltet' wird, wenn im Multiplex eine LED nicht leuchten soll)

von Electronics'nStuff (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> oder du baust deine Schaltung um.

Ich hänge X auf PB5 :)
Der Fall in dem keine LED leuchtet, kommt sowieso nie bis fast nie vor. 
Oder ist zumindest nicht vorgesehen.

Ich will auch nicht das 100ste Schieberegister an den 100ten Attiny mit 
dem 100-fach benutzten Code benutzen (auch wenn sich diese Lösung 
bewährt hat).

Gruss

von Karl H. (kbuchegg)


Lesenswert?

> Ich möchte eine Funktion, in die ich eingeben kann led(3) und
> dann leuchtet led 1-3. Wenn ich eingebe led(4) leuchtet led 1-4.

Ja, das kannst du dann ja immer noch drüber bauen.
Aber erst mal muss der Multiplex laufen. Den brauchst du um mehrere LED 
gleichzeitig leuchten alssen zu können.
Und zwar unabhängig davon, welche LED dann tatsächlich leuchten sollen

> (Im einfachsten Fall: auf eine LED verzichten, die immer dann
> 'eingeschaltet' wird, wenn im Multiplex eine LED nicht leuchten soll)

Ich geh mal davon aus, dass du auf LED-16 verzichtest
1
volatile uint8_t LedOn[15];
2
uint8_t multiplexCnt;
3
4
ISR( ... )
5
{
6
  multiplexCnt++;
7
  if( multiplexCnt == 15 )
8
    multiplexCnt = 0;
9
10
  if( LedOn[multiplexCnt] )
11
    PORTB = multiplexCnt;
12
  else
13
    PORTB = 15;
14
}

Und darüber kannst du jetzt Funktionen legen, die dir im Array LedOn 
eine 0 oder eine 1 einschreiben, je nachdem welche LED leuchten sollen.

von Karl H. (kbuchegg)


Lesenswert?

Electronics'nStuff schrieb:
> Karl Heinz Buchegger schrieb:
>> oder du baust deine Schaltung um.
>
> Ich hänge X auf PB5 :)

Keine gute Idee.
Nicht böse sein, aber bei deinen Programmierkünsten, solltest du dir 
Reset nicht wegfusen. Da kannst du 15 Prozessoren auch gleich so beim 
Fenster rauswerfen.

> Der Fall in dem keine LED leuchtet, kommt sowieso nie bis fast nie vor.
Du hast Multiplex nicht verstanden.
Der kommt vor!
Ungefähr 700 mal in der Sekunde!

Bei jeder LED stellt sich die Frage: Leuchten oder nicht Leuchten.
Leuchten ist einfach, du gibst ihr Muster an den Demux aus. Aber wie 
realisierst du 'nicht leuchten'? Im Zeitslot dieser LED muss irgendwas 
am Demux passieren, so dass dann diese LED (und zu diesem Zeitpunkt auch 
keine andere) eben nicht leuchtet.

von Electronics'nStuff (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> volatile uint8_t LedOn[15];
> uint8_t multiplexCnt;
>
> ISR( ... )
> {
>   multiplexCnt++;
>   if( multiplexCnt == 15 )
>     multiplexCnt = 0;
>
>   if( LedOn[multiplexCnt] )
>     PORTB = multiplexCnt;
>   else
>     PORTB = 15;
> }

Hm, verstehe ich das richtig, dass jetzt immer alle LEDs leuchten?
Weil if (LedOn[multiplexCnt]) ist doch immer wahr (ausser wenn 
multiplexCNnt = 0)?

von Electronics'nStuff (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Du hast Multiplex nicht verstanden.
> Der kommt vor!
> Ungefähr 700 mal in der Sekunde!
>
> Bei jeder LED stellt sich die Frage: Leuchten oder nicht Leuchten.
> Leuchten ist einfach, du gibst ihr Muster an den Demux aus. Aber wie
> realisierst du 'nicht leuchten'? Im Zeitslot dieser LED muss irgendwas
> am Demux passieren, so dass dann diese LED (und zu diesem Zeitpunkt auch
> keine andere) eben nicht leuchtet.

OH, jetzt habe ich verstanden. Ich war mir nicht ganz im Klaren, was 
PORTB = 0x00 in meiner Schaltung auslöst. Dann nehme ich die LED raus, 
das ist wirklch die einzige gescheite Alternative.

von Karl H. (kbuchegg)


Lesenswert?

Electronics'nStuff schrieb:
> Karl Heinz Buchegger schrieb:
>> volatile uint8_t LedOn[15];
>> uint8_t multiplexCnt;
>>
>> ISR( ... )
>> {
>>   multiplexCnt++;
>>   if( multiplexCnt == 15 )
>>     multiplexCnt = 0;
>>
>>   if( LedOn[multiplexCnt] )
>>     PORTB = multiplexCnt;
>>   else
>>     PORTB = 15;
>> }
>
> Hm, verstehe ich das richtig, dass jetzt immer alle LEDs leuchten?

Nein, das verstehst du falsch.

> Weil if (LedOn[multiplexCnt]) ist doch immer wahr (ausser wenn
> multiplexCNnt = 0)?

Ähm.
Da gibt es ein Array. Das nennt sich LedOn

Hier ist es

   LedOn
   +---+---+---+---+---+---+---+---+-...
   | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+-...

Und dann gibt es einen Zähler multiplexCnt. Der nimmt nacheinander alle 
Werte von 0 bis 14 an.

Wenn also multiplexCnt gerade den Wert 0 hat, was steht im Array an der 
Indexposition 0  (weil LedOn[multiplexCnt]). Da steht eine 0. Und 0 ist 
für das if ein logisches FALSE. d.h. in dem Fall wird dann auf den Demux 
eine 15 ausgegeben. D.h. Led-1 leuchtet nicht. (wohl aber würde LED-16 
leuchten, da die aber physisch nicht vorhanden ist, leuchtet gar keine 
LED)

Kurze Zeit später wird die ISR wieder aufgerufen.
multiplexCnt hat dann den Wert 1.
Was steht im Array an der Index-Position 1?
Da steht eine 1 drinnen.
1 ist für das if ein logisches TRUE.
Also wird der then Zweig genommen und die 1 an den Demux gegegeben. d.h. 
die LED-2 wird eingeschaltet und leuchtet.

Wieder kurze Zeit später wird die ISR das nächste mal aufgerufen. 
multiplexCnt hat denn den Wert 2.
Was steht im Array an der Index-Position 2?
Da steht eine 0. 0 ist für das if ein logisches FALSE (soll also 
heissen: die zugehörige LED soll nicht leuchten).
Ergo wird wieder das else genommen und der Demux auf 15 gestellt. 15 
heisst, dass LED-3 (und auch keine andere LED) nicht leuchtet.

usw. usw.
und so geht das immer reihum, mindestens 100 komplette Zyklen in der 
Sekunde (ansonsten flackert die ganze Sache). Zu jedem beliebigen 
Zeitpunkt leuchtet genau und nur eine einzige Led oder eben gar keine. 
Aber: die Zeiten sind so kurz und dein Auge ist so träge, dass du nicht 
mitkriegst, das das so ist. Für dich leuchten die jeweils 
eingeschalteten LED alle gleichzeitig.
Wie beim Kino. Du siehst in Wirklichkeit auch nur Standbilder. Da das 
aber viele in der Sekunde sind und du jedes Bild nur ganz kurz siehst, 
siehst du keine Einzelbilder mehr sondern einen bewegten Film.

von H.Joachim S. (crazyhorse)


Lesenswert?

Tja, komischer Ansatz.
Ich verstehe auch nicht, warum so ein kleiner Controller und dann wieder 
ne I/O-Erweiterung dran (noch dazu ne ganz schlechte wie in diesem 
Fall)?
Machs neu und nimm gleich nen Mega8 (oder 48/88), für jede LED nen Port.

Man muss auch los lassen können :-)

von Electronics'nStuff (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> LedOn
>    +---+---+---+---+---+---+---+---+-...
>    | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 |
>    +---+---+---+---+---+---+---+---+-...

Oh man, was steh ich auch auf dem Schlauch. Danke für deine schöne 
ausführliche Erklärung, aber diese Zeichnung hätte schon genügt um meine 
Verwirrung zu vernichten :)

Danke für eure Bemühungen!

von Peter D. (peda)


Lesenswert?

Der CD4067BE ist kein großer Stromtreiber, d.h. bei 1:16 Multiplex wirst 
du die LEDs kaum noch sehen.


Peter

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.