In meinem vorherigen Beitrag ‘Pixelmatrix Combo von Oxocard: So programmierst du die 5×5 LED Matrix‘ habe ich bereits die Grundlagen und Möglichkeiten der Pixelmatrix vorgestellt. In diesem Beitrag möchte ich nun einen Schritt weiter gehen und zeigen, wie du mit der 5 × 5 LED Matrix einen digitalen Würfel programmierst, der Zufallszahlen anzeigt. Dieses Projekt eignet sich hervorragend, um die Programmierung von Zufallszahlen und die Ansteuerung der LEDs in einem kreativen Projekt zu kombinieren.
Hinweis: Dieses Produkt wurde mir vom Entwickler der Oxocard auf der Maker Faire 2024 in Hannover kostenlos zur Verfügung gestellt. Meine Meinung und Bewertung des Produkts basieren jedoch ausschließlich auf meinen eigenen Erfahrungen und sind unabhängig von dieser Bereitstellung.
Inhaltsverzeichnis
- Bezug der Pixelmatrix von Oxocard
- Programmieren der Oxocard Connect in NanoPy
Bezug der Pixelmatrix von Oxocard
Die in diesem Beitrag verwendete Pixelmatrix bekommst du für derzeit 49 CHF (ca. 52 €) unter https://oxocard.ch/. Zu dem Set gehört neben der Pixelmatrix noch der Mikrocontroller Oxocard Connect, welchen du für diese Cartridge benötigst.
Rechts ist die Pixelmatrix Cartridge, da ich den Mikrocontroller bereits besitze, benötigte ich nicht das komplett Set.
Programmieren der Oxocard Connect in NanoPy
Den Mikrocontroller kannst du in NanoPy via Python programmieren. Die Entwicklungsumgebung NanoPy ist sehr leistungsstark und bietet für erfahrene Entwickler sehr viele nützliche Features, welches man in anderen Editoren für Mikrocontroller schmerzhaft vermisst, zum Beispiel ein Debugger.
Programmieren eines Würfels mit der Pixelmatrix & der Oxocard Connect
Bevor wir mit der eigentlichen Programmierung starten, schauen wir uns an, wie man die Pixelmatrix programmiert. Jeder NeoPixel hat einen Index, welcher oben rechts beginnt und unten links endet.
Mit der Funktion setDigitalLed können wir dann über diesen Index die LED ansteuern und einen RGB Wert übergeben.
#aktivieren der LED mit Index 1 und setzen der Farbe blau setDigitalLed(1, 0, 0, 100)
Theoretisch können wir jeden Farbwert verwenden, hier empfehle ich dir die Seite https://htmlcolorcodes.com/, auf welcher du recht einfach einen solchen Wert generieren kannst.
Bitmaskieren der Zeilen
Da wir die sechs möglichen Werte des Würfels auf der Pixelmatrix anzeigen wollen, gibt es hier mehrere Lösungen. Der wohl einfachste Weg ist ein Array mit 25 Werten für jeden Wert, das ergibt dann 6 Arrays welche wir je nach ermittelter Zufallszahl verwenden. Theoretisch spricht nichts gegen diese Lösung, denn es ist sehr unwahrscheinlich, dass ein neuer Wert hinzukommt, jedoch ist diese nicht optimal.
Wir können auch jede Zeile in ein Bitmuster maskieren und so durch eine 0 und 1 den Zustand jedes NeoPixel abbilden.
Im nachfolgenden Beispiel stelle ich die Augenzahl 1 dar, es sind alle NeoPixel deaktiviert außer das Mittlere in der dritten Zeile.
digits =[ 0b00000, 0b00000, 0b00100, 0b00000, 0b00000, #Zahl 1 ... ]
Wir benötigen zusätzlich noch eine Funktion, welche uns den Status des Neopixels liefert. Ich definiere hier, dass ein Bitmuster eine Zeile (in Englisch row) ist und als zusätzlichen Parameter übergebe ich den Index pro Zeile. Als Rückgabewert erhalte ich ein true, wenn der NeoPixel aktiviert werden soll, andernfalls ein false.
def checkLed(row, index)->bool: return row & (1 << index)
Hier siehst du auch eine Eigenheit von NanoPy, wir haben hier Datentypen welche wir in Python / MicroPython nicht haben. Auch müssen wir einen expliziten Rückgabewert benennen, wenn wir diesen haben.
Mit dieser Lösung haben wir nun die Darstellung aller möglichen Werte optimal gelöst.
#Würfelaugen auf der Pixelmatrix definieren digits =[ 0b00000, 0b00000, 0b00100, 0b00000, 0b00000, #Zahl 1 0b00001, 0b00000, 0b00000, 0b00000, 0b10000, #Zahl 2 0b00001, 0b00000, 0b00100, 0b00000, 0b10000, #Zahl 3 0b10001, 0b00000, 0b00000, 0b00000, 0b10001, #Zahl 4 0b10001, 0b00000, 0b00100, 0b00000, 0b10001, #Zahl 5 0b10001, 0b00000, 0b10001, 0b00000, 0b10001 #Zahl 6 ] def checkLed(row, index)->bool: return row & (1 << index)
Joystick-Tasten von der Oxocard Connect auswerten
Die Oxocard Connect verfügt über einen kleinen 4 Achsen Joystick, von welchem wir die Tasten auswerten können, zusätzlich haben wir noch die mittlere Taste, welche ich für dieses kleine Programm verwenden möchte.
button = getButtons() if button.middle: delay(500)
Damit wir den Eingang entprellen lege, ich direkt nach der If Bedingung eine pause von 500ms ein, diese reicht aus, damit der Benutzer den Finger von dem Joystick nimmt und somit lediglich ein Signal ausgewertet wird.
Ermitteln einer Zufallszahl
Nachdem das Event von dem Joystick ausgewertet wurde, erzeugen wir eine Zufallszahl. In diesem Fall nutzen wir die aktuell vergangenen Millisekunden, seit dem der Mikrocontroller gestartet ist als Quelle (RandomSeed) und generieren daraus eine Zufallszahl zwischen 1 und 7 (wobei die Zahl 7 exklusiv ist).
ms = getMillis() randomSeed(ms) value = random(1,7)
Berechnen eines Offsets für die Anzeige eines Wertes auf der Pixelmatrix
Unsere Daten liegen in einem Array hintereinander weg, wir benötigen jedoch immer nur genau 5 Werte aus diesem. Für die Ermittlung der Werte benötigen wir hier ein Offset, welches wir aus der ermittelten Zufallszahl errechnen können:
offset = 5 * (value-1)
Da Arrays immer mit dem Index 0 beginnen, müssen wir von der ermittelten Zufallszahl eins abziehen!
Anzeigen eines Wertes auf der Pixelmatrix
Mit dem Offset können wir nun die Zeilen ermitteln, welche wir für die Darstellung des Wertes benötigen. Da wir 25 Werte absenden müssen, merken wir uns den aktuellen Index in der Variable count welchen wir zusätzlich der Funktion displayDigit neben der Zeile übergeben.
for i in [0..5]: row = digits[offset+i] displayDigit(row,count) count = count + 5
Am Ende zählen wir diesen Index um 5 Stellen hoch.
Funktion – displayDigit
In der Funktion displayDigit wird jetzt die Zeile ausgewertet und die NeoPixel aktiviert oder deaktiviert.
#anzeigen der Augenzahl auf der Pixelmatrix def displayDigit(row, count): innerCounter = count for index in [0..4]: innerCounter++ if checkLed(row, index): setDigitalLed(innerCounter, 0, 0, 100) else: setDigitalLed(innerCounter, 0, 0, 0)
#initialisieren der NeoPixel initDigitalLeds(C_PIN_01, 25, C_LED_TYPE_WS2812) #setzen des Modus für die Farben der NeoPixel setDigitalLedMode(C_LED_MODE_GRB) #Würfelaugen auf der Pixelmatrix definieren digits =[ 0b00000, 0b00000, 0b00100, 0b00000, 0b00000, #Zahl 1 0b00001, 0b00000, 0b00000, 0b00000, 0b10000, #Zahl 2 0b00001, 0b00000, 0b00100, 0b00000, 0b10000, #Zahl 3 0b10001, 0b00000, 0b00000, 0b00000, 0b10001, #Zahl 4 0b10001, 0b00000, 0b00100, 0b00000, 0b10001, #Zahl 5 0b10001, 0b00000, 0b10001, 0b00000, 0b10001 #Zahl 6 ] def checkLed(row, index)->bool: return row & (1 << index) #anzeigen der Augenzahl auf der Pixelmatrix def displayDigit(row, count): innerCounter = count for index in [0..4]: innerCounter++ if checkLed(row, index): setDigitalLed(innerCounter, 0, 0, 100) else: setDigitalLed(innerCounter, 0, 0, 0) count = -1 def main(): button = getButtons() if button.middle: delay(500) count = -1 ms = getMillis() randomSeed(ms) value = random(1,7) print("Zufallszahl:"+value) offset = 5 * (value-1) print("Offset:"+offset) for i in [0..4]: row = digits[offset+i] displayDigit(row,count) count = count + 5 applyDigitalLeds() while true: main()