Charlieplexing - Multiplexing mit LEDs

Multiplexing sind Methoden zur Signalübertragung, bei denen mehrere Signale zusammengefasst und simultan über ein Medium (z.B. Kabel) übertragen werden. Dies wird oft dazu verwendet, um die Anzahl der Anschlüsse einer Komponente zu reduzieren.
Charlieplexing ist eine von Charlie Allen entwickelte Methode, um die Anzahl der Pins zu reduzieren, die eine gewisse Menge LEDs zum Betrieb benötigen. Bei dieser Technik macht man sich den Umstand zunutze, dass ein Mikrocontroller (z.B. Arduino oder ESP32) drei verschiedene Zustände an seinen digitalen Ausgängen einnehmen kann: HIGH, LOW und INPUT.

Verwendete Bauteile

Funktionsweise

Charlieplexing mit 2 LEDs unter Verwendung von 2 Pins
Abb.: Charlieplexing mit 2 LEDs unter Verwendung von 2 Pins

Die zwei Anschlüsse X1 und X2 des obigen Bildes sind zu zwei digitalen Pins am Arduino angeschlossen. Um LED1 leuchten zu lassen, muss man den X1 auf HIGH schalten und gleichzeitig X2 auf LOW. Um LED2 leuchten zu lassen, invertiert man die Signale einfach. Hier der Sketch für das abwechselnde Aufleuchten der LEDs:

#define PIN_X1 2
#define PIN_X2 3

void setup()
{
    pinMode(PIN_X1, OUTPUT);
    pinMode(PIN_X2, OUTPUT);
}

void loop()
{
    // light LED1
    digitalWrite(PIN_X1, HIGH);
    digitalWrite(PIN_X2, LOW);
    delay(1000);

    // light LED2
    digitalWrite(PIN_X1, LOW);
    digitalWrite(PIN_X2, HIGH);
    delay(1000);
}

In diesem einfachsten Fall bietet das Charlieplexing keine Ersparnis an Pins, doch fügt man einen weiteren digitalen Pin hinzu, wird das Prinzip ersichtlich:

Charlieplexing mit 6 LEDs unter Verwendung von 3 Pins
Abb.: Charlieplexing mit 6 LEDs unter Verwendung von 3 Pins

Um diese LED-Matrix richtig schalten zu können, benötigt man einen neuen logischen Zustand: INPUT. Um nun LED1 leuchten zu lassen muss nun das Signal an X1 HIGH und and X2 LOW sein. X3 muss aber sozusagen aus dem Stromkreis "abgekoppelt" werden. Dies erreicht man, indem man an X3 den Signalzustand INPUT anlegt, d.h. die Impedanz dieses Pins wird sehr hoch und damit faktisch nicht mehr Teil des Stromflusses. Die folgende Tabelle zeigt die Signalzustände zum Schalten einzelnen LEDs:

Schalttabelle für 6 LEDs

LED Pin X1 Pin X2 Pin X3
1 HIGH LOW INPUT
2 LOW HIGH INPUT
3 INPUT HIGH LOW
4 INPUT LOW HIGH
5 HIGH INPUT LOW
6 LOW INPUT HIGH

Was ist hier falsch?

Angenommen, man will LED6 zum leuchten bringen. Anhand der obigen Tabelle muss man dazu X1 auf LOW, X3 auf HIGH und X2 auf hohe Impedanz, also INPUT schalten. Aber was ist mit LED2 und LED4? Sollten diese nicht auch aufleuchten, da ja der Strom durch sie genauso hindurchfließt?
Nein, denn LEDs haben generell einen engen Bereich der Betriebsspannung, meist zwischen 2,9V bis 3,3V. Wenn man also 3,3V an X3 und 0V an X1 anlegt, dann liegt an LED6 ebenfalls eine Spannung von 3,3V an, und somit leuchtet sie auf. Aber bei LED2 und LED4 ist anhand der Kirchhoff'schen Regel die Summe 3,3V, d.h. die Spannung teilt sich hier auf 1,65V pro LED und die LEDs können nicht leuchten, da ihre Betriebsspannung nicht erreicht ist. Es fließt dennoch ein sehr kleiner Strom durch die LEDs, der aber zu vernachlässigen ist.

Vorwiderstände richtig platzieren

Normalerweise werden die Vorwiderstände zwischen Mikrocontroller und den Ports der Charlieplexing-Schaltung platziert. Jeder Widerstand den benötigten Wert halbieren, z.B. will man die LED mit 200 Ohm schützen, dann müssen 100-Ohm-Widerstände verwendet werden. Das kommt daher, weil der Strom immer durch zwei Widerstände in Serie fließt, wenn eine LED leuchten soll.

Der folgende Sketch lässt 6 LEDs (unter Verwendung von 3 Pins) nacheinander aufleuchten:

#define PIN_X1 2
#define PIN_X2 3
#define PIN_X3 4

void setup()
{
    resetPins();
}

void loop()
{
    // light one LED after each other
    for (byte i=1; i<=6; i++) {
        lightLed(i);
        delay(500);
    }
}

void lightLed(byte ledIndex)
{
    switch(ledIndex) {
        case 1:
            setPins(PIN_X1, PIN_X2);
            break;
        case 2:
            setPins(PIN_X2, PIN_X1);
            break;
        case 3:
            setPins(PIN_X2, PIN_X3);
            break;
        case 4:
            setPins(PIN_X3, PIN_X2);
            break;
        case 5:
            setPins(PIN_X1, PIN_X3);
            break;
        case 6:
            setPins(PIN_X3, PIN_X1);
            break;
    }
}

void setPins(byte highPin, byte lowPin)
{
    resetPins();
    pinMode(highPin, OUTPUT);
    pinMode(lowPin,  OUTPUT);

    digitalWrite(highPin, HIGH);
    digitalWrite(lowPin,  LOW);
}

void resetPins()
{
    pinMode(PIN_X1, INPUT);
    pinMode(PIN_X2, INPUT);
    pinMode(PIN_X3, INPUT);
    digitalWrite(PIN_X1, LOW);
    digitalWrite(PIN_X2, LOW);
    digitalWrite(PIN_X3, LOW);
}

Fügt man nun immer weiter digitale Pins in den Schaltplan hinzu, so wird die Anzahl an steuerbaren LEDs schnell größer. Die folgende Tabelle zeigt, wieviele LEDs sich mit entsprechenden Pins steuern lassen.

Pin-Verwendung

Pins LEDs
1 0
2 2
3 6
4 12
5 20
6 30
7 42
8 56
9 72
10 90
20 380
40 1560
n n2 − n

Matrix als Schaltungsvariante

Man kann wie beim Multiplexing die LEDs in Spalten und Zeilen einteilen, so dass man pro Spalte (oder Zeile) jeweils genau eine LED zum leuchten bringen kann.

Multiplexing-Matrix mit LEDs
Abb.: Multiplexing-Matrix mit LEDs
Charlieplexing-Matrix mit LEDs
Abb.: Charlieplexing-Matrix mit LEDs

Nur eine LED gleichzeitig?

Die Charlieplexing-Methode kann immer nur eine LED gleichzeitig schalten, allerdings gibt es eine Möglichkeit mehrere LEDs gleichzeitig leuchten zu lassen. Das heißt, es scheint nur so! Ähnlich wie es mit bewegten Bilder beim Film oder Fernsehen gemacht wird, werden die LEDs, die gleichzeitig leuchten sollen, so schnell hintereinander zum Leuchten und Erlöschen gebracht, dass es für das menschliche Auge so aussieht, als würden sie gleichzeitig leuchten.
Allerdings gibt es einige Parameter zu bedenken. Zunächst muss die HIGH-LOW-Rate schnell genug gewählt werden, damit das menschliche Auge getäuscht wird. Ab 24 Hz erscheint das Leuchten in etwa gleichmäßig. Allerdings scheinen die LEDs dann nicht mehr genauso hell, als wären sie gleichmäßig am Leuchten, sondern etwas gedimmt. Dem kann entgegengewirkt werden, wenn man die Vorwiderstände entsprechend kleiner wählt und der Strom, der durch die LEDs fließt damit wieder höher wird.
Hierbei kann die Lebensspanne der LEDs drastisch gesenkt werden, vor allem, wenn es Fehler in der Programmierung des Mikrocontrollers gibt und LEDs zu lange leuchten!
Dieses Prinzip machen sich auch die Projekte mit den 3x3x3-LED-Cubes bzw. 4x4x4-LED-Cubes zu Nutze.

Für hohere Ströme können auch Transistoren verwendet werden.

Charlieplexing zur Dateneingabe

Charlieplexing kann ebenfalls dazu verwendet werden, Eingaben zu verwalten, z.B. einen Knopfdruck. Hierbei werden die LEDs durch Taster bzw. Schaltern ersetzt. Um herauszubekommen, welcher Knopf in der Charlieplexing-Matrix gedrückt wurde, muss man im Sketch permanent durch alle Input iterieren. Dabei wird in jedem Schritt jeweils ein Taster als INPUT und die anderen als OUTPUT geschaltet. Falls der Mikrocontroller (z.B. Arduino) interne Pullup-Widerstände besitzt, kann man die externen Komponenten minimieren.

zurück