Es war im Jahre 1978 ...
In der Juli/August-Ausgabe der Elektor aus dem Jahre 1978 wurde ein "Pseudo-Random-Lauflicht" vorgestellt, bestehend aus einem Timer 555 und zwei CMOS-ICs (4015 und 4011). Dieses Lauflicht war sicherlich sehr beliebt, da es sich hervorragend z.B. für den Modellbau/ -bahnbereich eignete. Heutzutage würde man allerdings, um ein paar LEDs aufleuchten zu lassen, solch eine Schaltung mit einem Mikrocontroller aufbauen. Allerdings scheint es speziell für diesen Fall ein Problem zu geben: In der Schaltung werden zwei Ausgänge eines Schieberegisters über ein XOR-Gatter an den Dateneingang zurückgekoppelt. Die damalige Schaltung sah in etwa so aus:
Die beiden 4 Bit-Schiebregister schieben den aktuellen Wert "D" (IC2A) bei jedem CLK Signal weiter. Durch die Rückkopplung von zwei Ausgängen über das XOR ergibt das ein Problem: Zunächst sind alle Ausgänge auf "low", somit auch der Ausgang des XOR. Das hat zur Folge, dass immer nur "Nullen" durch die beiden Register geschoben werden. Es fehlt also ein Startpunkt, wo kurzzeitig der Eingang "D" auf "high" gesetzt wird. In der Orginalschaltung aus der Elektor wurde dazu eine R/C/D-Kombination an einem der XOR-Eingänge verwendet, die allerdings nicht immer zuverlässig funktionierte.
Theorie
Um die Schaltung mittels Mikrocontroller zu realisieren, muss man die genaue Abfolge dieser Schaltung einmal notieren. Zunächst wird davon ausgegangen, daß der erste Ausgang (QA, Pin13) auf "high" sein soll. Dieses high wird nun auf QB, QC usw. weitergeschoben, bis zu dem Punkt, wo der Ausgang des XOR beeinflusst wird. Die geschieht, wenn QB und QC (Pin 3 und 4) den Binärwert "10" oder "01" annehmen. Wenn das XOR dann ein "high" an "D" ausgibt, wird beim nächsten Takt diese "1" über das Schieberegister weitergeleitet. Um die Funktionalität besser darszustellen, sei diese Folge der Ausgänge dargestellt:
XOR-Wert
Pins
Bemerkungen
10
3
4
5
2
11
12
13
Pin 3 und 4 sind am XOR angeschlossen
0
0
0
0
0
0
0
0
1
Startwert
0
0
0
0
0
0
0
1
0
"1" weitergeschoben
0
0
0
0
0
0
1
0
0
"1" weitergeschoben
0
0
0
0
0
1
0
0
0
"1" weitergeschoben
0
0
0
0
1
0
0
0
0
"1" weitergeschoben
1
0
0
1
0
0
0
0
0
"1" weitergeschoben, im nächsten Takt wird "1" des XOR weitergeleitet
1
0
1
0
0
0
0
0
1
"1" weitergeschoben, "1" des XOR im ersten Bit (orange)
0
1
0
0
0
0
0
1
1
"1" weitergeschoben, "1" des XOR im ersten Bit (grün)
0
0
0
0
0
0
1
1
0
"1" weitergeschoben, "0" des XOR im ersten Bit (hellblau)
0
0
0
0
1
1
1
0
0
"1" weitergeschoben, "0" des XOR im ersten Bit (gelb)
Aus den ersten 10 Ausgangszuständen lässt sich eine Formel zu Berechnung des Augabewertes für einen Mikrocontroller entwickeln:
1) Wenn die XOR-Verknüpfung von Pin 3 und 4 ein "low" ist, dann wird der aktuelle Wert um eine Stelle nach links verschoben, dieser Wert wird dann ausgegeben.
2) Wenn die XOR-Verknüpfung von Pin 3 und 4 ein "high" ist, dann wird der aktuelle Wert um eine Stelle nach links verschoben, anschließend wird eine "1" zum Wert hinzuaddiert und dieser Wert dann ausgegeben.
Programm für dieses Lauflicht
1) Lauflichtprogramm für den USB-Controller FT232, FT2232 oder FT245
Sicherlich ist es zu schade, nur ein Lauflicht für einen USB-Controller zu schreiben. Man kann aber hier gleich sehen, ob der Algorithmus für das Lauflicht funktioniert. Nach Öffnen und Setzen des Devices in den bit-bang Modus werden zunächst einige Variablen benötigt:
DWORD BytesWritten; //Für die Funktion FT_Write()
int Wert; //Der aktuelle angezeige Wert
int StartWert=0x01; //Startwert 1, damit überhaupt etwas angezeigt wird
int XORErg = 0; //Das ERgebnis der XOR-Verknüpfung. Zunächst "0"
int XORWert1, XORWert2; //Input des XOR (Pin 3 und 4 der IC-Schaltung
Wert = StartWert; // Die "1" soll am Anfang gesetzt werden
In der while()-Schleife werden folgende Kommandos durchgeführt:
while (!_kbhit())
{
FT_Write(handleFT0,&Wert,1,&BytesWritten);
XORWert1 = (0x40 & Wert) >>6;
XORWert2 = (0x20 & Wert) >>5;
XORErg = XORWert1 ^ XORWert2;
if (XORErg == 0)
{
Wert = Wert << 1;
}
if (XORErg == 1)
{
Wert = (Wert << 1) + 1;
}
sleep (200);
Zunächst wird der aktuelle Wert (Am Anfang Startwert, also 1) mit der Funktion FT_Write() gesetzt. Anschließend wird der aktuelle Wert mit den Input-Pins (XORWert1 und XORWert2) des XOR (0x40 und 0x20) jeweils UND verknüpft und um 6 bzw. 5 Stellen nach rechts verschoben. Damit kann herausgefunden werden, ob der Ausgang des XOR (XORErg) gesetzt wird oder nicht (XOR-Verknüpfung zwischen XORWert1 und XORWert2).Eine kurze Wartezeit von 200ms macht das Ergebnis des Programms sichtbar. Das folgende kleine Video zeigt das USB-Lauflicht im Betrieb: Pseudo-Random-Lauflicht-USB.MPG (1,2MB)
2) Lauflichtprogramm für ATTiny26
Die Umsetzung des o.g. Programms auf einen Mikrocontroller ist relativ einfach: Die FT_SetBitMode()-Funktion wird durch den Aufruf DDRB = 0xFF (DB-Port auf Ausgabe) und die Write()-Funktion wird durch den PORTB = ... -Aufruf ersetzt. Das fertige Programm für den Tiny26 sieht wie folgt aus:
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
//**************************************************************
// Pseudo Random Lauflicht, 8 Kanal
// By B. Redemann, March 2007
//**************************************************************
int main(void)
{
//Variablen zur Berechnung des XOR Outputs
int StartWert=0x01;
int Wert, i;
unsigned char XORErg = 0;
unsigned char XORWert1, XORWert2;
Wert = StartWert;