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
Hi
>Ich habe einen Attiny13 in Kombination mit einem CD4067BE>Schieberegister.
Der CD4067 ist ein Multiplexer/Demultiplexer, kein Schieberegister.
MfG Spess
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)?
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.
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
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.
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
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
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_twelche;
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.
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
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.
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
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
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)
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
> 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
volatileuint8_tLedOn[15];
2
uint8_tmultiplexCnt;
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.
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.
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)?
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.
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.
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 :-)
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!