Dieser Text ist erst 2015 von meinem alten CMS in den Blog gewandert.
Dieses Projekt macht aus einem AVR ATmega8 Mikrocontroller einen LED-Controller für eine Matrix aus 8×8 LEDs. Der Controller verhält sich als I2C-Slave, die anzuzeigenden Bitmuster können also über diesen Bus (der auch als TWI bekannt ist, Two Wire Interface) geschickt werden.Sinn und Zweck
In meinem nächsten grösseren Projekt will ich Zahlenwerte auf Siebensegmentanzeigen ausgeben. Ich habe vor einer Weile eine Menge von diesen Dingern gekauft, jetzt kommen sie zum Einsatz. Das sind vierstellige mit einem zwölfpoligen Anschluss an der Unterseite. Acht Pins für die Kathoden der LEDs (sieben Segmente plus Punkt) und vier Anoden, eine für jede Ziffer.
Man kann sich diese Module als Matrix aus vier mal acht LEDs vorstellen, wie in dem Schaltplan hier dargestellt wird. Ich benutze zwei von den Modulen, also habe ich eine Matrix aus acht mal acht LEDs.
Die Zeilen und Spalten dieser Matrix werden an den Mikrocontroller angeschlossen, so dass der die Lampen Zeile für Zeile befeuern kann. Das hat zwei Vorteile: erstens sind maximal acht LEDs gleichzeitig an, das drückt den Stromverbrauch. Und zweitens braucht man auf diese Weise nur 16 Pins um 64 LEDs anzutreiben.
Durch diese Art der Ansteuerung flackert die Ausgabe natürlich etwas, aber der Controller ist schnell genug damit man das mit dem bloßen Auge nicht sehen kann.
Ich hätte meine Displaymodule natürlich auch direkt an den Hauptcontroller des nächsten Projektes anschließen können, aber da habe ich nicht mehr genug freie Pins. Außerdem wird das Programm auf dem Hauptcontroller übersichtlicher wenn das Multiplexen der LEDs woanders geschieht, da ich mich nicht um irgendein Timing kümmern muss. Also ist ein billiger ATmega8 ein prima LED-Treiber, und ich sage dem per I2C was er anzeigen soll.
I2C sprechen
Der ATmega8 hat ein eingebautes Hardware-I2C-Interface, also braucht es nicht allzu viel Code um I2C zu sprechen. Trotzdem habe ich mir von roboternetz.de die kleine Bibliothek gezogen, die Uwe Grosse-Wortmann (uwegw) geschrieben hat. Ich habe die nur etwas umformatiert um den Code meinem Programmierstil anzupassen. Nein, ich habe die Kommentare nicht gelöscht…
Benutzung
Am anderen Ende der Kommunikation habe ich die großartige Procyon AVRlib von Pascal Stang benutzt. Ein einfaches Code-Beispiel um mit der I2C LED Matrix zu sprechen sieht so aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#define I2C_LEDMATRIX 0x10 // address of the device timerInit(); // initialize timers timerPause(100); // give everything a little time to settle i2cInit(); // initialize i2c function library timerPause(100); // wait a bit more while (1) { // endless loop uint8_t buffer[9]; // prepare buffer // loop until 255 for (uint8_t i = 0; i <= 255; i++) { // set all bytes of the buffer to value i memset(buffer, i, sizeof(buffer)); // send the buffer via I2C-bus i2cMasterSend(I2C_LEDMATRIX, sizeof(buffer), buffer); timerPause(500); // wait, so you have the time to watch } } |
Man bemerke: der Buffer hält nicht wirklich die Zahlen die auf dem Display dargestellt werden sollen, zumindest nicht in diesem Beispiel. Da sind nur die Bitmuster drin.
Zahlen anzeigen
Wenn man Siebensegmentanzeigen an den Controller anschließt um darauf Zahlen anzuzeigen müssen die auf der Master-Seite des Busses definiert werden. Ich habe die Definitionen nicht in dieses Projekt aufgenommen um dem Master die volle Kontrolle über die LEDs zu geben, selbst wenn keine Zahlen angezeigt werden sollen.
Außerdem hängt die Darstellung davon ab wie die Displays an den Controller angeschlossen sind. Ich weiß nicht ob die Pinbelegung irgendwie standardisiert ist.
Um ein Beispiel zu geben wie sowas gebaut wird, hier ist ein Codeausschnitt der mit meinem Display funktioniert:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// Names of the segments: // aaaaa // f b // f b // ggggg // e c // e c // ddddd h uint8_t characters[16]; // c e g a h f b d characters[ 0] = (1 << 0) | (1 << 1) | (0 << 2) | (1 << 3) | (0 << 4) | (1 << 5) | (1 << 6) | (1 << 7); // 0 characters[ 1] = (1 << 0) | (0 << 1) | (0 << 2) | (0 << 3) | (0 << 4) | (0 << 5) | (1 << 6) | (0 << 7); // 1 characters[ 2] = (0 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (0 << 4) | (0 << 5) | (1 << 6) | (1 << 7); // 2 characters[ 3] = (1 << 0) | (0 << 1) | (1 << 2) | (1 << 3) | (0 << 4) | (0 << 5) | (1 << 6) | (1 << 7); // 3 characters[ 4] = (1 << 0) | (0 << 1) | (1 << 2) | (0 << 3) | (0 << 4) | (1 << 5) | (1 << 6) | (0 << 7); // 4 characters[ 5] = (1 << 0) | (0 << 1) | (1 << 2) | (1 << 3) | (0 << 4) | (1 << 5) | (0 << 6) | (1 << 7); // 5 characters[ 6] = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (0 << 4) | (1 << 5) | (0 << 6) | (1 << 7); // 6 characters[ 7] = (1 << 0) | (0 << 1) | (0 << 2) | (1 << 3) | (0 << 4) | (0 << 5) | (1 << 6) | (0 << 7); // 7 characters[ 8] = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (0 << 4) | (1 << 5) | (1 << 6) | (1 << 7); // 8 characters[ 9] = (1 << 0) | (0 << 1) | (1 << 2) | (1 << 3) | (0 << 4) | (1 << 5) | (1 << 6) | (1 << 7); // 9 characters[10] = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (0 << 4) | (1 << 5) | (1 << 6) | (0 << 7); // a characters[11] = (1 << 0) | (1 << 1) | (1 << 2) | (0 << 3) | (0 << 4) | (1 << 5) | (0 << 6) | (1 << 7); // b characters[12] = (0 << 0) | (1 << 1) | (0 << 2) | (1 << 3) | (0 << 4) | (1 << 5) | (0 << 6) | (1 << 7); // c characters[13] = (1 << 0) | (1 << 1) | (1 << 2) | (0 << 3) | (0 << 4) | (0 << 5) | (1 << 6) | (1 << 7); // d characters[14] = (0 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (0 << 4) | (1 << 5) | (0 << 6) | (1 << 7); // e characters[15] = (0 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (0 << 4) | (1 << 5) | (0 << 6) | (0 << 7); // f |
Nachteile
Bis jetzt hat das Teil in allen getesteten Situationen prima funktioniert. Alles läuft wie geplant.
Danke!
Ich danke den Autoren der Bibliotheken die ich benutzt habe: Uwe Grosse-Wortmann (uwegw) für die I2C-Slave-Bibliothek und Pascal Stang für seine Procyon AVRlib.
Lizenz
Dieses Projekt steht unter der GNU General Public License (GPL). Eine Kopie der GPL liegt dem Paket in der Datei License.txt bei.
Download
- i2c-ledmatrix_090506.tar.gz – Sourcecode und Dokumentation, 212kB