Zahnriemenscheibe montiert auf einer Motorwelle


Google-Suche auf MEINE-SCHALTUNG.de :





Online Rechner

Chronik

Dauerkalender


Tom und Jerry Würfelspiel

(Serielle Kommunikation zwischen drei Arduinos)

Am Beispiel eines Würfel-Spiels konstruieren wir jetzt eine Schaltung, in der drei Arduinos miteinander seriell kommunizieren. Alle drei Mikrocontroller müssen über die serielle Schnittstelle Daten senden und empfangen.
Die Spielregeln halten wir einfach. Zwei Spieler, Tom (links) und Jerry (rechts), würfeln pro ein Spiel fünfmal um ihr Glück. Die Augenzahlen werden summiert. Wer mehr angesammelt hat, hat gewonnen.
Die Spieler werden von zwei Arduino Nanos repräsentiert. Die Rolle des Schiedsrichters, der das Spiel leitet, übernimmt Arduino Mega. Nachdem das Spiel gestartet wurde, entscheidet der Schiedsrichter, welcher Spieler an der Reihe ist. Die Spieler würfeln nach dem Prinzip einer Zufallszahl. Anschließend übergeben sie das erreichte Ergebnis an den Schiedsrichter. Er summiert die Punkte und zeigt den aktuellen Spielstand auf einer Infotafel. Zum Schluss zeigt er auch an, welcher der beiden Spieler erfolgreicher war.

Die Mikrocontroller

Drei Arduinos

An dem Spiel nehmen drei Arduinos (2 x Arduino Nano und 1 x Arduino Mega) teil. Arduino Mega verfügt über mehrere serielle Schnittstellen. Arduino Nano hat nur eine.

Arduino

Die Matrix und das Modulmit Max7219

Matrix 8x8

Matrix 8x8

Modul mit Maxim

Maxim-Modul

Die Würfelaugen werden mithilfe zweier Matrix (8x8) angezeigt. Sie werden von dem Anzeigentreiber Max7219 gesteuert. Die Kommunikation des Treibers mit dem Arduino Nano erfolgt hier über die Pins D2, D3 und D4. Um die 64 Digits der Matrix anzusteuern, werden also nur drei Leitungen verwendet. Es werden auch keine Vorwiderstände gebraucht. Die Matrix wird auf das Modul mit MAX7219 einfach aufgesteckt.

Matrix 1088AS

LCD Bildschirm

Display

Display 5V 20x4

I2C Display-Modul

Display-Treiber

Um die Anzahl der notwendigen Verbindungen zu reduzieren, wird an das LCD ein I2C-Adapter (FC-113) angeschlossen (hier fest angelötet). Damit kann das Display über I2C-Bus angesprochen werden. Das reduziert die Anzahl der Verbindungen auf zwei. Die für den I2C-Bus zuständigen Pins am Arduino Mega – Board sind die Pins 20 (SDA) und 21 (SCL).

Display mit I2C-Adapter

Spannungsregler

Spannungsregler

Spannungsregler

Spannungsregler-Module

Der Schaltplan

Schaltplan

Schaltplan

Das Programm (Arduino Nano)

Beide Arduino Nanos werden mit dem gleichen Programm ausgestattet. In der Vorbereitungsphase muss an das Programm die Bibliothek "LedControl.h" (von Eberhard Fahle, 2007) eingebunden werden. Sie übernimmt die Kommunikation mit der Matrix, an der die Würfelaugen angezeigt werden. Für diese Kommunikation müssen wir drei digitale Pins des Arduino aufopfern, es sind die Pins D2, D3 und D4. Für die Einbindung der Bibliothek kann der Bibliothekenverwalter verwendet werden.
Die beiden Nanos arbeiten mit Zufallszahlen. Ohne weitere Vorkehrungen generiert der Mikrocontroller bei jedem Neustart die gleichen Zufallszahlen. Das kann den Spaß an einem Glückspiel ein wenig verderben. Um dem Problem vorzubeugen, kommt in dem Programm die Funktion randomSeed(analogRead(A0) zum Einsatz. Sie bestimmt den Startwert des Zufallsgenerators. Den Startwert holen wir von dem analogen Eingang A0. An den Eingang ist ein Kondensator angeschlossen, der sich über den Widerstand R1 auflädt. Bei Betätigen des Tasters S1 erfolgt über den Widerstand R2 eine kurze Entladung des Kondensators. Da nicht vorhersehbar ist, wie lange ein Mensch einen Taster drückt, kann man davon ausgehen, dass an dem analogen Eingang jeweils ein anderer Spannungswert ausgelesen wird. Damit wird sichergestellt, dass bei jedem Neustart andere Zufallszahlen generiert werden.
Viel zu tun haben die Nanos nicht. Es wird zunächst darauf gewartet, ob der Befehl Start von dem Arduino Mega, der in dem Spiel als Schiedsrichter fungiert, über die serielle Schnittstelle angekommen ist. Sobald dies geschieht, wird eine kleine Matrix-Show gestartet. Gleich danach wird eine Würfel-Augenzahl zwischen 1 und 6 via Zufall generiert. Die Augenzahl wird dann auf der Matrix angezeigt und über die serielle Schnittstelle dem Schiedsrichter mitgeteilt.
Damit es ein wenig persönlicher wird, bekamen die Arduinos statt Nummern eigene Namen. In der Testschaltung spielt auf der linken Seite Tom. Jerry positionierte sich auf der rechten Seite.

// *************************************************************************************
// Tom und Jerry Würfelspiel
// Serielle Kommunikation drei Arduinos
// Sketch Arduino Nano
// Arduino IDE 1.8.19
// *************************************************************************************

#include "LedControl.h"                                   // Bibliothek Matrix

int Pin_DIN = 2;                                          // Anschluss DIN
int Pin_CS = 3;                                           // Anschluss CS
int Pin_CLK = 4;                                          // Anschluss CLK

LedControl lc=LedControl(Pin_DIN,Pin_CLK,Pin_CS,1); 

int Show_Bits [28][2] = {                                 // LED-Lauf
    {0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4},               // { PosX, PosY }
    {0, 5}, {0, 6}, {0, 7}, {1, 7}, {2, 7},
    {3, 7}, {4, 7}, {5, 7}, {6, 7}, {7, 7},
    {7, 6}, {7, 5}, {7, 4}, {7, 3}, {7, 2},
    {7, 1}, {7, 0}, {6, 0}, {5, 0}, {4, 0},
    {3, 0}, {2, 0}, {1, 0}                  };
int Ziffern [42][3] = {                                   // Würfelaugen
    {1,1,0}, {1,5,0}, {3,1,0}, {3,3,1}, {3,5,0}, {5,1,0}, {5,5,0},    // 1
    {1,1,0}, {1,5,0}, {3,1,1}, {3,3,0}, {3,5,1}, {5,1,0}, {5,5,0},    // 2
    {1,1,1}, {1,5,0}, {3,1,0}, {3,3,1}, {3,5,0}, {5,1,0}, {5,5,1},    // 3
    {1,1,1}, {1,5,1}, {3,1,0}, {3,3,0}, {3,5,0}, {5,1,1}, {5,5,1},    // 4
    {1,1,1}, {1,5,1}, {3,1,0}, {3,3,1}, {3,5,0}, {5,1,1}, {5,5,1},    // 5
    {0,1,1}, {0,5,1}, {3,1,1}, {3,3,0}, {3,5,1}, {6,1,1}, {6,5,1} };  // 6  
String Empfang = "";
bool Startbit;
int Wuerfel_Zahl;

void setup() {
  
    lc.shutdown(0,false); 
    lc.setIntensity(0,8); 
    lc.clearDisplay(0);  
    Serial.begin (9600);  
    Startbit = HIGH;
}
// ******************************************************************************

void loop() {

   if (Serial.available() > 0) {                     // Daten von Mega vorhanden?
      Empfang = Serial.readString();                 // Ja. Auslesen.
   }
   delay(100);
   if (Empfang == "Start") {                         // Start von Mega
      Empfang = "";
      if (Startbit) { 
          randomSeed(analogRead(A0));                // Zufallsgenerator Startwert
          Startbit = LOW; }
      Show();                                        // Matrix Show
      Wuerfel_Zahl = random (1,7);                   // Augenzahl via Zufall 
      Ziffer (Wuerfel_Zahl);                         // Augenzahl anzeigen
      Serial.print (Wuerfel_Zahl);                   // Ergebnis zu Mega
   }
}      
// ******************************************************************************

void Show ()  {                                      // Rand-LEDs ein und aus
    lc.clearDisplay(0);
    for (int i=0; i<5; i++) {
        for (int j=0; j<28; j++) {
            lc.setLed (0,Show_Bits [j][0],Show_Bits [j][1],1);
            int k = j - 1;
            if (j == 0) { k = 27; }
            lc.setLed (0,Show_Bits [k][0],Show_Bits [k][1],0);
            delay(25);
        }
    }
    lc.setLed (0,1,0,0);
    for (int i=1; i<7; i++) {                       // Alle Würfelaugen anzeigen
        Ziffer (i);
        delay(200);
        lc.clearDisplay(0);
    }
    delay(1000);
}
// ******************************************************************************

void Ziffer (int Ziffer)  {                    // Würfelauge besteht aus 4 Digits
    
    int Pos = (Ziffer - 1) * 7;
    for (int j=0; j<7; j++) {
        lc.setLed (0,Ziffern [Pos+j][0],Ziffern [Pos+j][1],Ziffern [Pos+j][2]);
        lc.setLed (0,(Ziffern [Pos+j][0])+1,Ziffern [Pos+j][1],Ziffern [Pos+j][2]);
        lc.setLed (0,Ziffern [Pos+j][0],(Ziffern [Pos+j][1])+1,Ziffern [Pos+j][2]);
        lc.setLed (0,(Ziffern [Pos+j][0])+1,(Ziffern [Pos+j][1])+1,Ziffern [Pos+j][2]);
    }
}
// ******************************************************************************        
  


Das Programm (Arduino Mega)

Der Schiedsrichter (Arduino Mega) koordiniert das Spiel. Er bestimmt, welcher der Spieler gerade am Zug ist. Mit Serial.print("Start") wird Tom aufgefordert, den Würfel zu werfen. Mit Serial1.print("Start") wird der Jerry angesprochen. Nach jedem Aufruf wartet Arduino Mega auf Antwort des jeweiligen Spielers. Die vom Spieler mitgeteilte Augenzahl wird dann auf dem Display angezeigt. Zusätzlich wird die gesamte Punktezahl errechnet und ebenfalls angezeigt. Ein Spiel besteht aus fünf Runden. Wenn man weiter machen will, muss erneut der Startknopf betätigt werden.
Auch in diesem Programm wird eine Bibliothek verwendet. Sie ist für die Kommunikation mit dem Display notwendig. Die Bibliothek LiquidCrystal_I2C.h kann ebenfalls über den Bibliothekenverwalter installiert werden.
Die Funktionen, die sich auf serielle Schnittstelle beziehen, sind:
Serial.available() – Prüfung, ob Daten vorhanden sind
Serial.print () – Daten senden
Serial.parseInt() – lese die nächste gültige ganze Zahl

// ******************************************************************************
// Tom und Jerry Würfelspiel
// Serielle Kommunikation drei Arduinos
// Sketch Arduino Mega
// Arduino IDE 1.8.19
// ******************************************************************************

#include <LiquidCrystal_I2C.h>                   // Bibliothek Display I2C-Bus
LiquidCrystal_I2C lcd(0x27,20,4);                // Adresse, Zeichen, Zeilen

int Taster_Start = 13;                           // Taster Spiel Start
int Punkte_Tom [2];                              
int Punkte_Jerry [2];

void setup() {

    lcd.init();                                  // Display initialisieren 
    lcd.backlight();                             // Hintergrundbeleuchtung
    pinMode (Taster_Start, INPUT_PULLUP); 
    Serial.begin (9600);                         // Schnittstelle Tom
    Serial1.begin (9600);                        // Schnittstelle Jerry
}
// ******************************************************************************

void loop() {

    lcd.setCursor(1,1);                          // Start Text auf dem Display
    lcd.print("Druecke den Knopf,");
    lcd.setCursor(3,2);
    lcd.print("um zu beginnen.");
    
    if (digitalRead (Taster_Start) == LOW) {            // Taster betätigt?
        Punkte_Tom [0] = 0; Punkte_Tom [1] = 0;         // Punkte nullen
        Punkte_Jerry [0] = 0; Punkte_Jerry [1] = 0;
        Ergebnisse();

        for (int i=0; i<5; i++) {                       // 5 Durchläufe pro Spiel
            lcd.setCursor(0,0);
            lcd.print("Tom   - Du bist dran");          // Tom beginnt
            Serial.print ("Start");                     // Seriell zu Nano "Start"
            while (Serial.available() <= 0);            // Auf Antwort warten
            Punkte_Tom [0] = Serial.parseInt();         // Ergebnis als Zahl
            Punkte_Tom [1] = Punkte_Tom [1] + Punkte_Tom [0];  // Punkte addieren
            Ergebnisse();                               // Punkte anzeigen
            lcd.setCursor(0,0);
            lcd.print("Jerry - Du bist dran");          // Jerry folgt
            Serial1.print ("Start");                    // Jerry, du bist dran
            while (Serial1.available() <= 0);           // Auf Antwort warten
            Punkte_Jerry [0] = Serial1.parseInt();      // Ergebnis als Zahl
            Punkte_Jerry [1] = Punkte_Jerry [1] + Punkte_Jerry [0];  // Punkte addieren
            Ergebnisse();                               // Punkte anzeigen
        }
        Spiel_Ende();
    }
}    
// ******************************************************************************

void Ergebnisse() {                                     // Spielstand anzeigen
          
    lcd.clear();
    lcd.setCursor(1,1);
    lcd.print("Tom");
    lcd.setCursor(9,1);
    lcd.print(Punkte_Tom [0]);
    lcd.setCursor(14,1);
    lcd.print(Punkte_Tom [1]);    
    
    lcd.setCursor(1,2);
    lcd.print("Jerry"); 
    lcd.setCursor(9,2);
    lcd.print(Punkte_Jerry [0]);
    lcd.setCursor(14,2);
    lcd.print(Punkte_Jerry [1]);
}
// ******************************************************************************

void Spiel_Ende() {                                     // Gewinner ermitteln
          
    lcd.setCursor(1,3);
    if (Punkte_Tom [1] == Punkte_Jerry [1]) {
        lcd.print("REMIS");
    }
    if (Punkte_Tom [1] > Punkte_Jerry [1]) {
        lcd.print("Tom hat gewonnen!");
    }    
    if (Punkte_Tom [1] < Punkte_Jerry [1]) {
        lcd.print("Jerry war besser!");
    }     
    delay(5000);
    lcd.clear();
}       
  

Die Testschaltung

Testschaltung

Testschaltung


Kurzvideo

Kurzvideo


Weitere Themen:



Google-Suche auf MEINE-SCHALTUNG.de :


Home Impressum Datenschutz