===== LED-Matrix max7219 =====
In diesem Wiki-Eintrag soll es im Gegensatz zum anderen [[computer:basteln:led-matrix|LED-Matrix]]-Eintag, nicht um die selbstgebauten Matrizen, sondern um LED-Matrizen vom Typ max7219 gehen.
Hier sind im Folgenden einige Code-Beispiele, um solche Matrizen mit dem Arduino zu bedienen, sowie das Anschließen an eben diesen zu finden.
==== Anschließen ====
==== Initialisierung im Arduino Code ====
Je nachdem, wie viele Matrizen man anschließen möchte, muss man ggf. die Variable 'maxInUse' auf die entsprechende Zahl anpassen.
// ***************** Beginn Initialisierung Matrix ************************
int dataIn = 2;
int load = 3;
int clock = 4;
int maxInUse = 3; //change this variable to set how many MAX7219's you'll use
// define max7219 registers
byte max7219_reg_noop = 0x00;
byte max7219_reg_digit0 = 0x01;
byte max7219_reg_digit1 = 0x02;
byte max7219_reg_digit2 = 0x03;
byte max7219_reg_digit3 = 0x04;
byte max7219_reg_digit4 = 0x05;
byte max7219_reg_digit5 = 0x06;
byte max7219_reg_digit6 = 0x07;
byte max7219_reg_digit7 = 0x08;
byte max7219_reg_decodeMode = 0x09;
byte max7219_reg_intensity = 0x0a;
byte max7219_reg_scanLimit = 0x0b;
byte max7219_reg_shutdown = 0x0c;
byte max7219_reg_displayTest = 0x0f;
void putByte(byte data) {
byte i = 8;
byte mask;
while (i > 0) {
mask = 0x01 << (i - 1); // get bitmask
digitalWrite( clock, LOW); // tick
if (data & mask) { // choose bit
digitalWrite(dataIn, HIGH);// send 1
} else {
digitalWrite(dataIn, LOW); // send 0
}
digitalWrite(clock, HIGH); // tock
--i; // move to lesser bit
}
}
void maxAll (byte reg, byte col) { // initialize all MAX7219's in the system
int c = 0;
digitalWrite(load, LOW); // begin
for ( c = 1; c <= maxInUse; c++) {
putByte(reg); // specify register
putByte(col);//((data & 0x01) * 256) + data >> 1); // put data
}
digitalWrite(load, LOW);
digitalWrite(load, HIGH);
}
void maxOne(byte maxNr, byte reg, byte col) {
//maxOne is for adressing different MAX7219's,
//whilele having a couple of them cascaded
int c = 0;
digitalWrite(load, LOW); // begin
for ( c = maxInUse; c > maxNr; c--) {
putByte(0); // means no operation
putByte(0); // means no operation
}
putByte(reg); // specify register
putByte(col);//((data & 0x01) * 256) + data >> 1); // put data
for ( c =maxNr-1; c >= 1; c--) {
putByte(0); // means no operation
putByte(0); // means no operation
}
digitalWrite(load, LOW);
digitalWrite(load,HIGH);
}
void setup() {
Serial.begin(9600);
pinMode(dataIn, OUTPUT);
pinMode(clock, OUTPUT);
pinMode(load, OUTPUT);
//initiation of the max 7219
maxAll(max7219_reg_scanLimit, 0x07);
maxAll(max7219_reg_decodeMode, 0x00); // using an led matrix (not digits)
maxAll(max7219_reg_shutdown, 0x01); // not in shutdown mode
maxAll(max7219_reg_displayTest, 0x00); // no display test
for (int e = 1; e <= 8; e++) { // empty registers, turn all LEDs off
maxAll(e, 0);
}
maxAll(max7219_reg_intensity, 0x0f & 0x0f); // the first 0x0f is the value you can set
// range: 0x00 to 0x0f
}
// ********************************* Ende Initialisierung Matrix **********************************
==== Pong ====
Um ein Pongspiel mit zwei Spielern auf ebenfalls zwei Led-Matrizen zu realiesieren, die man mit zwei Tasten steuert, kann man hinter die Initialisierung nachfolgende Code-Zeilen setzen:
int zeit = 0;
int Schlaegerrechts = 24; // Schläger 1
int Schlaegerlinks = 24; // Schläger 2
int taster1 = 5; // Taster 1 1 und 2 für Schläger rechts
int taster2 = 6; // Taster 2
int taster3 = 7; // Taster 3 3 und 4 für Schläger links
int taster4 = 8; // Taster 4
int read_taster1;
int read_taster2;
int read_taster3;
int read_taster4;
unsigned long time1 = 0;
unsigned long time2 = 0;
unsigned long time3 = 0;
unsigned long debounce = 100;
unsigned long debounce2 = 10000;
int matrix = 1; // Matrix auf der sich der Ball aktuell befindet
int xball = 3;
int dx = 1; // x-Richtung
int yball = 1;
float dy = 2.0; // y-Richtung als float, da die Änderung teilweise 0,5 ist. Kommazahlen nicht als int
int r = 0; // Variable für Zufallsgenerierung
int vball = 25; // Ballgeschwindigkeit
int zahl[] = {nul, eins, zwei, drei, vier, fuenf, sechs, sieben, acht, neun};
int xz = 0; // xz + den aktuelen Wert x ergibt zahl[]
int Wert1 = 0; // Wert1 - Wert4 für den Punktestand der beiden Spieler --> pro Matrix (und Spieler) zwei Zahlen
int Wert2 = 0;
int Wert3 = 0;
int Wert4 = 0;
void loop() {
maxOne (2, 1, Schlaegerrechts); // Position Schläger 1
maxOne (1, 8, Schlaegerlinks); // Position Schläger 2
delay(2);
// ****** Schläger ******
read_taster1 = digitalRead (taster1);
read_taster2 = digitalRead (taster2);
read_taster3 = digitalRead (taster3);
read_taster4 = digitalRead (taster4);
if (read_taster1 == HIGH && Schlaegerrechts >= 6 && millis() - time1 > debounce) { // Bewegung Schläger über Taster
time1 = millis();
Schlaegerrechts = Schlaegerrechts /= 2;
}
if (read_taster2 == HIGH && Schlaegerrechts <= 96 && millis() - time1 > debounce) { // Bewegung Schläger über Taster
time1 = millis();
Schlaegerrechts = Schlaegerrechts *= 2;
}
if (read_taster3 == HIGH && Schlaegerlinks >= 6 && millis() - time2 > debounce) { // Bewegung Schläger über Taster
time2 = millis();
Schlaegerlinks = Schlaegerlinks /= 2;
}
if (read_taster4 == HIGH && Schlaegerlinks <= 96 && millis() - time2 > debounce) { // Bewegung Schläger über Taster
time2 = millis();
Schlaegerlinks = Schlaegerlinks *= 2;
}
delay(1);
// ****** Ball ******
r = random (0, 3); // y-Richtung Ball ändert zufaällig am Schläger
// random zwischen 0-5 --> jeweils 2 random Werte stehen für ein dy --> Zuweisung dort, wo Schläger und Ball zusammentreffen
if (millis() - time3 > debounce2 && vball > 3) { // Änderung der Ballgeschwindigkeit --> wird immer schneller
time3 = millis();
vball--;
}
if (zeit == 0) {
maxOne (matrix, xball, 0); // Null setzt die Spalte zurück, sodass der Ball immer ein Punkt bleibt
xball += dx; // Bewegung in x-Richtung
yball *= dy; // Bewegung in y-Richtung
if (yball == 128) { // Ball am oberen Spielfeldrand
dy = 0.5;
}
if (yball == 1) { // Ball am unteren Spielfeldrand
dy = 2;
}
if (xball == 9 && matrix == 2 && dx == 1) { // Ball am rechten Rand der linken Matrix
matrix = 1; // Ball springt auf die rechte Matrix
xball = 1; // x Komponente wieder 1, da rechte Matrix dort wieder bei 1 los geht
}
if (xball == 0 && matrix == 1&& dx == -1) { // Ball am linken Rand der rechten Matrix
matrix = 2; // Ball springt auf die linke Matrix
xball = 8; // x Komponente 8, da linke Matrix dort wieder bei 8 anfängt
}
// ****** rechter Spielfeldrand ******
if (xball == 7 && matrix == 1) {
int pos1 = Schlaegerlinks / 3; // zur Ermittlung ob Schläger den Ball trifft
if (yball == pos1 || yball == 2 * pos1) { // Schläger trifft
dx = -1;
if(r == 0 && yball != 1) { // Änderung der y-Richtung wird mit den folgenden 3 if-Schleifen bestimmt
dy = 0.5;
}
else if (r == 1) {
dy = 1;
}
else if (r == 2 && yball != 128) {
dy = 2;
}
}
else { // Schläger trifft nicht
Wert2 = Wert2 + 4; // ab hier Punktezähler für den linken Spieler
if (Wert2 == 40) { // Zahl immer plus 4, da jede Zahl vier Spalten belegt (siehe Buchstaben.h)
Wert2 = 0;
Wert1 = Wert1 + 4;
}
for (int a = 0; a < 4; a++) {
xz = a + Wert1;
maxOne (2, a + 1, zahl [xz]);
}
for (int a = 0; a < 4; a++) {
xz = a + Wert2;
maxOne (2, a + 5, zahl [xz]);
} // Ende Punkezähler linker Spieler
for (int a = 0; a < 4; a++) { // Analog dazu der Punktestand des anderen Spielers ; ändert sich nicht
xz = a + Wert3;
maxOne (1, a + 2, zahl [xz]);
}
for (int a = 0; a < 4; a++) {
xz = a + Wert4;
maxOne (1, a + 6, zahl [xz]);
}
delay(2000);
for (int a = 1; a < 9; a++) {
maxAll (a, 0); // Matrix zurücksetzen
}
xball = 3; // Variablen zurücksetzen
yball = 1;
dx = 1;
dy = 2;
Schlaegerrechts = 24;
Schlaegerlinks = 24;
vball = 18;
}
}
// ****** linker Spielfeldrand ******
if (xball == 2 && matrix == 2) {
int pos2 = Schlaegerrechts / 3; // zur Ermittlung ob Schläger den Ball trifft
if (yball == pos2 || yball == 2 * pos2) { // Schläger trifft
dx = 1;
if(r == 0 && yball != 1) { // Änderung der y-Richtung wird mit den folgenden 3 if-Schleifen bestimmt
dy = 0.5;
}
else if (r == 1) {
dy = 1;
}
else if (r == 2 && yball != 128) {
dy = 2;
}
}
else { // Schläger trifft nicht
Wert4 = Wert4 + 4; // ab hier Punktezähler für den rechten Spieler
if (Wert4 == 40) {
Wert4 = 0;
Wert3 = Wert3 + 4;
}
for (int b = 0; b < 4; b++) {
xz = b + Wert3;
maxOne (1, b + 2, zahl [xz]);
}
for (int b = 0; b < 4; b++) {
xz = b + Wert4;
maxOne (1, b + 6, zahl [xz]);
} // Ende Punktezähler rechter Spieler
for (int b = 0; b < 4; b++) { // Analog der Punktestand des anderen Spielers ; ändert sich nicht
xz = b + Wert1;
maxOne (2, b + 1, zahl [xz]);
}
for (int b = 0; b < 4; b++) {
xz = b + Wert2;
maxOne (2, b + 5, zahl [xz]);
}
delay(2000);
for (int b = 1; b < 9; b++) {
maxAll (b, 0); // Matrix zurücksetzen
}
xball = 3; // Variablen zurücksetzen
yball = 1;
dx = 1;
dy = 2;
Schlaegerrechts = 24;
Schlaegerlinks = 24;
matrix = 1;
vball = 18;
}
}
maxOne (matrix, xball, yball); // Position Ball
}
zeit = (zeit + 1) % vball; // Nach jedem dritten Durchgang wird die Schleife für den Ball ausgeführt
// Modulo ist erforderlich, da mit einem längeren delay die Schläger langsamer wären
// Duch das Modulo läuft der Ball unabhängig von den Schläger
Serial.println(zeit);
// ****** Spielende erreicht --> Spiel wird auf Null zurückgesetzt ******
if (Wert1 == 8 && Wert2 == 4 || Wert3 == 8 && Wert4 == 4) { // Puntestand von 21 ist Spiel gewonnen und startet von Vorne
for (int c = 0; c < 9; c++) {
maxAll (c, 0);
}
Wert1 = 0;
Wert2 = 0;
Wert3 = 0;
Wert4 = 0;
for (int c = 1; c < 9; c++) {
maxOne (2, c, 255);
maxOne (1, 9 - c, 255);
delay(200);
maxOne (2, c, 0);
maxOne (1, 9 - c, 0);
}
for (int c = 0; c < 9; c++) {
maxAll (c, 255);
}
delay (4000);
for (int c = 0; c < 9; c++) {
maxAll (c, 0);
}
vball = 25; // Geschwindigkeit zurückstzen
}
}
In diesem Codebeispiel sind die Zahlen der Spielstände in eine extra Header-Datei ausgelagert, um den Code übersichtlicher zu machen. Um eine Header-Datei im Code zu includieren fügt man als erste Zeile des Codes
#include "HeaderDateiName.h"
ein.
Die Header-Datei hat in unserem Beispiel folgenden Inhalt:
#define nul 127, 65, 127, 0 //4
#define eins 0, 0, 127, 0 //4
#define zwei 121, 73, 79, 0 //4
#define drei 73, 73, 127, 0 //4
#define vier 15, 8, 127, 0 //4
#define fuenf 79, 73, 121, 0 //4
#define sechs 127, 73, 121, 0 //4
#define sieben 1, 1, 127, 0 //4
#define acht 127, 73, 127, 0 //4
#define neun 79, 73, 127, 0 //4
Anmerkung zur 0: Da null bereits durch die C++Syntax belegt ist, wurde hier statt dem Wort null, das Wort nul als Variable gesetzt.
Hinweis: Das Pongspiel lässt sich auch mit einem schöneren und kürzeren Code realisieren. Obiger Code wird daher demnächst noch ersetzt.
==== Laufschrift ====
Im Folgenden ist ein Code, der eine Laufschrift auf die Matrizen projizieren kann. Wie man diesen Anpassen kann, findet man dadrunter beschrieben.
Vor diesem Code ist der Initialisierungscode einzufügen.
int txt = 6;
unsigned long prev = 0;
const long interval = 200; //Durchlaufgeschwindigkeit
int z[] = {
Initialisieren,
R, A, T, S, G, Y, M, N, A, S, I, U, M, _,
P, E, I, N, E
};
int x = 119; // Zustände in z[] --- siehe Buchstaben.h
int h[] = {24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};
void loop () {
unsigned long cur = millis();
if(cur - prev >= interval){
for (int i = 0; i < 24; i++){
h[i]++;
}
prev = cur;
}
for (int i = 0; i < 24; i++){
if(h[i] == x){
h[i] = 0;
}
}
maxOne(1,8,z[h[0]]);
maxOne(1,7,z[h[1]]);
maxOne(1,6,z[h[2]]);
maxOne(1,5,z[h[3]]);
maxOne(1,4,z[h[4]]);
maxOne(1,3,z[h[5]]);
maxOne(1,2,z[h[6]]);
maxOne(1,1,z[h[7]]);
maxOne(2,8,z[h[8]]);
maxOne(2,7,z[h[9]]);
maxOne(2,6,z[h[10]]);
maxOne(2,5,z[h[11]]);
maxOne(2,4,z[h[12]]);
maxOne(2,3,z[h[13]]);
maxOne(2,2,z[h[14]]);
maxOne(2,1,z[h[15]]);
maxOne(3,8,z[h[16]]);
maxOne(3,7,z[h[17]]);
maxOne(3,6,z[h[18]]);
maxOne(3,5,z[h[19]]);
maxOne(3,4,z[h[20]]);
maxOne(3,3,z[h[21]]);
maxOne(3,2,z[h[22]]);
maxOne(3,1,z[h[23]]);
}
Um eine eigene Schrift anzeigen zu lassen, ist lediglich notwendig in int z[] ={ Initialisieren,...};
hinter "Initialisieren" die gewollten Buchstaben einzufügen. Anschließend muss die Länge der Nachricht in int x =...;
angepasst werden. Hierzu werden 32 Zeichen für die Initialisierung benötigt und die restlichen Zahlen, die noch drauf addiert werden sollen, ist die Anzahl der Zeichen der jeweiligen Buchstaben, bzw. die Zahl, die in der "Buchstaben.h" Datei als Kommentar hinter dem jeweiligen Buchstaben finden lassen. \\
Bei Ratsgymnasium Peine ist daher der Wert 119.
\\
\\
Schließlich muss hier noch die Header-Datei "Buchstaben.h" noch includiert werden.
#include "Buchstaben.h"
Damit der Compiler die Header-Datei finden kann, muss sie im gleichen Ordner gespeichert sein, wie das gesamte Projekt. Die Arduino-Entwicklungsumgebung hilft dabei, indem man im Fenster mit dem geöffneten Code einen Tab hinzufügt und diese Datei entsprechend "Buchstaben.h" nennt und anschließen den zugehörigen Inhalt hinzufügt.\\
Der Inhalt dieser Datei ist folgender:
// Alphabet Definition
#define A 126, 17, 17, 126, 0 //5
#define B 127, 73, 73, 54, 0 //5
#define C 62, 65, 65, 65, 0 //5
#define D 127, 65, 65, 62, 0 //5
#define E 127, 73, 73, 65, 0 //5
#define F 127, 9, 9, 1, 0 //5
#define G 62, 65, 81, 50, 0 //5
#define H 127, 8, 8, 127, 0 //5
#define I 65, 127, 65, 0 //4
#define J 65, 65, 63, 0 //4
#define K 127, 20, 34, 65, 0 //5
#define L 127, 64, 64, 0 //4
#define M 127, 2, 12, 2, 127, 0 //6
#define N 127, 4, 8, 16, 127, 0 //6
#define O 62, 65, 65, 62, 0 //5
#define P 127, 9, 9, 6, 0 //5
#define Q 62, 65, 81, 33, 94, 0 //6
#define R 127, 25, 41, 70, 0 //5
#define S 38, 73, 73, 50, 0 //5
#define T 1, 1, 127, 1, 1, 0 //6
#define U 63, 64, 64, 63, 0 //5
#define V 31, 32, 64, 32, 31, 0 //6
#define W 127, 32, 28, 32, 127, 0 //6
#define X 99, 20, 8, 20 ,99, 0 //6
#define Y 3, 4, 120, 4, 3, 0 //6
#define Z 97, 81, 73, 69 ,67, 0 //6
#define AK 32, 84, 84, 120, 0 //5
#define BK 63, 72, 72, 48, 0 //5
#define CK 48, 72, 72, 72, 0 //5
#define DK 48, 72, 72, 127, 0 //5
#define EK 56, 84, 84, 88, 0 //5
#define FK 126, 9, 1, 0 //4
#define GK 76, 146, 146, 124, 0 //5
#define HK 127, 8, 8, 112, 0 //5
#define IK 122, 0 //2
#define JK 64, 136, 122, 0 //4
#define KK 127, 16, 40, 68, 0 //5
#define LK 63, 64, 64, 0 //4
#define MK 120, 8, 112, 8, 120, 0 //6
#define NK 8, 112, 8, 8, 112, 0 //6
#define OK 48, 72, 72, 48, 0 //5
#define PK 252, 36, 36, 24, 0 //5 (Alternative: 248, 72, 72, 48, 0)
#define QK 24, 36, 36, 252, 0 //5 (Alternative: 48, 72, 72, 248, 0)
#define RK 8, 112, 8, 8, 0 //5
#define SK 72, 84, 84, 36, 0 //5
#define TK 8, 63, 72, 64, 0 //5
#define UK 56, 64, 64, 56, 0 //5
#define VK 24, 32, 64, 32, 24, 0 //6
#define WK 56, 64, 48, 64, 56, 0 //6
#define XK 72, 48, 48, 72, 0 //5
#define YK 4, 8, 112, 8, 4, 0 //6 (Alternative: 24, 160, 160, 120, 0)
#define ZK 72, 104, 88, 72, 0 //5
#define nul 127, 65, 127, 0 //4
#define eins 0, 0, 127, 0 //4
#define zwei 121, 73, 79, 0 //4
#define drei 73, 73, 127, 0 //4
#define vier 15, 8, 127, 0 //4
#define fuenf 79, 73, 121, 0 //4
#define sechs 127, 73, 121, 0 //4
#define sieben 1, 1, 127, 0 //4
#define acht 127, 73, 127, 0 //4
#define neun 79, 73, 127, 0 //4
#define Fragezeichen 2, 1, 89, 6, 0 //5
#define Ausrufezeichen 79, 0 //2
#define Punkt 64, 0 //2
#define Appostroph 5, 3, 0 //3
#define Komma 160, 96, 0 //3
#define _ 0, 0 //2 (Leerzeichen)
#define Plus 8, 8, 62, 8, 8, 0 //6
#define Minus 8, 8, 8, 8, 8, 0 //6
#define Mal 20, 8, 62, 8, 20, 0 //6
#define Geteilt 32, 16, 8, 4, 2, 0 //6
#define Gleich 20, 20, 20, 20, 20, 0 //6
#define Initialisieren 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 //24 Pro Matrix 8x 0 dazu
#define Herz 28, 62, 126, 252, 126, 62, 28, 0 //8