Arduino Projekt: Pong Spiel: Unterschied zwischen den Versionen

Aus HSHL Mechatronik
Zur Navigation springen Zur Suche springen
Keine Bearbeitungszusammenfassung
Zeile 15: Zeile 15:


==Benötigte Materiallien==
==Benötigte Materiallien==
{| class="wikitable"
{| class="wikitable"
|+ style = "text-align: left"| Tabelle 1: Materialliste
|+ style = "text-align: left"| Tabelle 1: Materialliste
Zeile 54: Zeile 53:


== Aufbau Schaltung ==
== Aufbau Schaltung ==
[[Datei:Schaltung_Pong.png|500px|thumb|right|Abb.4 Schaltung Pong Spiel]]
[[Datei:Schaltung_Pong.png|500px|thumb|right|Abb.4 Schaltung Pong Spiel]]
In Abb. 4 wird die Schaltung für das Projekt "Arduino Pong Spiel" dargestellt.<br>
In Abb. 4 wird die Schaltung für das Projekt "Arduino Pong Spiel" dargestellt.<br>
Zeile 60: Zeile 58:


==Programmierung==
==Programmierung==
Es ist wichtig, die [[Programmierrichtlinien Einsteiger|['''Programmierrichtlinien''']]] beim Programmieren einzuhalten.<br><br>
Es ist wichtig, die [[Programmierrichtlinien Einsteiger|['''Programmierrichtlinien''']]] beim Programmieren einzuhalten.<br>
 
----
===1) Bibliotheken einfügen===
=== Bibliotheken einfügen===
Downloade die Bibliotheken für das OLED Display[https://github.com/adafruit/Adafruit_SSD1306 ''' [SSD10306]'''] und [https://github.com/adafruit/Adafruit-GFX-Library '''[GFX]'''].<br>
Downloade die Bibliotheken für das OLED Display[https://github.com/adafruit/Adafruit_SSD1306 ''' [SSD10306]'''] und [https://github.com/adafruit/Adafruit-GFX-Library '''[GFX]'''].<br>


Zeile 76: Zeile 74:
|-
|-
|
|
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">
// Benötigte Bibliotheken
// Benötigte Bibliotheken
#include <SPI.h>
#include <SPI.h>
Zeile 85: Zeile 83:
|}
|}


===2) Initialisierung Arduino===
=== Initialisierung Arduino===
'''2.1 Taster initialisieren'''<br>
'''1. Taster initialisieren'''<br>
Zuerst müssen allen vier Tastern einen Pin am Arduino zugewiesen werden, diese kann man beliebig an den digitalen Schnittstellen anschließen.<br>
Zuerst müssen allen vier Tastern einen Pin am Arduino zugewiesen werden, diese kann man beliebig an den digitalen Schnittstellen anschließen.<br>
Danach werden die Pins mit [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(Pulsierende_LED)#pinMode() '''<code>pinMode();</code>'''] und [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(Arduino_LED_W%C3%BCrfel)#digitalWrite() '''<code>digitalWrite();'''</code>] initialisiert.
Danach werden die Pins mit [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(Pulsierende_LED)#pinMode() '''<code>pinMode();</code>'''] und [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(Arduino_LED_W%C3%BCrfel)#digitalWrite() '''<code>digitalWrite();'''</code>] initialisiert.
Zeile 95: Zeile 93:
|-
|-
|       
|       
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">
/* Taster PINS */
/* Taster PINS */
const char UP_BUTTON = 2;
const char UP_BUTTON = 2;
Zeile 121: Zeile 119:
|}
|}


'''2.2 OLED Display''' <br>
'''2. OLED Display''' <br>
Um das OLED Display zu initialisieren, wird die Bibliothek Adafruit_SSD1306 benötigt.<br>
Um das OLED Display zu initialisieren, wird die Bibliothek Adafruit_SSD1306 benötigt.<br>
Hierfür nutzt man die [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(Arduino_Pong_Spiel)#OLED_Display <code>'''Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);'''</code>] Funktion.
Hierfür nutzt man die [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(Arduino_Pong_Spiel)#OLED_Display <code>'''Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);'''</code>] Funktion.
Zeile 130: Zeile 128:
|-
|-
|       
|       
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">
/* Deklaration Display, Verbindung zum I2C (SDA, SCL pins) */
/* Deklaration Display, Verbindung zum I2C (SDA, SCL pins) */
const char OLED_RESET; // Reset Pin
const char OLED_RESET; // Reset Pin
Zeile 137: Zeile 135:
|}
|}


'''2.3 Variablen''' <br>
'''3. Variablen''' <br>
Auch können vorab Variablen bestimmt werden, die für die Programmierung benötigt werden.<br>
Auch können vorab Variablen bestimmt werden, die für die Programmierung benötigt werden.<br>
* Die '''Größe des Displays''' und die '''Ball Rate'''<br>
* Die '''Größe des Displays''' und die '''Ball Rate'''<br>
Zeile 150: Zeile 148:
|-
|-
|       
|       
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">
const unsigned char BALL_RATE = 16;           
const unsigned char BALL_RATE = 16;           
const unsigned char PADDLE_HEIGHT = 25;
const unsigned char PADDLE_HEIGHT = 25;
Zeile 161: Zeile 159:
|}
|}


'''2.4 Position vom Ball, Paddle und Spieler auf dem Display festlegen''' <br>
'''4. Position vom Ball, Paddle und Spieler auf dem Display festlegen''' <br>
* Benötigte Postionen sind: '''Ball, Spieler 1 (Player) und Spieler 2 (Player_two)'''.<br>
* Benötigte Postionen sind: '''Ball, Spieler 1 (Player) und Spieler 2 (Player_two)'''.<br>
* Benötigt wird eine update Variablen, um den Ball zu bewegen.<br>
* Benötigt wird eine update Variablen, um den Ball zu bewegen.<br>
Zeile 171: Zeile 169:
|-
|-
|       
|       
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">
unsigned char Ball_x = 64, Ball_y = 32;                   
unsigned char Ball_x = 64, Ball_y = 32;                   
unsigned char Ball_dir_x = 1, Ball_dir_y = 1;
unsigned char Ball_dir_x = 1, Ball_dir_y = 1;
Zeile 186: Zeile 184:
|}
|}


===3) Display hochfahren===
=== Display hochfahren===
Um später zu sehen, wo man welche Objekte platziert hat, muss das Display hochgefahren werden.<br>
Um später zu sehen, wo man welche Objekte platziert hat, muss das Display hochgefahren werden.<br>
Zusätzlich wird beim Start vom Display ein Timer gesetzt, dieser wird für die Bewegung vom Ball benötigt.<br>
Zusätzlich wird beim Start vom Display ein Timer gesetzt, dieser wird für die Bewegung vom Ball benötigt.<br>
Zeile 196: Zeile 194:
|-
|-
|       
|       
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">
void setup() {
void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
Zeile 214: Zeile 212:
|}
|}


'''3.1 Display Spielname anzeigen''' <br>
'''1 Display Spielname anzeigen''' <br>
Als optionale Zusatzaufgabe können Sie den Namen '''Pong Spiel''' auf dem Display anzeigen lassen.<br>
Als optionale Zusatzaufgabe können Sie den Namen '''Pong Spiel''' auf dem Display anzeigen lassen.<br>


Zeile 224: Zeile 222:
|-
|-
|       
|       
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">
/* Pong Spiel Namen anzeigen */
/* Pong Spiel Namen anzeigen */
   display.setTextSize(2);
   display.setTextSize(2);
Zeile 236: Zeile 234:
|}
|}


===4) Display Punkteanzeige===
=== Display Punkteanzeige===
Um die Punktanzeige ins Spiel mit einzubringen, werden zwei Methoden benötigt.<br>
Um die Punktanzeige ins Spiel mit einzubringen, werden zwei Methoden benötigt.<br>
* Die erste Methode soll die Zahlen auf dem Display anzeigen.<br>
* Die erste Methode soll die Zahlen auf dem Display anzeigen.<br>
Zeile 248: Zeile 246:
|-
|-
|       
|       
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">


/* Punkteanzeigen */
/* Punkteanzeigen */
Zeile 273: Zeile 271:
|}
|}


===5) Bewegter Ball===
=== Bewegter Ball===
Damit der Ball sich auf dem Display bewegt, benötigt man eine '''Rechenfunktion'''.<br>
Damit der Ball sich auf dem Display bewegt, benötigt man eine '''Rechenfunktion'''.<br>


Zeile 283: Zeile 281:
|-
|-
|
|
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">
void loop() {
void loop() {
   unsigned long time = millis();              // Zeit-Variable
   unsigned long time = millis();              // Zeit-Variable
Zeile 295: Zeile 293:
|}
|}


'''5.1 Wände erkennen''' <br>
'''1. Wände erkennen''' <br>
Damit der Ball wie gewünscht von den Wänden abprallt, müssen die Wände mit einer [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(Pulsierende_LED)#if-Bedingung <code>'''if-Bedingung()'''</code>] erkannt werden.<br>
Damit der Ball wie gewünscht von den Wänden abprallt, müssen die Wände mit einer [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(Pulsierende_LED)#if-Bedingung <code>'''if-Bedingung()'''</code>] erkannt werden.<br>
* Wenn der Ball auf eine Wand trifft, muss die Richtung vom Ball geändert werden.<br>
* Wenn der Ball auf eine Wand trifft, muss die Richtung vom Ball geändert werden.<br>
Zeile 307: Zeile 305:
|-
|-
|
|
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">
  if (time > Ball_update) {
  if (time > Ball_update) {
     /* Neue Ballposition */
     /* Neue Ballposition */
Zeile 345: Zeile 343:
|}
|}


'''5.2 Paddel erkennen''' <br>
'''2. Paddel erkennen''' <br>
Auch muss der Ball, wenn er den Schläger berührt, seine Richtung ändern.<br>
Auch muss der Ball, wenn er den Schläger berührt, seine Richtung ändern.<br>


Zeile 355: Zeile 353:
|-
|-
|
|
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">
  /* Checkt, ob der Spieler 1 Paddel getroffen wurde */
  /* Checkt, ob der Spieler 1 Paddel getroffen wurde */
  if (New_x == PLAYER_X && New_y >= Player_y && New_y <= Player_y + PADDLE_HEIGHT) {
  if (New_x == PLAYER_X && New_y >= Player_y && New_y <= Player_y + PADDLE_HEIGHT) {
Zeile 370: Zeile 368:
|}
|}


'''5.3 Neue Ballposition anzeigen''' <br>
'''3. Neue Ballposition anzeigen''' <br>
Nun kann sich der Ball bewegen, muss aber noch auf dem Display als Pixel angezeigt werden und die alten Pixel wieder gelöscht werden.<br>
Nun kann sich der Ball bewegen, muss aber noch auf dem Display als Pixel angezeigt werden und die alten Pixel wieder gelöscht werden.<br>
Auch müssen die neuen Variablen übertragen werden auf die alten, um weitere Abläufe zu ermöglichen.<br>
Auch müssen die neuen Variablen übertragen werden auf die alten, um weitere Abläufe zu ermöglichen.<br>
Zeile 381: Zeile 379:
|-
|-
|
|
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">
   display.drawPixel(Ball_x, Ball_y, BLACK);
   display.drawPixel(Ball_x, Ball_y, BLACK);
   display.drawPixel(New_x, New_y, WHITE);
   display.drawPixel(New_x, New_y, WHITE);
Zeile 393: Zeile 391:
|}
|}


===6) Boolean Taster===
=== Boolean Taster===
Ich habe mich dafür entschieden, mit einem [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(Arduino_Pong_Spiel)#bool <code>'''bool'''</code>] zu programmieren, um die Taster abzufragen und falsche Eingaben zu überprüfen.<br>
Ich habe mich dafür entschieden, mit einem [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(Arduino_Pong_Spiel)#bool <code>'''bool'''</code>] zu programmieren, um die Taster abzufragen und falsche Eingaben zu überprüfen.<br>


Zeile 406: Zeile 404:
|-
|-
|
|
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">


bool update = false;                          // Ein bool enthält einen von zwei Werten, true oder false
bool update = false;                          // Ein bool enthält einen von zwei Werten, true oder false
Zeile 427: Zeile 425:
|}
|}


===7) Paddel Spieler===
=== Paddel Spieler===
Der letzte Schritt ist, die Schläger mit den Tastern steuerbar zu machen.<br>
Der letzte Schritt ist, die Schläger mit den Tastern steuerbar zu machen.<br>
Diese dürfen aber nicht aus dem Display gelangen.<br>
Diese dürfen aber nicht aus dem Display gelangen.<br>
Zeile 440: Zeile 438:
|-
|-
|
|
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">
/* Spieler 1 Paddel */
/* Spieler 1 Paddel */
   display.drawFastVLine(PLAYER_X, Player_y, PADDLE_HEIGHT, BLACK);
   display.drawFastVLine(PLAYER_X, Player_y, PADDLE_HEIGHT, BLACK);
Zeile 474: Zeile 472:
|}
|}


==Musterlösung==  
== Musterlösung ==  
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
| <strong>Lösung Code &thinsp;</strong>
| <strong>Lösung Code &thinsp;</strong>
|-
|-
|       
|       
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:small">
/* Benötigte Bibliotheken */
/* Benötigte Bibliotheken */
#include <SPI.h>
#include <SPI.h>

Version vom 26. August 2023, 13:26 Uhr

Abb. 1: Pong Spiel

Autor: Justin Frommberger

Aufgabenstellung

Das Ziel dieses Projektes ist eigenes Pong spiel umzusetzen.

  • Ein Punkt (Ball) bewegt sich auf dem Bildschirm hin und her.
  • Jeder der beiden Spieler steuert einen senkrechten Strich (Schläger), den er mit zwei Tastern nach oben und unten steuern kann.
  • Lässt man den „Ball“ am „Schläger“ vorbei und berührt die Wand, erhält der Gegner einen Punkt.

⇒ Für den Fall, dass kein Arduino zur Verfügung steht, kann dieser Online Arduino verwendet werden. [klicken]


[Abb. 2: UML]

Benötigte Materiallien

Tabelle 1: Materialliste
Nr. Anz. Beschreibung Bild
1 Funduino Arduino UNO R3
1 USB A zu USB B
14+ Jumperkabel, männlich/männlich
1 Steckbrett
4 Taster
1 0.96 I2C OLED Display

Vorab wichtig zu wissen!

Abb. 3: OLED Display

OLED Display:

Beim UNO R3 gibt es dafür oberhalb des Pin 13 einen SDA und SCL Pin, alternativ können auch die analogen Pins A4 (SDA) und A5 (SCL) verwendet werden.

Tabelle 2: OLED Display Pins
VCC Pin für die Spannungsversorgung, anzuschließen an den 5V Pin des Mikrocontrollers
GND Ground-Pin, anzuschließen an den GND Pin des Mikrocontrollers
SDA Überträgt Daten oder Adressen.
SCL Überträgt den Takt

Aufbau Schaltung

Abb.4 Schaltung Pong Spiel

In Abb. 4 wird die Schaltung für das Projekt "Arduino Pong Spiel" dargestellt.
Bevor mit der Programmierung begonnen werden kann, muss die Schaltung des Projekts aufgebaut werden.

Programmierung

Es ist wichtig, die [Programmierrichtlinien] beim Programmieren einzuhalten.


Bibliotheken einfügen

Downloade die Bibliotheken für das OLED Display [SSD10306] und [GFX].

Benötigt wird:

  1. Kommunikation zum I2C/TWI Gerät. Wire.h
  2. Kommunikation mit dem SPI Gerät. SPI.h
  3. Adafruit GFX Grafik. Adafruit_GFX.h
  4. 128x64 and 128x32 OLEDs Displays. Adafruit_SSD1306.h

[Quelltext 1: Pong.ino]

Initialisierung Arduino

1. Taster initialisieren
Zuerst müssen allen vier Tastern einen Pin am Arduino zugewiesen werden, diese kann man beliebig an den digitalen Schnittstellen anschließen.
Danach werden die Pins mit pinMode(); und digitalWrite(); initialisiert.

[Quelltext 2: Pong.ino]

2. OLED Display
Um das OLED Display zu initialisieren, wird die Bibliothek Adafruit_SSD1306 benötigt.
Hierfür nutzt man die Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); Funktion.

[Quelltext 3: Pong.ino]

3. Variablen
Auch können vorab Variablen bestimmt werden, die für die Programmierung benötigt werden.

  • Die Größe des Displays und die Ball Rate
  • Zwei Variablen für eine Punkteanzeige
  • BALL_RATE ist die Rate in Millisekunden, mit der der Ball aktualisiert werden soll.
    • Höhere Zahl, langsamerer Ball
    • Niedrigere Zahl, schnellerer Ball

[Quelltext 4: Pong.ino]

4. Position vom Ball, Paddle und Spieler auf dem Display festlegen

  • Benötigte Postionen sind: Ball, Spieler 1 (Player) und Spieler 2 (Player_two).
  • Benötigt wird eine update Variablen, um den Ball zu bewegen.
  • Dieser Werte können nach Geschmack angepasst werden.

[Quelltext 5: Pong.ino]

Display hochfahren

Um später zu sehen, wo man welche Objekte platziert hat, muss das Display hochgefahren werden.
Zusätzlich wird beim Start vom Display ein Timer gesetzt, dieser wird für die Bewegung vom Ball benötigt.
Benötigt wird: display.display(); und mills(); zum Zeitauslesen.

[Quelltext 6: Pong.ino]

1 Display Spielname anzeigen
Als optionale Zusatzaufgabe können Sie den Namen Pong Spiel auf dem Display anzeigen lassen.

Tipp: Hierfür werden die display.set(); und display.println(); Funktionen benötigt.

[Quelltext 7: Pong.ino]

Display Punkteanzeige

Um die Punktanzeige ins Spiel mit einzubringen, werden zwei Methoden benötigt.

  • Die erste Methode soll die Zahlen auf dem Display anzeigen.
  • Die zweite Methode soll die erstellen Zahlen wieder löschen, um das nächste Ergebnis korrekt anzuzeigen.

Tipp: Hierfür werden die display.set(); und display.println(); Funktionen benötigt.

[Quelltext 8: Pong.ino]

Bewegter Ball

Damit der Ball sich auf dem Display bewegt, benötigt man eine Rechenfunktion.

Tipp: Rechne den X und Y Wert + 1 und erstelle eine neue Variable.

[Quelltext 9: Pong.ino]

1. Wände erkennen
Damit der Ball wie gewünscht von den Wänden abprallt, müssen die Wände mit einer if-Bedingung() erkannt werden.

  • Wenn der Ball auf eine Wand trifft, muss die Richtung vom Ball geändert werden.
  • Zusätzlich soll der Spieler ein Punkt bekommen, wenn die Linke oder Rechte Wand berührt wurde.

Tipp: Wenn die X oder Y Position von der Wand erreicht wurde, negiere den Addierer.

[Quelltext 10: Pong.ino]

2. Paddel erkennen
Auch muss der Ball, wenn er den Schläger berührt, seine Richtung ändern.

Tipp: Postion von den Paddeln muss kleiner sein als die Postion vom Ball.

[Quelltext 11: Pong.ino]

3. Neue Ballposition anzeigen
Nun kann sich der Ball bewegen, muss aber noch auf dem Display als Pixel angezeigt werden und die alten Pixel wieder gelöscht werden.
Auch müssen die neuen Variablen übertragen werden auf die alten, um weitere Abläufe zu ermöglichen.

Tipp: Nutze display.drawPixel(Name, Name, BLACK/WHITE);.

[Quelltext 12: Pong.ino]

Boolean Taster

Ich habe mich dafür entschieden, mit einem bool zu programmieren, um die Taster abzufragen und falsche Eingaben zu überprüfen.

Tipp:

  1. Neue Variablen für die Taster mit bool initialisieren.
  2. Die alten und neuen Variablen auf LOW setzen, um die Taster schalten zu können.
  3. Wenn die bool Variable = true ist, soll das Display aktualisiert werden mit display.display();.

[Quelltext 13: Pong.ino]

Paddel Spieler

Der letzte Schritt ist, die Schläger mit den Tastern steuerbar zu machen.
Diese dürfen aber nicht aus dem Display gelangen.

Tipp:

  1. Der Ablauf ist ähnlich wie beim Ball, nur werden die if-Bedingung von den Tastern betätigt.
  2. Zusätzlich müssen noch die Schläger auf dem Display angezeigt werden, mit der Funktion display.drawFastVLine(PLAYER_X, Player_y, PADDLE_HEIGHT, BLACK);.

[Quelltext 14: Pong.ino]

Musterlösung

Quelle: Link



→ zurück zum Hauptartikel: BA: Arduino-Projekte für die Lehre