Projekt: Der Würfel

Wer kennt das nicht: man möchte mit seinen Freunden ein Brettspiel spielen, aber hat leider keinen passenden Würfel dabei. Aber natürlich immer ein Jugend Programmiert Starterkit und einen Raspberry griffbereit. Dann verraten wir dir jetzt die Lösung, wie du aus deinem Raspberry und dem OLED Display schnell und unkompliziert einen Würfel zaubern kannst 😀

Anschlüsse am Raspberry PiAnschlüsse am Display/Taster
GPIO 2 / I2C SDA1 – SDA
GPIO 3 / I2C SCL2 – SCL
3,3V3 – VCC
GND4 – GND
GPIO 231 – Taster
GND2- Taster + 10kOhm

Erstelle dazu eine neue Python-Datei und benne sie. Das kannst du z.B. mit nano machen.
Zu Beginn importieren wir wieder wie gewohnt die benötigeten Bibliotheken:

import adafruit_ssd1306
from PIL import Image, ImageDraw, ImageFont
from random import randint
import RPi.GPIO as gpio
import digitalio
import time
import board

Außerdem brauchen wir auch die GPIO Pins damit wir auch wissen, wann gewürfelt werden soll:

gpio.setmode(gpio.BCM)
channel = 23
gpio.setup(channel, gpio.IN, pull_up_down=gpio.PUD_UP)

Jetzt müssen wir nur noch das Display wieder initialisieren und dann können wir auch schon mit dem eigentlichen Teil anfangen:

RESET_PIN = digitalio.DigitalInOut(board.D4)
i2c = board.I2C()
oled = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3C,
    reset=RESET_PIN)

oled.fill(0)
oled.show()

Damit wir auch nachher die zufällig generierte Zahl auf dem Display anzeigen können, müssen wir aber zuvor noch die Schriftart importieren:

font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 64)

Wenn das Programm startet soll auf dem Display zunächst ein „?“ angezeigt werden, damit das Display nicht komplett leer ist und man auch weiß: „Ahh, jetzt kanns losgehen“.

imageBegin = Image.new("1", (oled.width, oled.height))
ImageDraw.Draw(imageBegin).text((40, 0), "?", font=font, fill=255)
oled.image(imageBegin)
oled.show()

Damit wir gleich, wenn eine zufällige Zahl gewürfelt wurde, nicht jedes mal ein neues Bild generieren müssen, machen wir das jetzt schon und speichern uns die Zahlen 1 bis 6 in einem Array ab:

numbers = []
for i in range(1, 7):
    image = Image.new("1", (oled.width, oled.height))
    ImageDraw.Draw(image).text((40, 0),
        str(i), font=font, fill=255)
    numbers.append(image)

Wie du siehst erstellen wir uns hierzu erstmal ein leeres Array numbers in dem wir gleich die generierten Bilder speichern können. Darauf wird eine for-Schleife von den Zahlen 1 bis 6 gestartet. Die Funktion range(1,7) erstellt ein Array von den Zahlen 1 bis 6, welches wir nutzen um in der for-Schleife die Bilder zu generieren. Achte dabei darauf das der zweite Parameter eine 7 ist, obwohl wir nur bis 6 Zählen wollen. Das kommt daher, dass die interne range Funktion dann aufhört das Array mit Zahlen zu befüllen, sobald sie beim Hochzählen diesen Wert erreicht hat. Die 7 wird also nicht mit übernommen.
Die nächste Zeile kennst du schon: Hier wird ein neues Bild erstellt. In der folgenden Zeile schreiben wir einen Text in das leere Bild. Dazu erstellen wir mit der str() Funktion einen String aus der übergebenen variable i , welche beim Durchlaufen der for-Schleife die Zahlen 1 bis 6 animmt.
Wenn das Bild fertig erstellt ist, fügen wir es dem Array numbers, dass wir zu Beginn erstellt haben hinzu. Dazu nutzen wir die eingebaute Array-Methode .append().

So, kommen wir nun zum Eigentlichen Part, wofür wir das Skript hier überhaupt schreiben: dem Würfeln:

while True:
    if gpio.input(channel) == 0:
        while True:
            oled.image(numbers[randint(0, 5)])
            oled.show()
            time.sleep(0.01)
            if gpio.input(channel) == 1:
                oled.image(numbers[randint(0, 5)])
                oled.show()
                time.sleep(0.5)
                break

Natürlich wollen wir nach jedem Würfelvorgang nicht das Skript neu starten müssen. Also schreiben wir den nächsten Teil in einer while True Schleife.
Zu Beginn fragen wir ab, ob der Taster betätigt wurde. Falls ja, starten wir eine Würfel-Animation, bei der solange eine zufällige Ziffer angezeigt wird, bis der Taster wieder losgelassen wird. Dazu setzen wir auch diesen Teil in eine while True Schleife und fragen in jeder Runde ab, ob der Taster wieder losgelassen wurde. Zuvor generieren wir allerdings mit der Funktion randint(0, 5) eine Zufällige Zahl von 0 bis 5 und nutzen diese um uns die entsprechende Stelle von dem Array numbers auszugeben. Bei Arrays fängt man bei der Programmierung fast immer bei 0 an zu zählen, desshalb erstellen wir zuvor auch eine zufällige Zahl von 0 bis 5 und nicht von 1 bis 6 ;).
Wir haben jetzt also aus dem Array numbers eins zufälliges den von vorhin generierten Bildern ausgewählt. Dieses übergeben wir nun an die Funktion oled.image() und führen darauf oled.show() aus um das Bild auf dem Display anzuzeigen. Genau das Gleiche machen wir nochmal, wenn der Taster losgelassen wurde; wir wolllen ja nicht, dass man einfach so lange den Taster gedrückt hält, bis die gewünschte Zahl auf dem Display aufleuchtet ;).
Wenn der Taster wieder losgelassen wurde, verlassen wir mit break die aktuelle Schleife und landen wieder in der der darüber liegenden Schleife, in der wir auf einen erneuten Tastendruck warten.

Sollte bei dir etwas nicht geklappt haben, kannst du dir auch das fertige Skript von uns runterladen:

wget https://cw42.de/p/oled-wuerfel.py

Jetzt ist das Skript auch schon fertig und du kannst jetzt deinem Raspberry, beim nächsten Spieleabend glänzen.