Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
airdraw [2022/06/22 22:23] – student | airdraw [2023/07/03 10:15] (aktuell) – Externe Bearbeitung 127.0.0.1 | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== AirDraw ====== | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Inspiration ===== | ||
+ | Das Projekt hat sich von dem Spiel „Paint Splash“ aus der Wii-Konsole inspiriert. Hier | ||
+ | ist eine Demonstration: | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Einführung ===== | ||
+ | Im Projekt werden der Sense Hat und drei externe Buttons verwendet. Aus dem Sense Hat sind der Magnetometer, | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Projektbilder ===== | ||
+ | |||
+ | ==== Malfenster ==== | ||
+ | |||
+ | |||
+ | {{ : | ||
+ | |||
+ | ==== VNC-Fenster ==== | ||
+ | {{ : | ||
+ | |||
+ | ==== Externe Buttons ==== | ||
+ | {{ :4.jpg?250 |}} | ||
+ | |||
+ | ==== Projektaufbau (Vorderansicht) ==== | ||
+ | {{ :1.png?500 |}} | ||
+ | |||
+ | ==== Projektaufbau (Seitenansicht) ==== | ||
+ | {{ :2.png?500 |}} | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Bauteile ===== | ||
+ | - [[https:// | ||
+ | - [[https:// | ||
+ | - [[https:// | ||
+ | - [[https:// | ||
+ | - [[https:// | ||
+ | - [[https:// | ||
+ | - [[https:// | ||
+ | - [[https:// | ||
+ | - [[https:// | ||
+ | - [[https:// | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Schaltplan ===== | ||
+ | {{ : | ||
+ | |||
+ | ** Fritzing: ** | ||
+ | * Raspberry pi 4B [[https:// | ||
+ | * Sense Hat [[https:// | ||
+ | |||
+ | ** GPIO PINs vom Sense Hat: ** | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Weitere Informationen ===== | ||
+ | |||
+ | ==== Sense Hat ==== | ||
+ | * In raspi-config muss I2C aktiviert sein: [[https:// | ||
+ | {{ : | ||
+ | |||
+ | ==== Magnetometer (Sense Hat) ==== | ||
+ | Da der Magnetometer ursprünglich für einen Kompass gedacht ist und nur einen kleinen Wertebereich nutzt, müssen die rohen Daten des Magnetometers verwendet werden. Dadurch vergrößert sich der Wertebereich, | ||
+ | |||
+ | ==== Joystick (Sense Hat) ==== | ||
+ | Um die Zeichenfunktion im Malprogramm zu aktivieren, gibt der Joystick des Sense Hats zwei Zustände an. Der erste Zustand des Stiftes ist als mittlere Position definiert, sodass die Malfunktion beim Drücken aktiviert wird. Der zweite Zustand ist die untere Position definiert, sodass die Malfunktion beim Drücken nach unten gestoppt wird. | ||
+ | |||
+ | ==== Externe Buttons ==== | ||
+ | Die freien GPIO Pins des Raspberry Pis können mithilfe eines verlängerten 40 PIN Headers angesprochen werden. Indem der PIN Header des Sense Hats mit den verlängerten PIN Header vertauscht wird, können die Buttons mit ihrem Kabel verbunden werden. Dabei bleibt die Funktionalität des Sense Hats erhalten. Wichtig ist, nicht die gleichen GPIO Pins wie von den Sense Hats zu verwenden, da sonst Fehler entstehen können. | ||
+ | |||
+ | ==== Bluetooth Lautsprecher ==== | ||
+ | * Hinweis: Falls die Bluetoothverbindung nicht mit den Raspberry Pi funktioniert, | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Konfiguration ===== | ||
+ | Für das Projekt werden folgende Pakete benötigt: | ||
+ | |||
+ | **Python3** | ||
+ | * Hinweis: Im Raspberry Pi 400 wird der Text von den Buttons nicht angezeigt, dies kann an der alten Python Version 3.7.3 liegen, weswegen Version 3.9.4 und darüber empfohlen wird. | ||
+ | |||
+ | **sense_hat** | ||
+ | |||
+ | enthält alle Funktionen des Sense Hats. [[https:// | ||
+ | |||
+ | **Pygame** | ||
+ | |||
+ | Mithilfe Pygame wird ein interaktives Malfenster erzeugt. In Pygame gibt es die Möglichkeit, | ||
+ | |||
+ | **Pygame GUI** | ||
+ | |||
+ | ist ein Graphical User Interface, mit dem Buttons im Malfenster angezeigt werden kann. Im Programm dient sie nur zur Orientierung der Funktionalität der externen Buttons. [[https:// | ||
+ | |||
+ | **gpiozero** | ||
+ | |||
+ | vereinfacht die Implementation der externen Buttons, da sie Funktionen aus RPI.GPIO in eigene Methoden übernimmt und dadurch den Programmcode verkürzt. [[https:// | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Zusätzliche Programme ===== | ||
+ | |||
+ | **m8tricks** | ||
+ | |||
+ | vereinfacht die Implementation der LED-Matrix, sodass wenn eine LED im Programm eine andere Farbe als Schwarz ausgewählt wird, auch im Sense Hat angezeigt wird. Dadurch kann leicht überprüft werden, ob ein Bild in 8x8 Format gut oder schlecht aussieht. Dazu kann die aktuelle LED-Matrix in einem Ordner gespeichert werden und später mit Thonny im Hauptprogramm gespeichert werden. M8tricks ist nur eine Hilfsanwendung, | ||
+ | * Hinweis: In der Dokumentation von m8tricks steht, dass das Programm im Terminal mit „m8tricxks“ ausgeführt wird. Dies ist falsch und wird stattdessen mit „m8tricks“ ausgeführt. | ||
+ | |||
+ | **VNC** | ||
+ | |||
+ | VNC (Virtual Network Computing) übertragt den Bildschirm des Raspberry Pis mit den Malprogramm auf einen zweiten Raspberry Pi, sodass während der Übertragung keine Maus, Keyboard und HDMI-Kabel benötigt wird. Dies verbessert die Bewegung des Sense Hats mit der Hand. Um VNC zu nutzen, muss im zweiten Raspberry Pi VNC-Viewer installiert werden und beide Raspberry Pis müssen im gleichen Netzwerk sein. Um das Malprogramm zu beenden, muss mit den zweiten Raspberry Pi das Malfenster geschlossen werden. [[https:// | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Programmcode ===== | ||
+ | |||
+ | In Pygame werden Parameter wie Name, Größe und Hintergrundfarbe des Fensters angegeben. Dazu wird für Pygame GUI ein Bereich definiert, welcher später die Buttons im Fenster verarbeitet. | ||
+ | |||
+ | **Malfenster** | ||
+ | |||
+ | <file python AirDraw.py> | ||
+ | # Fenstergröße und Hintergrundfarbe bestimmen | ||
+ | pygame.display.set_caption(' | ||
+ | screen = pygame.display.set_mode((screenX, | ||
+ | screen.fill(WE) | ||
+ | pygame.display.update() | ||
+ | |||
+ | # GUI-Bereich definieren | ||
+ | manager = pygame_gui.UIManager((screenX, | ||
+ | </ | ||
+ | |||
+ | Wenn ein Button im Fenster erzeugt werden soll, müssen bestimmte Parameter angegeben werden. In der Dokumentation von Pygame GUI werden weitere Möglichkeiten für Parameter angegeben. | ||
+ | |||
+ | **Beispiel eines Buttons im GUI** | ||
+ | |||
+ | <file python AirDraw.py> | ||
+ | # farbeButton erzeugen | ||
+ | farbeButton = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((25, | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | Falls ein externer Button gedrückt wird, wird eine Sounddatei abgespielt, der Mauszeiger springt zum jeweiligen Button im Malfenster und beispielsweise die Funktion „setze die Stiftfarbe auf Weiß“ wird ausgeführt. Zusätzlich wird in der LED-Matrix ein 8x8 Bild dargestellt und es folgt eine Pause. | ||
+ | |||
+ | ** Beispiel eines externen Buttons** | ||
+ | |||
+ | <file python AirDraw.py> | ||
+ | if button2.is_pressed: | ||
+ | sound_2.play() | ||
+ | position2() | ||
+ | aktuelleFarbe = WE | ||
+ | sense.set_pixels( | ||
+ | [(0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (255, 0, 255), (255, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (255, 0, 255), (255, 0, 255), (255, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (255, 0, 255), (255, 0, 255), (255, 0, 255), (255, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (255, 0, 255), (255, 0, 255), (255, 0, 255), (255, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (255, 0, 255), (255, 0, 255), (255, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (255, 0, 255), (255, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0)]) | ||
+ | pygame.time.delay(2500) | ||
+ | sense.clear() | ||
+ | </ | ||
+ | |||
+ | Um die Koordinaten vom Sense Hat in Pygame korrekt anzeigen zu können, müssen die Sensordaten des Sense Hats formatiert und gerundet werden. Danach wird im Malfenster mit den Koordinaten des Sense Hats ein Kreis gezeichnet. | ||
+ | |||
+ | **Kreis an der richtigen Position zeichnen** | ||
+ | |||
+ | <file python AirDraw.py> | ||
+ | raw = sense.get_compass_raw() | ||
+ | # Button für das Zeichnen wird gedrückt | ||
+ | if event.type == Draw and zeichnen is True: | ||
+ | # Formatierung und Berechnung der Position des Stiftes | ||
+ | xsense = " | ||
+ | ysense = " | ||
+ | |||
+ | xsense = float(xsense) | ||
+ | ysense = float(ysense) | ||
+ | |||
+ | xsense = round(xsense) | ||
+ | ysense = round(ysense) | ||
+ | |||
+ | # Multiplikation mit negativer Zahl, weil der SenseHat in Normalposition negative Zahlen anzeigt | ||
+ | lastPos = ((ysense * -10) + 350, (xsense * -10) - 200) | ||
+ | pygame.draw.circle(screen, | ||
+ | pygame.display.update() | ||
+ | pygame.time.delay(100) | ||
+ | </ | ||
+ | |||
+ | Am Ende des Malprogramms wird ein Bild vom Malfenster erzeugt und im Verzeichnis „Zeichnungen“ gepeichert. Außerdem wird Pygame heruntergefahren. | ||
+ | |||
+ | **Ende des Malprogramms** | ||
+ | |||
+ | <file python AirDraw.py> | ||
+ | except StopIteration: | ||
+ | pass | ||
+ | sense.clear() | ||
+ | screenshot.blit(sub, | ||
+ | |||
+ | # Ordner " | ||
+ | pygame.image.save(screenshot, | ||
+ | print(" | ||
+ | # Programm wird beendet | ||
+ | pygame.mixer.music.stop() | ||
+ | pygame.quit() | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Gesamter Programmcode ===== | ||
+ | |||
+ | <file python AirDraw.py> | ||
+ | # Pakete importieren | ||
+ | import pygame | ||
+ | import pygame_gui | ||
+ | from sense_hat import SenseHat | ||
+ | from gpiozero import Button | ||
+ | |||
+ | # Buttons definieren | ||
+ | button1 = Button(" | ||
+ | button2 = Button(" | ||
+ | button3 = Button(" | ||
+ | |||
+ | # Pygame und Sense Hat starten | ||
+ | pygame.mixer.pre_init(44100, | ||
+ | pygame.init() | ||
+ | pygame.mixer.init() | ||
+ | sense = SenseHat() | ||
+ | |||
+ | # LED-Matrix in Normalzustand versetzen | ||
+ | sense.clear() | ||
+ | |||
+ | # Hintergrundmusik starten | ||
+ | pygame.mixer.music.load(' | ||
+ | pygame.mixer.music.play(-1) | ||
+ | pygame.mixer.music.set_volume(0.3) | ||
+ | |||
+ | # Fenstergröße bestimmen | ||
+ | screenX = 800 | ||
+ | screenY = 600 | ||
+ | |||
+ | # Farben mit RGB-Werten bestimmen | ||
+ | WE = (255, 255, 255) | ||
+ | SCHW = (0, 0, 0) | ||
+ | ROT = (255, 0, 0) | ||
+ | GR = (0, 255, 0) | ||
+ | BL = (0, 0, 255) | ||
+ | |||
+ | # Liste für FarbeButton | ||
+ | Farben = [ROT, GR, BL] | ||
+ | |||
+ | aktuelleFarbe = SCHW | ||
+ | |||
+ | # Zähler für Farben_Button | ||
+ | counter = 0 | ||
+ | |||
+ | # Bedingung für while-Schleife | ||
+ | durchlaufen = True | ||
+ | |||
+ | # Fenstergröße und Hintergrundfarbe bestimmen | ||
+ | pygame.display.set_caption(' | ||
+ | screen = pygame.display.set_mode((screenX, | ||
+ | screen.fill(WE) | ||
+ | pygame.display.update() | ||
+ | |||
+ | # GUI-Bereich definieren | ||
+ | manager = pygame_gui.UIManager((screenX, | ||
+ | |||
+ | # farbeButton erzeugen | ||
+ | farbeButton = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((25, | ||
+ | | ||
+ | | ||
+ | # loeschButton erzeugen | ||
+ | loeschButton = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((125, | ||
+ | text=' | ||
+ | manager=manager) | ||
+ | |||
+ | # resetButton erzeugen | ||
+ | resetButton = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((225, | ||
+ | | ||
+ | | ||
+ | |||
+ | # Uhr für Bildwiederholrate und Abfrage der Buttons | ||
+ | clock = pygame.time.Clock() | ||
+ | |||
+ | # boolean zur Bestimmung des Zustandes des Stiftes | ||
+ | zeichnen = False | ||
+ | |||
+ | # Endposition des Stiftzeigers | ||
+ | lastPos = (0, 0) | ||
+ | |||
+ | # Radius vom Kreis, also Stiftdicke am Anfang bestimmen | ||
+ | radius = 10 | ||
+ | |||
+ | # boolean, um Loeschzustand zu bestimmen | ||
+ | radierer = 0 | ||
+ | |||
+ | # Bildwiederholrate auf 60 FPS, um Leistung zu minimieren | ||
+ | timeDelta = clock.tick(60) / 1000.0 | ||
+ | |||
+ | # Definition eines eignen Pygame-Events, | ||
+ | Draw = pygame.USEREVENT + 0 | ||
+ | pygame.time.set_timer(Draw, | ||
+ | |||
+ | # Positionen des Mauscursors, | ||
+ | |||
+ | def startPosition(): | ||
+ | pygame.mouse.set_pos([screenX / 2, screenY / 2]) | ||
+ | } | ||
+ | |||
+ | |||
+ | def position1(): | ||
+ | pygame.mouse.set_pos([screenX - 742, screenY - 555]) | ||
+ | } | ||
+ | |||
+ | |||
+ | def position2(): | ||
+ | pygame.mouse.set_pos([screenX - 637, screenY - 555]) | ||
+ | } | ||
+ | |||
+ | |||
+ | def position3(): | ||
+ | pygame.mouse.set_pos([screenX - 542, screenY - 555]) | ||
+ | } | ||
+ | |||
+ | # Definition eines Teilfensters, | ||
+ | rect = pygame.Rect(0, | ||
+ | sub = screen.subsurface(rect) | ||
+ | screenshot = pygame.Surface((screenX, | ||
+ | |||
+ | # Soundeffekte initialisieren | ||
+ | sound_1 = pygame.mixer.Sound(' | ||
+ | sound_1.set_volume(0.4) | ||
+ | sound_2 = pygame.mixer.Sound(' | ||
+ | sound_2.set_volume(0.4) | ||
+ | sound_3 = pygame.mixer.Sound(' | ||
+ | sound_3.set_volume(0.4) | ||
+ | |||
+ | # Mauszeiger in der Mitte des Malfensters | ||
+ | startPosition() | ||
+ | |||
+ | # Programm wird gestartet | ||
+ | try: | ||
+ | while durchlaufen: | ||
+ | # alle externe Button-Events | ||
+ | if button1.is_pressed: | ||
+ | sound_1.play() | ||
+ | position1() | ||
+ | if aktuelleFarbe == WE: | ||
+ | aktuelleFarbe = SCHW | ||
+ | # set_pixels() zeigt im SenseHat die LEDS an | ||
+ | sense.set_pixels( | ||
+ | [(0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (255, 0, 0), (255, 0, 0), (0, 0, 0), (0, 0, 0), (0, 255, 0), (0, 255, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (255, 0, 0), (255, 0, 0), (0, 0, 0), (0, 0, 0), (0, 255, 0), | ||
+ | (0, 255, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 255), | ||
+ | (0, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 255), | ||
+ | (0, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0)]) | ||
+ | pygame.time.delay(2500) | ||
+ | sense.clear() | ||
+ | else: | ||
+ | counter = counter + 1 | ||
+ | if counter == 1: | ||
+ | aktuelleFarbe = Farben[0] | ||
+ | sense.set_pixels( | ||
+ | [(255, 255, 255), (255, 255, 255), (255, 255, 255), (255, 255, 255), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (255, 255, 255), (255, 0, 0), (255, 0, 0), (255, 255, 255), | ||
+ | (0, 0, 0), (0, 255, 0), (0, 255, 0), (0, 0, 0), (255, 255, 255), (255, 0, 0), (255, 0, 0), | ||
+ | (255, 255, 255), (0, 0, 0), (0, 255, 0), (0, 255, 0), (0, 0, 0), (255, 255, 255), | ||
+ | (255, 255, 255), (255, 255, 255), (255, 255, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 255), (0, 0, 255), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 255), (0, 0, 255), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0)]) | ||
+ | pygame.time.delay(2500) | ||
+ | sense.clear() | ||
+ | if counter == 2: | ||
+ | aktuelleFarbe = Farben[1] | ||
+ | sense.set_pixels([(0, | ||
+ | (255, 255, 255), (255, 255, 255), (0, 0, 0), (255, 0, 0), (255, 0, 0), | ||
+ | (0, 0, 0), (255, 255, 255), (0, 255, 0), (0, 255, 0), (255, 255, 255), | ||
+ | (0, 0, 0), (255, 0, 0), (255, 0, 0), (0, 0, 0), (255, 255, 255), (0, 255, 0), | ||
+ | (0, 255, 0), (255, 255, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (255, 255, 255), (255, 255, 255), (255, 255, 255), (255, 255, 255), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 255), | ||
+ | (0, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 255), (0, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0)]) | ||
+ | pygame.time.delay(2500) | ||
+ | sense.clear() | ||
+ | if counter == 3: | ||
+ | aktuelleFarbe = Farben[2] | ||
+ | sense.set_pixels( | ||
+ | [(0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (255, 0, 0), (255, 0, 0), (0, 0, 0), (0, 0, 0), (0, 255, 0), (0, 255, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (255, 0, 0), (255, 0, 0), (0, 0, 0), (0, 0, 0), (0, 255, 0), | ||
+ | (0, 255, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (255, 255, 255), | ||
+ | (255, 255, 255), (255, 255, 255), (255, 255, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (255, 255, 255), (0, 0, 255), (0, 0, 255), (255, 255, 255), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (255, 255, 255), (0, 0, 255), (0, 0, 255), | ||
+ | (255, 255, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (255, 255, 255), | ||
+ | (255, 255, 255), (255, 255, 255), (255, 255, 255)]) | ||
+ | pygame.time.delay(2500) | ||
+ | sense.clear() | ||
+ | if counter == 4: | ||
+ | aktuelleFarbe = SCHW | ||
+ | sense.set_pixels( | ||
+ | [(0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (255, 0, 0), (255, 0, 0), (0, 0, 0), (0, 0, 0), (0, 255, 0), (0, 255, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (255, 0, 0), (255, 0, 0), (0, 0, 0), (0, 0, 0), (0, 255, 0), | ||
+ | (0, 255, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (255, 255, 255), (255, 255, 255), (255, 255, 255), (255, 255, 255), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (255, 255, 255), (0, 0, 0), (0, 0, 0), | ||
+ | (255, 255, 255), (0, 0, 0), (0, 0, 255), (0, 0, 255), (0, 0, 0), (255, 255, 255), | ||
+ | (0, 0, 0), (0, 0, 0), (255, 255, 255), (0, 0, 0), (0, 0, 255), (0, 0, 255), (0, 0, 0), | ||
+ | (255, 255, 255), (255, 255, 255), (255, 255, 255), (255, 255, 255), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0)]) | ||
+ | pygame.time.delay(2500) | ||
+ | sense.clear() | ||
+ | counter = 0 | ||
+ | |||
+ | if button2.is_pressed: | ||
+ | sound_2.play() | ||
+ | position2() | ||
+ | aktuelleFarbe = WE | ||
+ | sense.set_pixels( | ||
+ | [(0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (255, 0, 255), (255, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (255, 0, 255), (255, 0, 255), (255, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (255, 0, 255), (255, 0, 255), (255, 0, 255), (255, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (255, 0, 255), (255, 0, 255), (255, 0, 255), (255, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (255, 0, 255), (255, 0, 255), (255, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (255, 0, 255), (255, 0, 255), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0)]) | ||
+ | pygame.time.delay(2500) | ||
+ | sense.clear() | ||
+ | |||
+ | if button3.is_pressed: | ||
+ | sound_3.play() | ||
+ | position3() | ||
+ | screen.fill(WE) | ||
+ | aktuelleFarbe = SCHW | ||
+ | pygame.display.update() | ||
+ | sense.set_pixels( | ||
+ | [(0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), | ||
+ | (0, 0, 0), (255, 255, 255), (255, 255, 255), (255, 255, 255), (255, 255, 255), (255, 255, 255), | ||
+ | (255, 255, 255), (0, 0, 0), (0, 0, 0), (255, 255, 255), (255, 255, 255), (255, 255, 255), | ||
+ | (255, 255, 255), (255, 255, 255), (255, 255, 255), (0, 0, 0), (0, 0, 0), (255, 255, 255), | ||
+ | (255, 255, 255), (255, 255, 255), (255, 255, 255), (255, 255, 255), (255, 255, 255), (0, 0, 0), | ||
+ | (0, 0, 0), (255, 255, 255), (255, 255, 255), (255, 255, 255), (255, 255, 255), (255, 255, 255), | ||
+ | (255, 255, 255), (0, 0, 0), (0, 0, 0), (255, 255, 255), (255, 255, 255), (255, 255, 255), | ||
+ | (255, 255, 255), (255, 255, 255), (255, 255, 255), (0, 0, 0), (0, 0, 0), (255, 255, 255), | ||
+ | (255, 255, 255), (255, 255, 255), (255, 255, 255), (255, 255, 255), (255, 255, 255), (0, 0, 0), | ||
+ | (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0)]) | ||
+ | pygame.time.delay(2500) | ||
+ | sense.clear() | ||
+ | # Joystick-Events | ||
+ | for event in sense.stick.get_events(): | ||
+ | if event.action == ' | ||
+ | zeichnen = True | ||
+ | elif event.action == ' | ||
+ | zeichnen = False | ||
+ | # allgemeine Events | ||
+ | for event in pygame.event.get(): | ||
+ | raw = sense.get_compass_raw() | ||
+ | # Button für das Zeichnen wird gedrückt | ||
+ | if event.type == Draw and zeichnen is True: | ||
+ | # Formatierung und Berechnung der Position des Stiftes | ||
+ | xsense = " | ||
+ | ysense = " | ||
+ | |||
+ | xsense = float(xsense) | ||
+ | ysense = float(ysense) | ||
+ | |||
+ | xsense = round(xsense) | ||
+ | ysense = round(ysense) | ||
+ | |||
+ | # Multiplikation mit negativer Zahl, weil der SenseHat in Normalposition negative Zahlen anzeigt | ||
+ | lastPos = ((ysense * -10) + 350, (xsense * -10) - 200) | ||
+ | pygame.draw.circle(screen, | ||
+ | pygame.display.update() | ||
+ | pygame.time.delay(100) | ||
+ | |||
+ | # Bedingung wird erfüllt, wenn Malfenster geschlossen wird | ||
+ | if event.type == pygame.QUIT: | ||
+ | raise StopIteration | ||
+ | # führt die Events aus | ||
+ | manager.process_events(event) | ||
+ | # aktualisiert den Zustand der Buttons | ||
+ | manager.update(timeDelta) | ||
+ | |||
+ | # die Änderungen im Fenster werden in Pygame verarbeitet | ||
+ | screen.blit(screen, | ||
+ | manager.draw_ui(screen) | ||
+ | clock.tick(60) | ||
+ | |||
+ | pygame.display.update() | ||
+ | |||
+ | except StopIteration: | ||
+ | pass | ||
+ | sense.clear() | ||
+ | screenshot.blit(sub, | ||
+ | |||
+ | # Ordner " | ||
+ | pygame.image.save(screenshot, | ||
+ | print(" | ||
+ | # Programm wird beendet | ||
+ | pygame.mixer.music.stop() | ||
+ | pygame.quit() | ||
+ | </ | ||
+ | |||
+ | Um die Sounddateien im Malprogramm abspielen zu können, müssen sie sich im gleichen Verzeichnis neben der Python-Datei sich befinden. | ||
+ | |||
+ | ---- | ||
+ | === Sounddateien === | ||
+ | |||
+ | **Hintergrundmusik** | ||
+ | |||
+ | {{noodleSoup.mp3? | ||
+ | |||
+ | **Button1** | ||
+ | |||
+ | {{decidemp.mp3? | ||
+ | |||
+ | **Button2** | ||
+ | |||
+ | {{ding.mp3? | ||
+ | |||
+ | **Button3** | ||
+ | |||
+ | {{woosh.mp3? | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Quellen ===== | ||
+ | |||
+ | **Fritzing-Quellen** | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | **Dokumentationen** | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | **Programme** | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | **Codebeispiele** | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | **Soundquellen** | ||
+ | |||
+ | [[http:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | **Andere Quellen** | ||
+ | |||
+ | [[http:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | |||