Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

projektewise24:projekt8:doku

Dies ist eine alte Version des Dokuments!




Projektdokumentation

Einleitung / Themenbeschreibung

In diesem Projekt entwickeln wir einen Roboter, der das Spiel „4-Gewinnt“ gegen einen menschlichen Spieler bestreiten kann. Der Roboter soll das Spiel eigenständig spielen können, indem er seine Spielsteine gezielt in das Spielfeld einwirft und gegnerische Spielzüge selbstständig analysiert. Dazu muss er die Position freier und besetzter Felder erkennen sowie zwischen eigenen und gegnerischen Spielsteinen unterscheiden.
Darauf aufbauend soll der Roboter sinnvolle Spielzüge berechnen und ausführen. Ein wichtiges Ziel ist, dass der Roboter strategisch vorgeht und nicht nur zufällige Züge setzt, weil sonst der Spaß am Spielen mit unserem Roboter untergehen würde. Er soll in der Lage sein, gewinnbringende Spielzüge zu identifizieren und den Gegner gegebenenfalls am Sieg blockieren. Hierzu wird ein Algorithmus benötigt, der das Spielfeld auswertet und basierend darauf optimale Entscheidungen auf einer moderaten Schwierigkeitsstufen trifft. Diese Schwierigkeitsstufe wird angestrebt, um die Spielerfahrung angenehm zu gestalten, da eine perfekt spielende KI den Spielspaß mindern könnte.
Außerdem soll der Roboter mit dem Spieler interagieren können. Das bedeutet, er muss erkennen, wann der Mensch einen Spielzug gemacht hat, und dann selbstständig darauf reagieren. Die Bedienung soll möglichst einfach sein, sodass jeder mit unserem Roboter spielen kann. Das Interagieren soll am Besten mit Soundeffekten sowie Lichteffekten passieren und eine schöne Spielerfahrung schaffen.
Die technische Umsetzung umfasst mehrere Kernkomponenten: einen Mechanismus zum präzisen Einwerfen der Spielsteine, eine Sensorik zur Spielzugerkennung und eine Spiellogik zur Berechnung und Ausführung der Spielstrategie. Ziel des Projektes ist es, einen funktionsfähigen, interaktiven Spielroboter zu realisieren, der zuverlässig operiert und eine herausfordernde, aber unterhaltsame Spielerfahrung bietet.

Links zu ähnlichen Projekten:

Überblick über das Gesamtsystem

Abbildung 1: Schaltplan

Systembestandteile

Gerüst mit Trichter

Das Gerüst besteht aus drei Teilkomponenten: den Beinen zur Stabilisierung der Konstruktion, dem Arm mit den Trichtern zur Lenkung der Spielsteine in die richtigen Spalten und der V-Slot-Schiene für die Bewegung des Schlittens.
Die Trichter wurden mittels CAD konstruiert und 3D-gedruckt (Abb. 2).

Damit die Spielsteine möglichst genau in das Spielfeld fallen, haben die Trichter eine abgerundete Form. Denn beim Vergleich zwischen einer abgerundeten und nicht abgerundeten Version, konnte der Spielstein bei der ersten Version sicherer in das Spielfeld geleitet werden. Am unteren Ende der Trichter befinden sich zwei Platten, damit das 4-gewinnt-Spiel problemloser unter den Trichtern positioniert werden kann, falls man die Spielsteine aus dem Spielfeld entfernen muss.

Abbildung 2: Trichter

Die V-Slot-Schiene dient als Führung für den beweglichen Schlitten. Hierbei haben wir uns an dem Projekt Das intelligente Bücherregal orientiert.

Steppermotor mit Schlitten und Zahnriemen

Oberhalb der Trichter verläuft eine V-Slot Schiene, auf der mit Hilfe eines Steppermotors ein Schlitten hin und her gefahren werden kann. Am Anfang jedes Spiel muss der Schlitten manuell auf seine Startpositionen auf der Seite des Motors geschoben werden.

Um den Stepper ansteuern zu können, haben wir zwischen Stepper und Arduino einen Stepper Treiber geschaltet. Wir verwenden das Steppermodel A4988. Die Ansteuerung der Stepper Treiber erfolgt durch das Setzen des Richtungs-Pins auf HIGH oder LOW und anschließend wiederholtes Ein- und Ausschalten des Step-Pins. Die Geschwindigkeit des Motors wird dabei durch die Wartezeit zwischen den Impulsen gesteuert.

Zur Steuerung des Schlittens haben wir die Klasse Stepper geschrieben. Diese Stellt die Funktion moveTo(col) zur Verfügung. Die Variable int col steht dabei für die Spalte, in die der Roboter seinen Spielsteil fallen lassen soll. col = 0 ist die Position des Parkplatzes. Um die Anzahl an Steps zu ermitteln, die der Schlitten von seinem Parkplatz bis zu den einzelnen Spalten benötigt, ließen wir den Schlitten in einer langsamen Geschwindigkeit fahren, während das Programm die getätigten Steps mitzählte. Jeder Spalt bekam also eine Step-Anzahl zugeordnet. Nach jeder Fahrt wird die currentPosition aktualisiert. Sie speichert den Abstand vom Schlitten zum Parkplatz. Diese Kenngröße ist wichtig, weil von ihr abhängt in welche Richtung die nächste Fahrt stattfindet und wie viele Steps der Motor braucht, um nach einem getätigten Zug wieder auf seine Parkplatz zu fahren. Wenn der Stein geschmissen wurde, soll der Motor wieder auf seine Ausgangsposition, seinen Parkplatz, zurück fahren. Das funktioniert über die Funktion moveTo(0). Die Step-Anzahl entspricht dabei der currentPosition.

Abbildung 3: Schlittenabdeckung
Abbildung 4: Stepperhalterung

Reinfallmechanismus

Die Spielsteine des Roboters sollen gezielt in das Spielfeld befördert werden. Dazu werden die Spielsteine in einem Magazin gelagert (Abb.5). Dieses hat unten eine Öffnung, um die Spielsteine herausschieben zu können und oben eine Öffnung, damit die Spielsteine nachgefüllt werden können. Das Magazin haben wir an der Abdeckung des Schlittens (Abb. 3) befestigt.

Abbildung 5: Magazin

Horizontal auf dieser Abdeckung befindet sich der Schiebemechanismus. Dieser besteht aus aus einer Zahnstange, die in einer Schiene liegt. Ein auf den Servo geklebtes Zahnrad bewegt die Zahnstange, wodurch die Steine gezielt in das Spielfeld geschoben werden. Vorne auf der Zahnstange steckt ein abgerundeter Aufsatz, damit die Steine möglichst präzise in das Spielfeld geschoben werden können. Die Schiene und den Aufsatz haben wir 3D-gedruckt (Abb. 6).

Abbildung 6: Schiene und Aufsatz

Nachdem der Schlitten zur richtigen Spalte gefahren ist, dreht sich der Servomotor, um den Spielstein in das Spielfeld zu schieben. Damit dies möglichst genau geschieht, haben wir unterschiedliche Gradzahlen getestet. Die beim Test am Besten passendsten, haben wir in den zugehörigen Code-Abschnitt geschrieben:

void push() {
  Serial.println("Servo dreht sich hin");  // Ausgabe zur Kontrolle
  // Servo dreht sich von 160° auf 25°:
  for (int i = 160; i>=25; i--) {
    servo.write(i);
    delay(30);
  }
  Serial.println("Servo dreht sich zurück");  // Ausgabe zur Kontrolle
  // Servo dreht sich zurück von 25° auf 160°:
  for (int i = 25; i <= 160; i++) {
    servo.write(i);
    delay(30);
  }

Kommunikationskomponenten

Die Kommunikation zwischen Spieler und Roboter erfolgt über drei Komponenten:

  • 7 Knöpfe zur Übermittlung des getätigten Spielzug
  • 2 LEDs in rot (Spieler) und blau (Roboter)
  • einen Piezo-Lautsprecher

Über die zwei verschiedenfarbigen LEDs soll der Roboter anzeigen können, wer am Zug ist. Besonders wichtig ist das am Anfang des Spiel, damit man überhaupt weiß, wer beginnt; Mensch oder Roboter. Passend zu den Spielsteinen steht die rote Led für den Menschen und die blaue für den Roboter.

Die akustische Kommunikation über den Piezo wird nur am Anfang und am Ende eines Spiels ausgelöst. Beim Anschalten des Roboters ertönt eine kurze Melodie, die signalisieren soll, dass der Roboter bereit ist zum Spielen. Und je nachdem wie das Spiel ausgegangen ist, wird am Ende ein individueller Sound für „gewonnen“ “verloren” oder “unentschieden” abgespielt.

Außerdem soll mithilfe der Knöpfe die Spalte, in die der Mensch seinen Spielstein fallen lässt, an den Roboter übergeben werden. Dazu haben wir uns an dem Youtube-Video https://www.youtube.com/watch?v=zaMemluFaoM orientiert. Dadurch können wir alle sieben Knöpfe an einem Pin ansteuern.
Zuerst hatten wir für die Spaltenerkennung den Einsatz von Druck- oder Infrarotsensoren erwogen. Allerdings hatten wir keinen passenden Drucksensor für unsere Ansprüche gefunden. Daraufhin haben wir unterschiedliche Infrarot-Entfernungssensoren ausprobiert und uns für den GP2Y0A41SK0F-Sensor entschieden. Diesen haben wir kalibriert, indem wir die Output-Werte in Abhängigkeit zur Länge gemessen und in ein Diagramm gezeichnet haben (Abb.7) .

Abbildung 7: Kalibrierungskurve

Der Sensor war daraufhin auch relativ genau. Allerdings konnte er die fallenden Steine nur ungenau erfassen. Deswegen hatten wir uns schließlich dazu entschieden, Knöpfe zu benutzen. Um möglichst wenige Pins benutzen zu müssen, haben wir sieben Knöpfe an einem analogen Pin (A0) angeschlossen. Je nachdem welcher Knopf gedrückt wird, existiert ein anderer Widerstandswert im Stromkreis. Somit werden, je nach Knopf, verschiedene Werte zwischen 0 und 1023 ausgegeben. Die Werte für jeden Knopf haben wir gemessen. Leider schwanken diese. Das haben wir aber versucht im Code zu berücksichtigen:

void setup() {
  pinMode(KNOEPFE,INPUT);
  Serial.begin(9600);
}
void loop() {
  int buttonvalue = analogRead(A0);
  if(buttonvalue <= 155 && buttonvalue > 100) {
    Serial.println(1);
  }
  if(buttonvalue <= 185 && buttonvalue > 160) {
  Serial.println(2);
  }
  if(buttonvalue <= 230 && buttonvalue > 190) {
  Serial.println(3);
  }
  if(buttonvalue <= 320 && buttonvalue > 240) {
  Serial.println(4);
  }
  if(buttonvalue <= 400 && buttonvalue > 340) {
  Serial.println(5);
  }
  if(buttonvalue <= 600 && buttonvalue > 490) {
  Serial.println(6);
  }
  if(buttonvalue <= 1024 && buttonvalue > 900) {
  Serial.println(7);
  }
  delay(300);
}

Mithilfe einer If-Bedingung wird aus dem Input-Wert die zugehörige Spalte ermittelt. Aktuell haben wir zur Überprüfung noch die serielle Ausgabe im Code zu stehen. Der Code ist noch nicht mit den anderen Komponenten verknüpft.

Die beiden LEDs und die sieben Knöpfe haben wir auf einer 3D-gedruckten Platte (Abb.8) befestigt.

Abbildung 8: Platte für Knöpfe und LEDs

Spiellogik

Technische Daten

Tabelle 1: Pinbelegung
Pin Komponente [Pin]
5V Stepper Treiber [VDD]
GND Stepper Treiber [GND]
D2 Stepper Treiber [STEP]
D3 Stepper Treiber [DIR]
D4 Stepper Treiber [ENABLE]
D5 Piezo
D7 Servomotor
D8 blaue LED
D9 rote LED
A0 Schalter
GND Piezo, rote LED, blaue LED, Schalter, Servo
Tabelle 2: Bauteile und Materiallen
Schon vorhanden? / b(estellt) Material Preis Link bezahlt von
4-Gewinnt Spiel 11,69€ https://kurzlinks.de/z82v Clara → A
Schiene 13,92€ https://lmy.de/ksCPN Clara → A
Schlitten 13,40€ https://lmy.de/fqtzl Clara → A
GT2 Zahnriemen 6,99€ https://lmy.de/rEVqM Anne
GT2 Riemenscheibe 1,05€ https://lmy.de/ZXVeu Clara → A
Riemenspanner 11,79€ https://lmy.de/wMXVm Anne
2x Crimp Klammern 1,10€ https://lmy.de/NliFP Clara → A
10 x Winkel für V-Slot Schiene 7,99€ https://lmy.de/YJGxe Clara → A
Steppermotor / Labor
Steppermotor-Treiber / Labor
Servomotor / Labor
Piezo-Speaker / -Piepser / Labor
2 LEDs (rot, blau) / Labor
7 Knöpfe / Labor
großes Breadboard / Labor
Holz 8,50€ Baumarkt Jonathan
doch nicht benötigt Infrarotentfernungssensor Clara → A
doch nicht benötigt Feder Jonathan → A

Ergebnis und Diskussion

Das Ziel unseres Projekts war die Entwicklung eines Roboters, der das Spiel „4-Gewinnt“ gegen einen menschlichen Spieler autonom spielen kann. Der Roboter sollte dazu in der Lage sein, die eigenen Spielsteine gezielt in das Spielfeld einzuwerfen, Spielzüge zu analysieren und mit dem Spieler zu interagieren.

Zum jetzigen Zeitpunkt kann der Roboter bereits den Beginner per Zufallsauswahl bestimmen und dies durch LEDs signalisieren. Er kann anzeigen, wer am Zug ist. Ist der Roboter am Zug, kann er die gewünschte Spalte präzise ansteuern und seinen Spielstein mit meist in das Spielfeld fallen lassen. Wenn der Mensch am Zug ist, kann dieser seinen Spielzug über Knöpfe eingeben (nachdem diese kalibriert wurden). Der Spielausgang wird durch LEDs und einen Piezo-Lautsprecher verdeutlicht. Mithilfe der LEDs und dem Piezo-Lautsprecher kann deutlich gemacht werden, wie das Spiel ausgegangen ist.

Allerdings bestehen derzeit noch Probleme mit der Kommunikation zwischen den einzelnen Komponenten. Dadurch ist kein reibungsloser Spielablauf möglich. Die einzelnen Code-Abschnitte müssen wir noch miteinander verbinden, um diese Probleme lösen zu können. Dies ist bis jetzt aus Zeitgründen noch nicht geschehen.
Die Kommunikation über die Knöpfe ist aktuell noch fehlerhaft, da die Input-Werte nicht immer stabil sind. Das führt zu einer fehlerhaften Spielzugerkennungen, wenn man diese nicht erneut kalibriert. Mögliche Lösungsansätze wären die Verwendung anderer Widerstände oder eine verbesserte Codevariante, um Spannungsschwankungen besser auszugleichen.
Ein weiteres geplantes Feature war die Implementierung einer KI, die das Spielfeld auswertet und Spielzüge auf einer moderaten Schwierigkeitsstufe trifft. Aufgrund von Zeitbeschränkungen konnten wir dies bislang nicht umsetzen. Unsere Idee wäre die Nutzung eines Minimax-Algorithmus, um den Roboter zu einem anspruchsvolleren Gegner zu machen.

Code und Rohdaten

Wenn man ein 4-gewinnt Spiel programmiert ist die erste Aufgabe ein Gerüst für das Spiel zu schaffen mit mit Spielmechaniken. Unter Spielmechaniken verstehen wir die Initialisierung des Spielfelds, der Spielzug und die Überprüfung ob gewonnen wurde.

Die Spiellogik des Vier-Gewinnt-Roboters bildet sein Herzstück. Sie bestimmt, wie der Roboter das Spielfeld analysiert, Züge berechnet und strategisch auf den Gegner reagiert. Die Grundlage dieser Logik ist ein Algorithmus, der das aktuelle Spielfeld auswertet und mögliche Spielzüge im Vorraum bewertet. Dabei wird sichergestellt, dass der Roboter stets über eine optimale Strategie verfügt und dennoch eine moderate Schwierigkeitsstufe bietet, um dem Spieler eine faire Herausforderung zu bieten.

Zunächst erkennt unser KI gesteuerter Roboter die aktuelle Spielsituation, indem er alle freien und belegten (seiner + Spielers) Felder analysiert. Das passiert durch die Erstellung eines digitalem Spielfeldes.

Anschließend werden verschiedene Zugmöglichkeiten simuliert in einem MiniMax-Algorithmus. Dieser Algorithmus arbeitet nach einem einfachen Prinzip, die KI versucht, ihren eigenen besten Zug zu maximieren, während die KI gleichzeitig annimmt, dass der Gegner ebenfalls optimal spielt und dessen beste Option minimiert. Durch diese Vorgehensweise kann die Spiellogik, nicht nur offensive, sondern auch defensive Spielzüge erkennen und entsprechende Entscheidungen treffen.
Hier der Code des MiniMax-Algorithmus:


Hier solltet Ihr eine lauffähige Version eures Codes inkl. aller verwendeten Libraries als .zip-Datei zum Download anbieten.



projektewise24/projekt8/doku.1743455601.txt.gz · Zuletzt geändert: 2025/03/31 23:13 von jck8erlin