In unserem Minenspiel spielen zwei Schrittmotoren, ein IR-Empfänger mit mehreren IR‑Sendern und ein Arduino Uno die Hauptrollen. Es ist ein
einfaches Geschicklichkeitsspiel, in dem vor allem Konzentration und schnelle Reaktion gefordert werden. Ein Schiff gelangte ungewollt in ein Seeminenfeld.
Es gilt, bei der Weiterfahrt darauf zu achten, keine der Minen zu nah zu kommen. Sonst…
Das Minenfeld, bei uns auf einer alten Schallplatte aufgebaut, bewegt sich und zwingt das Schiff zu diversen Manövern, die notwendig sind, um den Minen
auszuweichen. Das Minenfeld wird mit einem Schrittmotor bewegt. Mit einem Taster kann ein gewünschtes Spiellevel voreingestellt werden. Je höher das Level,
umso schneller wird das Minenfeld bewegt. Damit wird auch automatisch der Schwierigkeitsgrad des Spiels erhöht.
In der Schallplatte befinden sich mehrere Löcher, die die Seeminen symbolisieren. Unter dem „Minenfeld“ befinden sich IR‑Sender, Leuchtdioden, die
Infrarotlicht verstrahlen. Der IR-Empfänger ist an einem Arm, der sich über dem Minenfeld befindet, angebracht. Die IR-Sender, der IR-Empfänger und die Löcher
sind so positioniert, dass es bei bestimmter Lage des Minenfeldes möglich ist, dass das Infrarotlicht durch ein Loch den IR-Empfänger erreicht. In diesem Fall
„explodiert“ die Mine und das Schiff sinkt. Spiel verloren. Die Aufgabe des Spielers ist es natürlich, dies zu vermeiden. Ihm steht ein Potentiometer als
Ruder zur Verfügung. Mit dem Potentiometer kann er den Arm mit dem IR-Empfänger bewegen. Durch Bewegungen des Armes nach links oder rechts kann er den Minen
ausweichen und das Schiff retten.
Der erste Motor, mit dem das Minenfeld bewegt wird, ist ähnlich wie auch der zweite Motor an den Motortreiber DM420 angeschlossen. Die Aufgabe
des Motortreibers ist es, das Problem der Leistung zu lösen. Das eigentliche Steuergerät, der Mikrocontroller Arduino Uno, kann alleine diese Aufgabe nicht
bewältigen. Wenn seine Ausgänge zu stark belastet werden, können sie beschädigt werden. Die maximale Spannung an seinen Ausgängen beträgt lediglich 5V DC.
Der Motortreiber dient in solchen Fällen wie eine Schnittstelle, die den Mikrocontroller und den Motor miteinander verbindet. Der Treiber ist an die
Ausgänge PIN 11, 12 und PIN 13 des Mikrocontrollers angeschlossen. Die Ansteuerung des Motors ist in diesem Fall denkbar einfach. Das Minenfeld dreht sich
stets in eine Richtung. Mit einem Taster (S2) wird das Level des Spiels eingestellt. Mit Levelwechsel wird eine andere Drehzahl des Motors eingestellt.
Beim Starten des Spiels wird mit dem Ausgang D13 (Enable) der Motor gestartet.
Mit dem zweiten Motor wird der Arm mit dem IR-Empfänger bewegt. Dank dieser Bewegungen kann der Spieler mit dem Schiff manövrieren und den Minen
ausweichen. Vor dem Start des Spiels muss der Arm in seine Referenzposition gebracht werden. Damit die Aufgabe leicht zu bewältigen ist, wird in dem Modus eine
geringe Drehzahl des Motors eingestellt. Die Referenzposition des IR-Empfängers befindet sich auf dem Außenrand des Minenfeldes.
Nach dem Spielstart wird der Arm mithilfe eines Potentiometers, das als Steuerruder fungiert, bewegt. Das Verstellen des Potentiometers nach links
bewirkt eine Linksbewegung des Armes. Entsprechend bewirkt das Verstellen des Potentiometers nach rechts eine Rechtsbewegung des Armes.
Mit drei Leuchtdioden wird der aktuell voreingestellte Level angezeigt. Das Level wird mit der Taster S2 voreingestellt. Die rote Leuchtdiode leuchtet
dann auf, wenn eine Mine „hochgegangen“ ist. Mit Taster S1 wird das Spiel gestartet
bzw. gestoppt.
Schaltplan
Aufbau der Testschaltung
Minenfeld
"Schiff" mit dem IR-Empfänger
IR-Sender
Steuerruder
Steuerelemente und Anzeigen
Schrittmotor
Motortreiber
Einstellung der DIP-Schalter Treiber beweglicher Arm
Einstellung der DIP-Schalter Treiber Minenfeld
Testschaltung komplett
Programm
// *******************************************************************************************
// Minenspiel mit Infrarot und Schrittmotoren
// Arduino UNO
// Arduino IDE Version 2.3.8
// *******************************************************************************************
// Anschluss-Pins Minenfeld
int Motor_Minenfeld_PUL = 11; // Treiber DM420: Pulse Anschluss
int Motor_Minenfeld_DIR = 12; // Treiber DM420: Drehrichtung
int Motor_Minenfeld_ENBL = 13; // Treiber DM420: Freigabe
// Anschluss-Pins beweglicher Arm
int Motor_Arm_PUL = 2; // Treiber DM420: Pulse Anschluss
int Motor_Arm_DIR = 3; // Treiber DM420: Drehrichtung
int Motor_Arm_ENBL = 4; // Treiber DM420: Freigabe
int Taster_Spiel_Start = 9; // Pin 9 - Taster Start/Stop
int Taster_Spiel_Level = 8; // Pin 8 - Leveleinstellung
int Spiel_Level = 1; // Spiellevel aktuell
int Spiel_Status; // Status (0-Stop, 1-Auto 2-Mine getroffen)
int Pulslaenge; // Verzögerung
int LED_Level_1 = A0; // Pin LED weiß
int LED_Level_2 = A1; // Pin LED blau
int LED_Level_3 = A2; // Pin LED gelb
int LED_Mine_getroffen = A3; // Pin LED rot
int Poti = A4; // Pin Steuerruder
int IR_Sensor = A5; // PIN IR-Empfänger
int Poti_Altwert; // Analogwert
bool Arm_Bewegen; // Arm Bewegungsfreigabe
int Arm_Position; // Arm aktuelle Position
int Potisitionswert_Max = 78; // Arm Bewegungsradius Max.
// *******************************************************************************************
void setup() {
pinMode (Motor_Minenfeld_PUL, OUTPUT); // PUL-Pin als Ausgang
pinMode (Motor_Minenfeld_DIR, OUTPUT); // DIR-Pin als Ausgang
pinMode (Motor_Minenfeld_ENBL, OUTPUT); // ENBL-Pin als Ausgang
digitalWrite (Motor_Minenfeld_DIR, HIGH); // Motordrehrichtung Vorbelegung
pinMode (Motor_Arm_PUL, OUTPUT); // PUL-Pin als Ausgang
pinMode (Motor_Arm_DIR, OUTPUT); // DIR-Pin als Ausgang
pinMode (Motor_Arm_ENBL, OUTPUT); // ENBL-Pin als Ausgang
pinMode (Taster_Spiel_Start, INPUT_PULLUP); // Eingang
pinMode (Taster_Spiel_Level, INPUT_PULLUP); // Eingang
pinMode (LED_Level_1, OUTPUT); // Status LED Level 1
pinMode (LED_Level_2, OUTPUT); // Status LED Level 2
pinMode (LED_Level_3, OUTPUT); // Status LED Level 3
pinMode (LED_Mine_getroffen, OUTPUT); // Status LED Mine angefahren
Poti_Altwert = analogRead (A4); // Poti Position aktuell
digitalWrite (Motor_Arm_ENBL, HIGH); // Motor Arm Freigabe
}
// *******************************************************************************************
void Level_Umschaltung () { // Level-Bestimmung mit Taster S2
if (digitalRead (Taster_Spiel_Level) == LOW) {
Spiel_Level++;
delay (150);
}
if (Spiel_Level > 3) {
Spiel_Level = 1;
}
digitalWrite (LED_Level_1, LOW);
digitalWrite (LED_Level_2, LOW);
digitalWrite (LED_Level_3, LOW);
switch (Spiel_Level) {
case 1: {
Pulslaenge = 10000;
digitalWrite (LED_Level_1, HIGH);
break;
}
case 2: {
Pulslaenge = 6000;
digitalWrite (LED_Level_2, HIGH);
break;
}
case 3: {
Pulslaenge = 3000;
digitalWrite (LED_Level_3, HIGH);
break;
}
}
}
// *******************************************************************************************
void Spiel_starten () {
// Automatik START
if ((digitalRead (Taster_Spiel_Start) == LOW) && (Spiel_Status == 0)) {
Spiel_Status = 1; // Status Automatik
Arm_Position = Potisitionswert_Max; // Startwert Arm Position
digitalWrite (Motor_Minenfeld_ENBL, HIGH); // Minenfeld starten
delay (250); // Wartezeit
}
// Spiel zurücksetzen
if ((digitalRead (Taster_Spiel_Start) == LOW) && (Spiel_Status == 3)) {
Spiel_Status = 0; // Wartezustand
digitalWrite (LED_Mine_getroffen, LOW); // Rote LED ausschalten
digitalWrite (Motor_Minenfeld_ENBL, LOW); // Minenfeld anhalten
delay (250); // Wartezeit
}
// Automatik unterbrechen
if ((digitalRead (Taster_Spiel_Start) == LOW) && (Spiel_Status == 1)) {
Spiel_Status = 0; // Wartezustand
digitalWrite (Motor_Minenfeld_ENBL, LOW); // Minefeld anhalten
delay (250); // Wartezeit
}
}
// *******************************************************************************************
void Motoren_drehen () { // Impulsbreite und Pulspause gleich für
// beide Motoren (Automatik)
digitalWrite(Motor_Minenfeld_PUL,HIGH);
if (Arm_Bewegen) {
digitalWrite(Motor_Arm_PUL,HIGH);
}
delayMicroseconds(Pulslaenge);
digitalWrite(Motor_Minenfeld_PUL,LOW);
if (Arm_Bewegen) {
digitalWrite(Motor_Arm_PUL,LOW);
Arm_Bewegen = false;
}
delayMicroseconds(Pulslaenge);
}
// *******************************************************************************************
void Arm_Motor_drehen () { // Langsames Drehen um Referenzpunkt
// anzufahren (Spiel Aus)
digitalWrite(Motor_Arm_PUL,HIGH);
delay(25);
digitalWrite(Motor_Arm_PUL,LOW);
delay(25);
}
// *******************************************************************************************
void loop() {
Level_Umschaltung (); // Level Einstellung
Spiel_starten (); // Automatik Start
if (Spiel_Status == 1) { // Automatik
Motoren_drehen ();
}
int IR_Signal = analogRead(IR_Sensor); // Signal vom IR-Empfänger prüfen
if ((IR_Signal < 100) && (Spiel_Status == 1)) { // Mine angefahren, Spiel Stop
Spiel_Status = 3;
digitalWrite (LED_Mine_getroffen, HIGH); // Rote LED Ein
digitalWrite (Motor_Minenfeld_ENBL, LOW); // Minenfeld Stop
}
int Poti_Wert = analogRead (A4); // Poti Wert abfragen
if (Poti_Wert > 520) { // Arm wird bewegt nach rechts
Arm_Position++;
if (Arm_Position > Potisitionswert_Max) { // Bewegung nur im zugelassenen Abschnitt
Arm_Position = Potisitionswert_Max;
} else {
digitalWrite (Motor_Arm_DIR, HIGH);
Arm_Bewegen = true;
}
if (Spiel_Status == 0) { // Referenzpunkt langsam anfahren (Recht)
digitalWrite (Motor_Arm_DIR, HIGH);
Arm_Motor_drehen ();
}
}
if (Poti_Wert < 470) { // Arm wird bewegt nach links
Arm_Position--;
if (Arm_Position < 0) {
Arm_Position = 0;
} else {
digitalWrite (Motor_Arm_DIR, LOW);
Arm_Bewegen = true;
}
if (Spiel_Status == 0) { // Referenzpunkt langsam anfahren (Links)
digitalWrite (Motor_Arm_DIR, LOW);
Arm_Motor_drehen ();
}
}
}
// *******************************************************************************************