Arduino Projekt: Türsicherheitssystem: Unterschied zwischen den Versionen

Aus HSHL Mechatronik
Zur Navigation springen Zur Suche springen
Keine Bearbeitungszusammenfassung
Keine Bearbeitungszusammenfassung
 
(209 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
[[Kategorie:Arduino: Projekt]]
[[Kategorie:Arduino: Projekt]]
[[Datei:PongGae neu.gif|thumb|right|600px|Abb. 1: Pong Spiel]]
[[Datei:TastFeldXgif.gif|thumb|right|700px|Abb. 1: Türsicherheitssystem]]
 
'''Autor:''' Justin Frommberger<br>
'''Autor:''' Justin Frommberger<br>


== '''Aufgabenstellung''' ==
==Aufgabenstellung==
Ziel von dem Projekt ist eine Tür Sicherheitssystem zu simulieren.<br>
* Ziel des Projektes ist, ein Türsicherheitssystem zu simulieren.
Die Aufgabe ist mit einem vier stelligen Zahlen Code die Tür zu öffnen.
* Die Aufgabe besteht darin, die Tür mit einem vierstelligen Zahlencode zu öffnen (LED leuchtet grün).
* Wird der Code 3-mal falsch eingegeben, ertönt ein Warnsignal und die LED leuchtet rot.
* Alle Eingaben müssen auf dem seriellen Monitor angezeigt werden.<br>


== '''Benötigte Software''' ==
⇒ Für den Fall, dass '''kein Arduino''' zur Verfügung steht oder '''Materialien''' nicht vorhanden sind. Kann dieser '''webbasierter Arduino Emulator''' verwendet werden. [https://wokwi.com/projects/new/arduino-uno [klicken]]
*Aktuellste '''Arduino IDE''' mit der Version für ihren PC. [https://www.arduino.cc/en/software/ (Download link)]
<br><br>
*Bibliotheken für das 4x4 Tastenfeld downloaden: [https://github.com/Chris--A/Keypad (Link)]
[[Datei:UML_Tür.png|600px]]<br>
** Klicke oben rechts in GitHub auf Code und dann downloade die Zip-Datei.
[Abb. 2: UML]
** Um die Zip-Datei in ihre Arduino Bibliothek einzubinden, folgen diese Schritte: [https://ardutronix.de/anleitung-library-in-arduino-ide-installieren-und-einbinden/ (Link)]


== '''Benötigte Materiallien''' ==
== Benötigte Materialien ==
'''Tabelle 1: Materialliste'''
{| class="wikitable"
{| class="wikitable"
|+ style = "text-align: left"|
|+ style = "text-align: left"| Tabelle 1: Materialliste
|-
|-
 
! Nr. !! Anz.    !! Beschreibung !! Bild
! Nr. !! Anz.    !! Beschreibung !! Bild !! Pos. !! Anz.    !! Beschreibung !!Bild
|-
|-
|<big><big>&#9312;</big></big>  || 1 || [[Arduino|Funduino Arduino UNO R3]] ||[[Datei:Arduino Uno R3.jpg|ohne|100px|]]
|<big><big>&#9312;</big></big>  || 1 || [[Arduino|Funduino Arduino UNO R3]] ||[[Datei:Arduino Uno R3.jpg|ohne|100px|]]
|<big><big>&#9313;</big></big>  || viele || Jumper Kabel, männlich/männlich||[[Datei:R19-F-2-2.jpg|ohne|100px|]]
|-
|-
|<big><big>&#9313;</big></big>  || 1 || Typ 2 ||[[Datei:Arduino_Kabel.png|ohne|100px|]]
|-
|<big><big>&#9314;</big></big>  || 20+ || Jumperkabel, männlich/männlich||[[Datei:R19-F-2-2.jpg|ohne|100px|]]
|-
|<big><big>&#9315;</big></big>  || 1 || [[Steckbrett]]||[[Datei:Steckbrett1.png|ohne|100px|]]
|-
|-
|<big><big>&#9314;</big></big>  || 1 || [[Steckbrett]] ||[[Datei:R12-A-9-1.jpg|ohne|100px|]]
|<big><big>&#9316;</big></big>  || 2 || LED Rot/Grün||[[Datei:R20-F-1-1.jpg|ohne|100px|]]
|<big><big>&#9315;</big></big>  || 4 || Taster||[[Datei:R12-KT-6.jpg|ohne|100px|]]
|-
|-
|<big><big>&#9317;</big></big>  || 3 || Widerstand <br>120&thinsp;Ω||[[Datei:Widerstaende.jpg|ohne|100px|]]
|-
|<big><big>&#9318;</big></big>  || 1 || [[Servomotor SG90|TowerPro SG90 Servomotor]]||[[Datei:R19-F-2-1.jpg|ohne|100px|]]
|-
|<big><big>&#9319;</big></big>  || 1 || [[Piezo Lautsprecher]]||[[Datei:R6-B-0-1.jpg|ohne|100px|]]
|-
|<big><big>&#9320;</big></big>  || 1 || [[4x4 Tastenfeld]]||[[Datei:4x4_Tastenfeld.png|ohne|100px|]]
|-
|-
|<big><big>&#9316;</big></big>  || 1 || 0.96 I2C OLED Display||[[Datei:OLED 0.96.png|ohne|100px|]]
|}
|}


== '''Vorab wichtig zu wissen!''' ==
== Vorab wichtig zu wissen ==
[[Datei:OLED 0.96.png|thumb|rigth|250px|Abb. 2: OLED Display]]
[[Datei:Anode Kathode.png |thumb|rigth|130px|Abb. 3: LED]]
'''Arduino Uno R3:'''
* Der Arduino besitzt unterschiedliche [[Arduino_UNO:_Board_Anatomie | Schnittstellen]], weil der Arduino ein digitaler Mikrocontroller ist, kann er nur <nowiki>&thinsp;</nowiki>5&thinsp;Volt ausgeben oder annehmen.
* Bei einer konstanten <nowiki>&thinsp;</nowiki>5&thinsp;V Spannung, ist die LED immer gleich hell, so ist das Ziel die Spannung zur LED zu reduzieren.
* Dafür wird eine Pulsweitenmodulation (PWM) Schnittstelle benötigt, denn bei den anderen Schnittstellen ist dies nicht möglich.
* Bei einem geringen PWM-Wert ist das <nowiki>&thinsp;</nowiki>5&thinsp;V Signal kaum noch vorhanden und bei einem hohen PWM-Wert liegt das <nowiki>&thinsp;</nowiki>5&thinsp;V Signal nahezu durchgehend am Pin an.
* Durch die PWM Schnittstelle kann nun die LED unterschiedlich hell leuchten, da die Spannung anpassbar ist.
* Die [[https://de.wikipedia.org/wiki/Pulsdauermodulation PWM]] Schnittstellen sind ganz einfach zu erkennen an diesem Zeichen (~)


'''Steckbrett:'''<br>
===Servomotor Kabel===
Erklärung zum Arbeiten mit einem Steckbrett [[Steckbrett | (klicken!)]]
{| class="wikitable"
 
|+ style = "text-align: left"| Tabelle 2: Servomotor Farberkennung
'''OLED Display:'''<br>
|-
Das Display verfügt über vier Pins:
| '''Schwarz oder Braun'''|| Masse (GND)<br>
* '''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
|'''Rot''' || VCC/+<nowiki>&thinsp;</nowiki>5&thinsp;V<br>
* '''SDA und SCL''': mit den dafür vorgesehenen Kontakten am Mikrocontroller
** 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.
 
== '''Aufbau Schaltung''' ==
[[Datei:Schaltung_Pong.png|500px|thumb|right|Abb.3 Schaltung Pong Spiel]]
In Abb. 3 wird die Schaltung für das Projekt '''" Arduino Pong Spiel"''' dargestellt.
 
=='''Arduino Datei erstellen'''==
Erstellen der ersten '''Arduino Datei''' ([https://wiki.hshl.de/wiki/index.php/Erste_Schritte_mit_der_Arduino_IDE Link zum Tutorial]).
 
=='''Programmierung Vorkenntnisse'''==
*Kenntnisse in den '''Programmierrichtlinien''' für die Erstellung von Software. ([[Programmierrichtlinien Einsteiger|Link]])<br>
*Grundkenntnisse von Projekt '''1-5''' verstanden haben. [https://wiki.hshl.de/wiki/index.php/Kategorie:Arduino:_Projekt (Link)]
*Grundkenntnisse für das Projekt '''"Arduino Pong Spiel"''' verstehen. ([[Grundkenntnisse Programmierung (Arduino Pong Spiel) |Link]])
 
=='''Programmierung Anleitung'''==
Nachdem alle Schritte abgeschlossen sind, kann mit der Programmierung des Projektes gestartet werden.
 
===1) Bibliotheken einfügen===
Zuerst muss, für das Projekt Pong Spiel die heruntergeladenen Bibliotheken eingefügt werden.<br>
 
'''Benötigt wird: '''
# Kommunikation zum I2C/TWI Gerät.
# Kommunikation mit dem SPI Gerät.
# Adafruit GFX Grafik.
# 128x64 and 128x32 OLEDs Displays.
 
'''Quelltext 1:''' <code>Pong.ino</code>
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
| <strong>Lösung &thinsp;</strong>
|-
|-
|
| '''Organe, Gelb oder Weiß'''|| PWM-Signal
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
// Benötigte Bibliotheken
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
</syntaxhighlight>
|}
|}


===2) Initialisierung Arduino===
===Tastenfeld===
Nachdem nun die Bibliotheken hinzugefügt wurden, folgt nun die Initialisierung der benötigten Pins und Variablen.<br>
Definition Tastenfeld [https://wiki.hshl.de/wiki/index.php/4x4_Tastenfeld [klicken]]
Wichtig ist, sich vorab Gedanken zu machen, wie man diese anordnet. (siehe Abbildung 3)


====2.1) Taster: ====
== Aufbau Schaltung ==
Zuerst müssen allen vier Tastern einen Pin am Arduino zugewiesen werden, diese kann man beliebig an den digitalen Schnittstellen anschließen.<br>
[[Datei:Tür_Schaltplan.png|550px|thumb|right|Abb.4 Schaltung Tür Sicherheitssystem]]
Danach werden die Pins mit <code>pinMode();</code> und <code>digitalWrite();</code> initialisiert.
In Abbildung 4 wird die Schaltung für das Projekt '''"Tür Sicherheitssystem"''' dargestellt.<br>
Bevor mit der Programmierung begonnen werden kann, muss die Schaltung des Projekts aufgebaut werden.


'''Quelltext 2:''' <code>Pong.ino</code>
==Programmierung==
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
Es ist wichtig, die [[Programmierrichtlinien Einsteiger|['''Programmierrichtlinien''']]] beim Programmieren einzuhalten.<br><br>
| <strong>Lösung &thinsp;</strong>
Wenn Sie Fragen zur Programmierung haben, finden Sie die Antworten in den [https://wiki.hshl.de/wiki/index.php/Kategorie:Arduino:_Projekt_Grundkenntnisse ['''Grundkenntnissen''']].
|-
<br>
|     
----
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
=== Bibliotheken einfügen===
/* Taster PINS */
Laden Sie für das Projekt die [https://github.com/Chris--A/Keypad '''Bibliothek'''] für das Tastenfeld 4x4 herunter.<br>
const char UP_BUTTON = 2;
Benötigt werden die Bibliotheken <code>'''Servo.h'''</code> und <code>'''Keypad.h'''</code>.
const char DOWN_BUTTON = 3;
const char UP_BUTTON_TWO = 4;
const char DOWN_BUTTON_TWO = 5;
 
void setup() {
/* Taster Initialisieren */
pinMode(UP_BUTTON, INPUT);
pinMode(DOWN_BUTTON, INPUT);               
digitalWrite(UP_BUTTON, HIGH);
digitalWrite(DOWN_BUTTON, HIGH);
   
/* Taster zwei */
pinMode(UP_BUTTON_TWO, INPUT);
pinMode(DOWN_BUTTON_TWO, INPUT);               
digitalWrite(UP_BUTTON_TWO, HIGH);
digitalWrite(DOWN_BUTTON_TWO, HIGH);
 
void loop() {
//Später
}
</syntaxhighlight>
|}


====2.2) OLED Display====
['''Quelltext 1: ''' <code>TSS.ino</code>]
Um das OLED Display zu initialisieren, wird die Bibliothek Adafruit_SSD1306 benötigt.<br>
Hierfür nutzt man die <code>Adafruit_SSD1306 display()</code> Funktion.
 
'''Quelltext 3:''' <code>Pong.ino</code>
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
| <strong>Lösung &thinsp;</strong>
| <strong>Lösung &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">
/* Deklaration Display, Verbindung zum I2C (SDA, SCL pins) */
/* Benötigte Bibliotheken */
const char OLED_RESET; // Reset pin
#include <Keypad.h>
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#include <Servo.h>
</syntaxhighlight>
</syntaxhighlight>
|}
|}
----


====2.3) Variablen====
=== Initialisierung Arduino ===
Auch können vorab Variablen bestimmt werden, die für die Programmierung benötigt werden.<br>
'''1. Tastenfeld initialisieren'''<br>
Wie die Größe des Displays und die Eigenschaften vom Schläger und Ball.<br>
Ziel ist es, alle benötigten Variablen für die Funktion zu definieren: <br>[https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(T%C3%BCr_Sicherheitssystem) '''<code>Keypad tastenfeld = Keypad(makeKeymap(Hexa_Keys), rowPins, colPins, ROWS, COLS);</code>''']
Zusätzlich ist geplant, eine Punkteanzeige zu entwerfen, wofür zwei Variablen benötigt werden.
* '''ROWS''' sind die Anzahl der Spalten und '''COLS''' sind die Anzahl der Zeilen. Diese werden als Variable festgelegt.
* Daraufhin müssen '''rowPins''' und '''colPins''' über eine Array-Zuweisung ihren Ziffern zugeordnet werden.
* Zum Schluss muss die '''hexaKeys''' Matrix aufgebaut werden. Hier wird jede Ziffer für das Tastenfeld festgelegt.


'''Quelltext 4:''' <code>Pong.ino</code>
['''Quelltext 2: ''' <code>TSS.ino</code>]
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
| <strong>Lösung &thinsp;</strong>
| <strong>Lösung &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">
const unsigned char PADDLE_RATE = 33;        // const: Konstant, wert bleibt unverändert
/* Tastenfeld */
const unsigned char BALL_RATE = 16;           // unsigned long: kann keine negativen Zahlen speichern
/* Größe des Keypads definieren */
const unsigned char PADDLE_HEIGHT = 25;
const byte COLS = 4; //4 Spalten
const byte ROWS = 4; //4 Zeilen


const char SCREEN_WIDTH = 128;     // OLED Display Breite
byte colPins[COLS] = {2,3,4,5}; //Definition der Pins für die 3 Spalten
const char SCREEN_HEIGHT = 64;     // OLED Display Höhe
byte rowPins[ROWS] = {6,7,8,9}; //Definition der Pins für die 4 Zeilen


unsigned int Player_one = 0, Player_two = 0;
/* Ziffern und Zeichen des Keypads festlegen */
char hexaKeys[ROWS][COLS]={
{'D','#','0','*'},
{'C','9','8','7'},
{'B','6','5','4'},
{'A','3','2','1'}
};
Keypad tastenfeld = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); //Das Keypad kann ab sofort mit "Tastenfeld" angesprochen werden
</syntaxhighlight>
</syntaxhighlight>
|}
|}


====2.4) Position vom Ball, Paddle und Spieler auf dem Display ====
'''2. Tastenfeld Variablen'''<br>
Im nächsten Schritt sollen die Postionen auf dem Display festgelegt werden.<br>
Benötigte Variablen zum:
Benötigte Postionen sind: '''Ball, Spieler 1 (Player) und Spieler 2 (CPU)'''.<br>
* Festlegen des Passwortes, jeder Buchstabe einzeln
Auch werden '''zwei update Variablen''' benötigt, um später den Ball und Schläger bewegen zu können.<br>
* Speichern der aktuell gedrückten Taste
Dieser Werte können nach Geschmack angepasst werden.
* Speichern der vier gedrückten Tasten
* Verhindern einer falschen Position bei der Eingabe


'''Quelltext 5:''' <code>Pong.ino</code>
['''Quelltext 3: ''' <code>TSS.ino</code>]
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
| <strong>Lösung &thinsp;</strong>
| <strong>Lösung &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">
unsigned char Ball_x = 64, Ball_y = 32;                 
unsigned char Ball_dir_x = 1, Ball_dir_y = 1;
 
const unsigned char CPU_X = 12;                   
unsigned char Cpu_y = 16;
 
const unsigned char PLAYER_X = 115;
unsigned char Player_y = 16;
 
unsigned long Ball_update;
unsigned long Paddle_update;


/* Variablen */
char p1='1';char p2='2';char p3='3';char p4='A'; // Vier Zeichen des Passwortes eingegeben
char taste; //Taste ist die Variable für die jeweils gedrückte Taste auf dem Tastenfeld
char c1, c2, c3, c4; // Speichern der gedrückten Tasten
byte z1=0, z2, z3, z4; // Falsche Position zuordnen wird verhindert
</syntaxhighlight>
</syntaxhighlight>
|}
|}


===3) Display hochfahren===
'''3. Motor, Buzzer und RGB initialisieren'''<br>
Um später zu sehen, wo man welche Objekte platziert hat, muss das Display hochgefahren werden.<br>
{| class="wikitable"
Zusätzlich wird beim Start vom Display ein Timer gesetzt, dieser wird für die Bewegung vom Ball benötigt.<br>
|+ style = "text-align: left"| Pins
'''Benötigt wird: ''' <code>display.display();</code> und <code>mills();</code> zum Zeitauslesen.   
 
'''Quelltext 6: ''' <code>Pong.ino</code>
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
| <strong>Lösung Code &thinsp;</strong>
|-
|-
|      
| '''LED''' || 12 und 13
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
void setup() {
  Serial.begin(9600);
 
/* Hochfahren vom Display */
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // Starte das Display       
  display.display();                    // Zeigt das Startbild vom Arduino an
  unsigned long start = millis();      // Anzahl von Ms zurück, seit Arduino-Board das aktuelle Programm gestartet hat
  delay(1000);
  display.clearDisplay();            // Löscht das Bild
 
/* Ball Timer zuweisen*/
  Ball_update = millis();
  delay(1000);
}
</syntaxhighlight>
|}
 
====3.1) Display Spielname anzeigen====
Als Zusatzaufgabe habe ich überlegt, bevor das Spiel startet den Namen '''Pong Spiel''' auf dem Display anzeigen zu lassen.<br>
Tipp: Hierfür werden die <code>display.set();</code> und <code>display.println();</code> Funktionen benötigt.
 
'''Quelltext 7: ''' <code>Pong.ino</code>
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
| <strong>Lösung &thinsp;</strong>
|-
|-
|      
| '''Motor''' || 11
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
/* Pong Spiel Namen anzeigen */
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(5, 25);
  display.println("Pong Spiel");
  display.display();
  delay(1000);
  display.clearDisplay();
</syntaxhighlight>
|}
 
===4) Display Punkteanzeige===
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 zweite Methode soll die erstellen Zahlen wieder löschen, um das nächste Ergebnis korrekt anzuzeigen.<br>
'''Tipp:''' Hierfür werden die <code>display.set();</code> und <code>display.println();</code> Funktionen benötigt.
 
'''Quelltext 8:''' <code>Pong.ino</code>
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
| <strong>Lösung &thinsp;</strong>
|-
|-
|      
| '''Buzzer''' || 10
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
 
/* Punkteanzeigen */
void drawScore() {               
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(43, 0);
  display.println(Player_one);
 
  display.setCursor(73, 0);
  display.println(Player_two);
}
/* Punkte zurücksetzten */
void eraseScore() {                             
  display.setTextSize(2);
  display.setTextColor(BLACK);
  display.setCursor(43, 0);
  display.println(Player_one);
 
  display.setCursor(73, 0);
  display.println(Player_two);
}
</syntaxhighlight>
|}
|}
⇒ [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(Pulsierende_LED)#pinMode() '''<code>pinMode();</code>''']<br>
⇒ [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(Servomotor_mit_einem_Potentiometer_steuern)#Servo.h <code>'''Servo.h'''</code>]<br>
['''Quelltext 4: ''' <code>TSS.ino</code>]


===5) Bewegter Ball===
Damit der Ball sich auf dem Display bewegt, benötigt man eine Rechenfunktion.<br>
'''Tipp:''' Rechne den X und Y Wert + 1 und erstelle eine neue Variable.
'''Quelltext 9:''' <code>Pong.ino</code>
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
| <strong>Lösung &thinsp;</strong>
| <strong>Lösung &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">
void loop() {
/* Motor */
  unsigned long time = millis();              // Zeit-Variable
Servo servoBlau; //Servomotor Definition
 
/* Neue Ballposition */
if (time > Ball_update) {
  unsigned char New_x = Ball_x + Ball_dir_x;               // (x+1)
  unsigned char New_y = Ball_y + Ball_dir_y;              // (y+1)
}
</syntaxhighlight>
|}


====5.1) Wände erkennen====
/* Buzzer */
Damit der Ball wie gewünscht von den Wänden abprallt, müssen die Wände mit einer If Abfrage erkannt werden.<br>
const byte SOUND_BUZZER = 10; // Buzzer ist an Pin 10 angeschlossen
Wenn der Ball auf eine Wand trifft, muss die Richtung vom Ball geändert werden.<br>
unsigned int sound = 500; // Frequenz von 500 Hertz
Zusätzlich soll der Spieler ein Punkt bekommen, wenn die Linke oder Rechte Wand berührt wurde.<br>
byte falscheEingabe;   // Für eine falsche Eingabe
'''Tipp: ''' Wenn die X oder Y Position von der Wand erreicht wurde, negiere den Addierer.
 
'''Quelltext 10:''' <code>Pong.ino</code>
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
| <strong>Lösung &thinsp;</strong>
|-
|
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
if (time > Ball_update) {
    /* Neue Ballposition */
    unsigned char New_x = Ball_x + Ball_dir_x;               // (x+1)
    unsigned char New_y = Ball_y + Ball_dir_y;               // (y+1)


    /* Checkt ob die verticalen Wände berüht werden */
/* RGB */
    if (New_x == 0) {                        // Wand links
const byte ROTE_LED = 12; //Rote LED ist an Pin 12 angeschlossen
      Ball_dir_x = -Ball_dir_x;             // Wechselt die Richtung
const byte GRUENE_LED = 13; //Grüne LED wird an Pin 13 angeschlossen
      New_x += Ball_dir_x + Ball_dir_x;
      eraseScore();                         // Punkt für Spieler
      Player_one += 1;
      drawScore();


    }
void setup()  
    if (New_x == 127) {                     // Wand rechts
{
      Ball_dir_x = -Ball_dir_x;            // Wechselt die Richtung
Serial.begin(9600);
      New_x += Ball_dir_x + Ball_dir_x;
      eraseScore();                       // Punkt für den Computer
      Player_two += 1;
      drawScore();
    }


    // Checkt ob die horizontalen Wände berüht werden
pinMode(ROTE_LED, OUTPUT);  //Die LEDs werden als Ausgang festgelegt
    if (New_y == 0 || New_y == 63) {
pinMode(GRUENE_LED, OUTPUT);
      Ball_dir_y = -Ball_dir_y;          // Wechselt die Richtung
      New_y += Ball_dir_y + Ball_dir_y;


    }
servoBlau.attach(11); //Der Servomotor ist an Pin 11 angeschlossen
}
}
</syntaxhighlight>
</syntaxhighlight>
|}
|}
----


====5.2) Paddel erkennen====
=== Richtige Reihenfolge der Eingabe===
Auch muss der Ball, wenn er den Schläger berührt, seine Richtung ändern.<br>
'''Wichtig''' ist, dass die Ziffern richtig eingegeben werden.
'''Tipp: ''' Postion von den Paddeln muss kleiner sein als die Postion vom Ball.
* So muss sich eine Funktion überlegt werden, welche dies ermöglicht.
* Zur Verwendung kommen nun die Variablen für die falsche Eingabe.
* Auch muss die Variable Taste ihre Werte erhalten.
* Die gedrückte Taste wird in der c1-4 Variable abgespeichert, um später das Passwort zu überprüfen.


'''Quelltext 11:''' <code>Pong.ino</code>
'''Tipp: '''
# Nachdem die erste Ziffer gedrückt wurde, öffnet sich die Eingabe für die zweite Ziffer usw.
# Benötigt wird hierfür eine [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(Pulsierende_LED)#if-Bedingung <code>'''if-Bedingung'''</code>] und eine [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(T%C3%BCr_Sicherheitssystem) <code>'''goto'''</code>] Funktion.
# Die Taste bekommt mit der Funktion <code>'''tastenfeld.getKey();'''</code> ihre Ziffer.
 
['''Quelltext 5: ''' <code>TSS.ino</code>]
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
| <strong>Lösung &thinsp;</strong>
| <strong>Lösung &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">
  /* Checkt, ob der Spieler 1 Paddel getroffen wurde */
void loop()
if (New_x == PLAYER_X && New_y >= Player_y && New_y <= Player_y + PADDLE_HEIGHT) {
{
   Ball_dir_x = -Ball_dir_x;
Anfang: // Goto Anfang
   New_x += Ball_dir_x + Ball_dir_x;
  taste = tastenfeld.getKey();
 
/* Richtige Reihenfolge des Passwortes erstellen */
  if (z1==0) // Wenn das erste Zeichen noch nicht gespeichert wurde.
  {
  c1=taste; //Unter der Variablen "C1" wird nun die aktuell gedrückte Taste gespeichert
  Serial.print("Die Taste ");
  Serial.print(c1);
  Serial.println(" wurde gedrückt");
  z1=1; z2=0; z3=1; z4=1; // Zugang zur zweiten Zeicheneingabe freischalten
  goto Anfang;
  }
  if (z2==0)
  {
  c2=taste; //Unter der Variablen "C2" wird nun die aktuell gedrückte Taste gespeichert
  Serial.print("Die Taste ");
  Serial.print(c2);
  Serial.println(" wurde gedrückt");
  z1=1; z2=1; z3=0; z4=1; // Zugang zur dritten Zeicheneingabe freischalten
  goto Anfang;
  }
 
  if (z3==0)
  {
  c3=taste; //Unter der Variablen "C3" wird nun die aktuell gedrückte Taste gespeichert
  Serial.print("Die Taste ");
  Serial.print(c3);
  Serial.println(" wurde gedrückt");
  z1=1; z2=1; z3=1; z4=0; // Zugang zur vierten Zeicheneingabe freischalten
  goto Anfang;
  }
 
  if (z4==0) // Wenn das vierte Zeichen noch nicht gespeichert wurde
  {
   c4=taste; //Unter der Variablen "C4" wird nun die aktuell gedrückte Taste gespeichert
  Serial.print("Die Taste ");
  Serial.print(c4);
  Serial.println(" wurde gedrückt");
   z1=1; z2=1; z3=1; z4=1; // Zugang zur weiteren Zeicheneingabe sperren
  }
  }
  }
/* Checkt, ob der Spieler 2 Paddel getroffen wurde */
if (New_x == CPU_X && New_y >= Cpu_y && New_y <= Cpu_y + PADDLE_HEIGHT) {
  Ball_dir_x = -Ball_dir_x;
  New_x += Ball_dir_x + Ball_dir_x;
}
}
</syntaxhighlight>
</syntaxhighlight>
|}
|}
----
=== Tür öffnen und schließen ===
* Für das Öffnen der Tür wird die Taste '''(#)''' verwendet. Um die Tür zu verriegeln, wird die Taste '''(*)''' genutzt.
* Wenn die Tür offen ist, leuchtet die LED Grün, und Rot, wenn die Tür geschlossen ist.
* Der Motor soll sich beim Schließen zu 90 Grad, beim Öffnen wiederum zu 0 Grad drehen.
* Überprüfe vor dem Öffnen, ob das Passwort korrekt eingegeben wurde.<br>


====5.3) Neue Ballposition anzeigen====
'''Tipp: '''
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>
# Benötigt werden if-Else Funktionen, die nach der bestimmten Taste abfragen und die Anweisung dann ausführen.
Auch müssen die neuen Variablen übertragen werden auf die alten, um weitere Abläufe zu ermöglichen.<br>
# Nutzen Sie Vergleichsoperatoren zum Abfragen des Passwortes.
'''Tipp: '''Nutze <code>display.drawPixel(Name, Name,BLACK/WHITE);</code>.


'''Quelltext 12:''' <code>Pong.ino</code>
['''Quelltext 6: ''' <code>TSS.ino</code>]
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
| <strong>Lösung &thinsp;</strong>
| <strong>Lösung &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">
   display.drawPixel(Ball_x, Ball_y, BLACK);
void loop()
  display.drawPixel(New_x, New_y, WHITE);
{
  Ball_x = New_x;
Anfang: // Goto Anfang
   Ball_y = New_y;
taste = tastenfeld.getKey();
 
if (taste)
  Ball_update += BALL_RATE;
{
  display.display();       // Später: update = true;   (true = display.display();
   if (taste=='*')
   
  {
    Serial.println("Tür verriegelt");
    delay(1000);
    servoBlau.write(90); //Servomotor zum Verriegeln auf 90 Grad ansteuern
    digitalWrite(ROTE_LED, HIGH);
    digitalWrite(GRUENE_LED, LOW);  
    z1=0; z2=1; z3=1; z4=1; // Zugang zur ersten Zeicheneingabe freischalten
    goto Anfang; // Damit das Zeichen "*" nicht im folgenden Abschnitt als Codeeingabe gewertet wird
  }
 
   if (taste=='#')
  {
  if (c1==p1&&c2==p2&&c3==p3&&c4==p4) //wird geprüft, ob die eingaben Codezeichen übereinstimmen
  {
    Serial.println ("Code korrekt, Schloss offen");
    servoBlau.write(0); //Servomotor zum Öffnen auf 0 Grad ansteuern.
    digitalWrite(ROTE_LED, LOW);
    digitalWrite(GRUENE_LED, HIGH);
  }
  else // ist das nicht der Fall, bleibt das Schloss gesperrt
  {
    Serial.println ("Code falsch, Schloss gesperrt");
    digitalWrite(ROTE_LED, HIGH);
    digitalWrite(GRUENE_LED, LOW);
    delay(2000);
    z1=0; z2=1; z3=1; z4=1; // Der Zugang für die erste Zeicheneingabe wird wieder freigeschaltet
    goto Anfang; // Damit das Zeichen "#" nicht im folgenden Abschnitt als Codeeingabe gewertet wird.
  }
  }
</syntaxhighlight>
</syntaxhighlight>
|}
|}
----


===6) Boolean Taster===
=== Einbrecher Warnung! ===
Ich habe mich dafür entschieden, mit einem <code>bool</code> zu programmieren, um die Taster abzufragen und falsche Eingaben zu überprüfen.<br><br>
Die Zusatzaufgabe ist, einen Buzzer ertönen zu lassen, wenn das Passwort 3-mal falsch eingegeben wurde.  
'''Tipp: '''<br>
Neue Variablen für die Taster mit <code>bool</code> initialisieren.<br>
Die alten und neuen Variablen auf <code>LOW</code> setzen, um die Taster schalten zu können.<br>
Wenn die <code>bool</code> Variable = true ist, soll das Display aktualisiert werden. (<code> display.display();</code>)


'''Quelltext 13:''' <code>Pong.ino</code>
'''Tipp: '''
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
# Bei einer falschen Eingabe wird die Variable hochgezählt.
| <strong>Lösung &thinsp;</strong>
# Wenn die Variable 3 erreicht, ertönt der Buzzer.
|-
⇒ [https://wiki.hshl.de/wiki/index.php/Grundkenntnisse_Programmierung_(USS_mit_Buzzer)#tone() <code>'''tone();'''</code>]<br>
|
<syntaxhighlight lang="C" style="border: none; background-color: #EFF1C1; font-size:14px">
void loop() {
bool update = false;                          // Ein bool enthält einen von zwei Werten, true oder false
 
  static bool Up_state = false;
  static bool Down_state = false;
  static bool Up_state_two = false;
  static bool Down_state_two = false;
 
  Up_state |= (digitalRead(UP_BUTTON) == LOW);                  // Taster auslesen
  Down_state |= (digitalRead(DOWN_BUTTON) == LOW);
  Up_state_two |= (digitalRead(UP_BUTTON_TWO) == LOW);
  Down_state_two |= (digitalRead(DOWN_BUTTON_TWO) == LOW);
 
 
if (update)                      // Wenn Variable = true wird display.display(); ausgeführt
    display.display();
}
</syntaxhighlight>
|}
===7) Paddel Spieler===
Der letzte Schritt ist, die Schläger mit den Tastern steuerbar zu machen.<br>
Diese dürfen aber nicht aus dem Display gelangen.<br><br>
'''Tipp: '''<br>
Der Ablauf ist ähnlich wie beim Ball, nur werden die If-Anweisungen von den Tastern betätigt.<br>
Zusätzlich müssen noch die Schläger auf dem Display angezeigt werden, mit der Funktion <code>display.drawFastVLine(PLAYER_X, Player_y, PADDLE_HEIGHT, BLACK);</code>.


'''Quelltext 14:''' <code>Pong.ino</code>
['''Quelltext 7: ''' <code>TSS.ino</code>]
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
{| role="presentation" class="wikitable mw-collapsible mw-collapsed"
| <strong>Lösung &thinsp;</strong>
| <strong>Lösung &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">
void loop() {
  if (taste=='#')
/* Spieler 1 Paddel */
  {
  display.drawFastVLine(PLAYER_X, Player_y, PADDLE_HEIGHT, BLACK);
  if (c1==p1&&c2==p2&&c3==p3&&c4==p4) //wird geprüft, ob die eingaben Codezeichen übereinstimmen
  if (Up_state) {
  {
     Player_y -= 1;
    Serial.println ("Code korrekt, Schloss offen");
    servoBlau.write(0); //Servomotor zum Öffnen auf 0 Grad ansteuern.
    digitalWrite(ROTE_LED, LOW);
    digitalWrite(GRUENE_LED, HIGH);
  }
  else // ist das nicht der Fall, bleibt das Schloss gesperrt
  {
    Serial.println ("Code falsch, Schloss gesperrt");
    falscheEingabe += 1;
 
  if(falscheEingabe == 3)         // Wenn der Code 3 mal falsch eigegeben wurde
  {
     Serial.println("Besitzer wurde benachrichtigt!");
    tone(SOUND_BUZZER, Sound);
    delay(8000);
    noTone(SOUND_BUZZER);
  }
    digitalWrite(ROTE_LED, HIGH);
    digitalWrite(GRUENE_LED, LOW);
    delay(2000);
    z1=0; z2=1; z3=1; z4=1; // Der Zugang für die erste Zeicheneingabe wird wieder freigeschaltet
    goto Anfang; // Damit das Zeichen "#" nicht im folgenden Abschnitt als Codeeingabe gewertet wird.
   }
   }
  if (Down_state) {
}
    Player_y += 1;
  }
  Up_state = Down_state = false;
 
  if (Player_y < 1) Player_y = 1;                                    // Um nicht aus dem Bildschirm zu gelangen
  if (Player_y + PADDLE_HEIGHT > 63) Player_y = 63 - PADDLE_HEIGHT;
  display.drawFastVLine(PLAYER_X, Player_y, PADDLE_HEIGHT, WHITE);
 
  update = true;
 
/* Spieler 2 Paddel */
  display.drawFastVLine(CPU_X, Cpu_y, PADDLE_HEIGHT, BLACK);
  if (Up_state_two) {
    Cpu_y -= 1;                      // Paddle 1 nach unten
  }
  if (Down_state_two) {
    Cpu_y += 1;                      // Paddle 1 nach oben
  }
  Up_state_two = Down_state_two = false;
 
  if (Cpu_y < 1) Cpu_y = 1;                                        // Um nicht aus dem Bildschirm zu gelangen
  if (Cpu_y + PADDLE_HEIGHT > 63) Cpu_y = 63 - PADDLE_HEIGHT;
  display.drawFastVLine(CPU_X, Cpu_y, PADDLE_HEIGHT, WHITE);
}
</syntaxhighlight>
</syntaxhighlight>
|}
|}


== '''Musterlösung''' ==
== Musterlösung ==
 
Quelle: [https://github.com/shveytank/Arduino_Pong_Game Link]
{| 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 <Keypad.h>
#include <Wire.h>
#include <Servo.h>
#include <Adafruit_GFX.h>
                                 
#include <Adafruit_SSD1306.h>
/* Tastenfeld */
/* Größe des Keypads definieren */
const byte COLS = 4; //4 Spalten
const byte ROWS = 4; //4 Zeilen


/* Taster PINS */
byte colPins[COLS] = {2,3,4,5}; //Definition der Pins für die 3 Spalten
const char UP_BUTTON = 2;
byte rowPins[ROWS] = {6,7,8,9}; //Definition der Pins für die 4 Zeilen
const char DOWN_BUTTON = 3;
 
const char UP_BUTTON_TWO = 4;
/* Ziffern und Zeichen des Keypads festlegen */
const char DOWN_BUTTON_TWO = 5;
char hexaKeys[ROWS][COLS]={
{'D','#','0','*'},
{'C','9','8','7'},
{'B','6','5','4'},
{'A','3','2','1'}
};
Keypad tastenfeld = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); //Das Keypad kann ab sofort mit "Tastenfeld" angesprochen werden


/* Variablen */
/* Variablen */
const unsigned char PADDLE_RATE = 33;         // const: Konstant, wert bleibt unverändert
char p1='1';char p2='2';char p3='3';char p4='A'; // Vier Zeichen des Passwortes eingegeben
const unsigned char BALL_RATE = 16;           // unsigned long: kann keine negativen Zahlen speichern
char taste; //Taste ist die Variable für die jeweils gedrückte Taste auf dem Tastenfeld
const unsigned char PADDLE_HEIGHT = 25;
char c1, c2, c3, c4; // Speichern der gedrückten Tasten
 
byte z1=0, z2, z3, z4; // Falsche Position zuordnen wird verhindert
const char SCREEN_WIDTH = 128;     // OLED Display Breite
const char SCREEN_HEIGHT = 64;     // OLED Display Höhe
 
unsigned int Player_one = 0, Player_two = 0;


/* Deklaration Display, verbindung zum I2C (SDA, SCL pins) */
const char OLED_RESET = 0; // Reset pin
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


/* Motor */
Servo servoBlau; //Servomotor Definition


/* Position vom Ball, Paddle und Spieler auf dem Display */
/* Buzzer */
const byte SOUND_BUZZER = 10; // Buzzer ist an Pin 10 angeschlossen
unsigned int sound = 500;  // Frequenz von 500 Hertz
byte falscheEingabe;    // Für eine falsche Eingabe


unsigned char Ball_x = 64, Ball_y = 32;
/* RGB */
unsigned char Ball_dir_x = 1, Ball_dir_y = 1;
const byte ROTE_LED = 12; //Rote LED ist an Pin 12 angeschlossen
const byte GRUENE_LED = 13; //Grüne LED wird an Pin 13 angeschlossen


const unsigned char CPU_X = 12;
void setup()
unsigned char Cpu_y = 16;
{
Serial.begin(9600);


const unsigned char PLAYER_X = 115;
pinMode(ROTE_LED, OUTPUT);   //Die LEDs werden als Ausgang festgelegt
unsigned char Player_y = 16;
pinMode(GRUENE_LED, OUTPUT);


unsigned long Ball_update;
servoBlau.attach(11); //Der Servomotor ist an Pin 11 angeschlossen
unsigned long Paddle_update;
 
void setup() {
  Serial.begin(9600);
 
  /* Hochfahren vom Display */
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // Starte das Display
  display.display();                    // Zeigt das Startbild vom Arduino an
  unsigned long start = millis();      // Anzahl von Ms zurück, seit Arduino-Board das aktuelle Programm gestartet hat
  delay(1000);
  display.clearDisplay();            // Löscht das Bild
 
  /* Pong Spiel Namen anzeigen */
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(5, 25);
  display.println("Pong Spiel");
  display.display();
  delay(1000);
  display.clearDisplay();
 
  /* Ball Timer zuweisen*/
  Ball_update = millis();
  delay(1000);
 
  /* Taster Initialisieren */
  pinMode(UP_BUTTON, INPUT);      // Taster als INPUT festlegen
  pinMode(DOWN_BUTTON, INPUT);
  digitalWrite(UP_BUTTON, HIGH);      // Taster anschalten
  digitalWrite(DOWN_BUTTON, HIGH);
 
  /* Taster zwei */
  pinMode(UP_BUTTON_TWO, INPUT);
  pinMode(DOWN_BUTTON_TWO, INPUT);
  digitalWrite(UP_BUTTON_TWO, HIGH);
  digitalWrite(DOWN_BUTTON_TWO, HIGH);
}
}


/* Punkteanzeige */
void loop()  
void drawScore() {
{
  display.setTextSize(2);
Anfang: // Goto Anfang
  display.setTextColor(WHITE);
taste = tastenfeld.getKey();  
   display.setCursor(43, 0);
if (taste)  
   display.println(Player_one);
   {
 
   if (taste=='*')
  display.setCursor(73, 0);
  {
  display.println(Player_two);
    Serial.println("Tür verriegelt");
}
    delay(1000);
/* Punkte zurücksetzten */
    servoBlau.write(90); //Servomotor zum Verriegeln auf 90 Grad ansteuern
void eraseScore() {
    digitalWrite(ROTE_LED, HIGH);
  display.setTextSize(2);
    digitalWrite(GRUENE_LED, LOW);  
  display.setTextColor(BLACK);
    z1=0; z2=1; z3=1; z4=1; // Zugang zur ersten Zeicheneingabe freischalten
  display.setCursor(43, 0);
    goto Anfang; // Damit das Zeichen "*" nicht im folgenden Abschnitt als Codeeingabe gewertet wird
  display.println(Player_one);
  }
 
 
  display.setCursor(73, 0);
   if (taste=='#')
  display.println(Player_two);
  {
}
    if (c1==p1&&c2==p2&&c3==p3&&c4==p4) //wird geprüft, ob die Eingaben Codezeichen übereinstimmen
 
  {
 
     Serial.println ("Code korrekt, Schloss offen");
void loop() {
     servoBlau.write(0); //Servomotor zum Öffnen auf 0 Grad ansteuern.
  drawScore();
    digitalWrite(ROTE_LED, LOW);
 
    digitalWrite(GRUENE_LED, HIGH);
  bool update = false;                         // Ein bool enthält einen von zwei Werten, true oder false
  }
 
  else // ist das nicht der Fall, bleibt das Schloss gesperrt
  unsigned long time = millis();               // Zeit-Variable
  {
 
    Serial.println ("Code falsch, Schloss gesperrt");
  static bool Up_state = false;
    falscheEingabe += 1;
   static bool Down_state = false;
 
  static bool Up_state_two = false;
  if(falscheEingabe == 3)         // Wenn der Code 3-mal falsch eingegeben wurde
  static bool Down_state_two = false;
  {
 
     Serial.println("Besitzer wurde benachrichtigt!");
  Up_state |= (digitalRead(UP_BUTTON) == LOW);                  // Taster auslesen
     tone(SOUND_BUZZER, sound);
  Down_state |= (digitalRead(DOWN_BUTTON) == LOW);
     delay(8000);
  Up_state_two |= (digitalRead(UP_BUTTON_TWO) == LOW);
    noTone(SOUND_BUZZER);
  Down_state_two |= (digitalRead(DOWN_BUTTON_TWO) == LOW);
  }
 
     digitalWrite(ROTE_LED, HIGH);  
/* Neue Ballposition */
     digitalWrite(GRUENE_LED, LOW);
  if (time > Ball_update) {
     delay(2000);
     /* Neue Ballposition */
     z1=0; z2=1; z3=1; z4=1; // Der Zugang für die erste Zeicheneingabe wird wieder freigeschaltet
    unsigned char New_x = Ball_x + Ball_dir_x;              // (x+1)
     goto Anfang; // Damit das Zeichen "#" nicht im folgenden Abschnitt als Codeeingabe gewertet wird.
    unsigned char New_y = Ball_y + Ball_dir_y;               // (y+1)
 
     /* Checkt ob die verticalen Wände berüht werden */
    if (New_x == 0) {                        // Wand links
      Ball_dir_x = -Ball_dir_x;             // Wechselt die Richtung
      New_x += Ball_dir_x + Ball_dir_x;
      eraseScore();                        // Punkt für Spieler
      Player_one += 1;
      drawScore();
 
    }
    if (New_x == 127) {                    // Wand rechts
      Ball_dir_x = -Ball_dir_x;            // Wechselt die Richtung
      New_x += Ball_dir_x + Ball_dir_x;
      eraseScore();                       // Punkt für den Computer
      Player_two += 1;
      drawScore();
    }
 
    // Checkt ob die horizontalen Wände berüht werden
    if (New_y == 0 || New_y == 63) {
      Ball_dir_y = -Ball_dir_y;          // Wechselt die Richtung
      New_y += Ball_dir_y + Ball_dir_y;
 
    }
    // Checkt, ob der Spieler 1 Paddel getroffen wurde
     if (New_x == PLAYER_X && New_y >= Player_y && New_y <= Player_y + PADDLE_HEIGHT) {
      Ball_dir_x = -Ball_dir_x;
      New_x += Ball_dir_x + Ball_dir_x;
 
     }
    // Checkt, ob der Spieler 2 Paddel getroffen wurde
     if (New_x == CPU_X && New_y >= Cpu_y && New_y <= Cpu_y + PADDLE_HEIGHT) {
      Ball_dir_x = -Ball_dir_x;
      New_x += Ball_dir_x + Ball_dir_x;
    }
 
     display.drawPixel(Ball_x, Ball_y, BLACK);
     display.drawPixel(New_x, New_y, WHITE);
     Ball_x = New_x;
     Ball_y = New_y;
 
    Ball_update += BALL_RATE;
 
     update = true;               // true ~ display.display();
   }
   }
 
}
/* Spieler 1 Paddel */
 
   display.drawFastVLine(PLAYER_X, Player_y, PADDLE_HEIGHT, BLACK);
/* Richtige Reihenfolge des Passwortes erstellen */
  if (Up_state) {
   if (z1==0) // Wenn das erste Zeichen noch nicht gespeichert wurde.
    Player_y -= 1;
  {
  c1=taste; //Unter der Variablen "C1" wird nun die aktuell gedrückte Taste gespeichert
  Serial.print("Die Taste ");
  Serial.print(c1);
  Serial.println(" wurde gedrückt");
  z1=1; z2=0; z3=1; z4=1; // Zugang zur zweiten Zeicheneingabe freischalten
  goto Anfang;
   }
   }
   if (Down_state) {
    Player_y += 1;
   if (z2==0)
  {
  c2=taste; //Unter der Variablen "C2" wird nun die aktuell gedrückte Taste gespeichert
  Serial.print("Die Taste ");
  Serial.print(c2);
  Serial.println(" wurde gedrückt");
  z1=1; z2=1; z3=0; z4=1; // Zugang zur dritten Zeicheneingabe freischalten
  goto Anfang;
   }
   }
  Up_state = Down_state = false;
 
  if (Player_y < 1) Player_y = 1;                                    // Um nicht aus dem Bildschirm zu gelangen
  if (Player_y + PADDLE_HEIGHT > 63) Player_y = 63 - PADDLE_HEIGHT;
  display.drawFastVLine(PLAYER_X, Player_y, PADDLE_HEIGHT, WHITE);


   update = true;
   if (z3==0)
 
  {
/* Spieler 2 Paddel */
  c3=taste; //Unter der Variablen "C3" wird nun die aktuell gedrückte Taste gespeichert
  display.drawFastVLine(CPU_X, Cpu_y, PADDLE_HEIGHT, BLACK);
  Serial.print("Die Taste ");
  if (Up_state_two) {
  Serial.print(c3);
    Cpu_y -= 1;                       // Paddle 1 nach unten
  Serial.println(" wurde gedrückt");
  z1=1; z2=1; z3=1; z4=0; // Zugang zur vierten Zeicheneingabe freischalten
  goto Anfang;
   }
   }
   if (Down_state_two) {
 
    Cpu_y += 1;                     // Paddle 1 nach oben
   if (z4==0) // Wenn das vierte Zeichen noch nicht gespeichert wurde
  {
  c4=taste; //Unter der Variablen "C4" wird nun die aktuell gedrückte Taste gespeichert
  Serial.print("Die Taste ");
  Serial.print(c4);
  Serial.println(" wurde gedrückt");
  z1=1; z2=1; z3=1; z4=1; // Zugang zur weiteren Zeicheneingabe sperren
   }
   }
  Up_state_two = Down_state_two = false;
}
 
  if (Cpu_y < 1) Cpu_y = 1;                                        // Um nicht aus dem Bildschirm zugelangen
  if (Cpu_y + PADDLE_HEIGHT > 63) Cpu_y = 63 - PADDLE_HEIGHT;
  display.drawFastVLine(CPU_X, Cpu_y, PADDLE_HEIGHT, WHITE);
 
 
  if (update)
    display.display();
}
}


</syntaxhighlight>
</syntaxhighlight>
|}
|}
[https://funduino.de/tastenfeld-schloss Quelle]


<br>
<br>
----
----
→ zurück zum Hauptartikel: [[Konzipierung_und_Evaluierung_von_Arduino-Projekten_verschiedener_Schwierigkeitsgrade_für_die_Lehre | BA: Arduino-Projekte für die Lehre]]
'''→ zurück zum Hauptartikel: [[Konzipierung_und_Evaluierung_von_Arduino-Projekten_verschiedener_Schwierigkeitsgrade_für_die_Lehre | BA: Arduino-Projekte für die Lehre]]'''

Aktuelle Version vom 22. September 2023, 15:20 Uhr

Abb. 1: Türsicherheitssystem

Autor: Justin Frommberger

Aufgabenstellung

  • Ziel des Projektes ist, ein Türsicherheitssystem zu simulieren.
  • Die Aufgabe besteht darin, die Tür mit einem vierstelligen Zahlencode zu öffnen (LED leuchtet grün).
  • Wird der Code 3-mal falsch eingegeben, ertönt ein Warnsignal und die LED leuchtet rot.
  • Alle Eingaben müssen auf dem seriellen Monitor angezeigt werden.

⇒ Für den Fall, dass kein Arduino zur Verfügung steht oder Materialien nicht vorhanden sind. Kann dieser webbasierter Arduino Emulator verwendet werden. [klicken]


[Abb. 2: UML]

Benötigte Materialien

Tabelle 1: Materialliste
Nr. Anz. Beschreibung Bild
1 Funduino Arduino UNO R3
1 Typ 2
20+ Jumperkabel, männlich/männlich
1 Steckbrett
2 LED Rot/Grün
3 Widerstand
120 Ω
1 TowerPro SG90 Servomotor
1 Piezo Lautsprecher
1 4x4 Tastenfeld

Vorab wichtig zu wissen

Abb. 3: LED

Servomotor Kabel

Tabelle 2: Servomotor Farberkennung
Schwarz oder Braun Masse (GND)
Rot VCC/+ 5 V
Organe, Gelb oder Weiß PWM-Signal

Tastenfeld

Definition Tastenfeld [klicken]

Aufbau Schaltung

Abb.4 Schaltung Tür Sicherheitssystem

In Abbildung 4 wird die Schaltung für das Projekt "Tür Sicherheitssystem" dargestellt.
Bevor mit der Programmierung begonnen werden kann, muss die Schaltung des Projekts aufgebaut werden.

Programmierung

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

Wenn Sie Fragen zur Programmierung haben, finden Sie die Antworten in den [Grundkenntnissen].


Bibliotheken einfügen

Laden Sie für das Projekt die Bibliothek für das Tastenfeld 4x4 herunter.
Benötigt werden die Bibliotheken Servo.h und Keypad.h.

[Quelltext 1: TSS.ino]


Initialisierung Arduino

1. Tastenfeld initialisieren
Ziel ist es, alle benötigten Variablen für die Funktion zu definieren:
Keypad tastenfeld = Keypad(makeKeymap(Hexa_Keys), rowPins, colPins, ROWS, COLS);

  • ROWS sind die Anzahl der Spalten und COLS sind die Anzahl der Zeilen. Diese werden als Variable festgelegt.
  • Daraufhin müssen rowPins und colPins über eine Array-Zuweisung ihren Ziffern zugeordnet werden.
  • Zum Schluss muss die hexaKeys Matrix aufgebaut werden. Hier wird jede Ziffer für das Tastenfeld festgelegt.

[Quelltext 2: TSS.ino]

2. Tastenfeld Variablen
Benötigte Variablen zum:

  • Festlegen des Passwortes, jeder Buchstabe einzeln
  • Speichern der aktuell gedrückten Taste
  • Speichern der vier gedrückten Tasten
  • Verhindern einer falschen Position bei der Eingabe

[Quelltext 3: TSS.ino]

3. Motor, Buzzer und RGB initialisieren

Pins
LED 12 und 13
Motor 11
Buzzer 10

pinMode();
Servo.h
[Quelltext 4: TSS.ino]


Richtige Reihenfolge der Eingabe

Wichtig ist, dass die Ziffern richtig eingegeben werden.

  • So muss sich eine Funktion überlegt werden, welche dies ermöglicht.
  • Zur Verwendung kommen nun die Variablen für die falsche Eingabe.
  • Auch muss die Variable Taste ihre Werte erhalten.
  • Die gedrückte Taste wird in der c1-4 Variable abgespeichert, um später das Passwort zu überprüfen.

Tipp:

  1. Nachdem die erste Ziffer gedrückt wurde, öffnet sich die Eingabe für die zweite Ziffer usw.
  2. Benötigt wird hierfür eine if-Bedingung und eine goto Funktion.
  3. Die Taste bekommt mit der Funktion tastenfeld.getKey(); ihre Ziffer.

[Quelltext 5: TSS.ino]


Tür öffnen und schließen

  • Für das Öffnen der Tür wird die Taste (#) verwendet. Um die Tür zu verriegeln, wird die Taste (*) genutzt.
  • Wenn die Tür offen ist, leuchtet die LED Grün, und Rot, wenn die Tür geschlossen ist.
  • Der Motor soll sich beim Schließen zu 90 Grad, beim Öffnen wiederum zu 0 Grad drehen.
  • Überprüfe vor dem Öffnen, ob das Passwort korrekt eingegeben wurde.

Tipp:

  1. Benötigt werden if-Else Funktionen, die nach der bestimmten Taste abfragen und die Anweisung dann ausführen.
  2. Nutzen Sie Vergleichsoperatoren zum Abfragen des Passwortes.

[Quelltext 6: TSS.ino]


Einbrecher Warnung!

Die Zusatzaufgabe ist, einen Buzzer ertönen zu lassen, wenn das Passwort 3-mal falsch eingegeben wurde.

Tipp:

  1. Bei einer falschen Eingabe wird die Variable hochgezählt.
  2. Wenn die Variable 3 erreicht, ertönt der Buzzer.

tone();

[Quelltext 7: TSS.ino]

Musterlösung

Quelle



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