Snake Arduino?! Dein Nokia 3310 läuft nicht mehr? Jetzt selbst bauen!

Snake Arduino?! Dein Nokia 3310 läuft nicht mehr? Jetzt selbst bauen!

Arduino, Projekte
21 September 2020

Falls du dein altes Nokia Handy vermisst, kannst du dir mit Hilfe dieses Tutorials dein altes Lieblingsgame, Snake, ganz einfach mit einem Arduino nachbauen.

Snake ist den Meisten als eines der beliebtesten Handyspieler aller Zeiten bekannt und war in den 2000ern auf jedem Nokia Handy vorinstalliert. So konnten sich Millionen Jugendliche, zu denen du eventuell auch gehört hast, die Langeweile vertreiben. 2017 hat Nokia das 3310 wiederaufleben lassen und Snake wiederfuhr eine Neuauflage. Diese konnte allerdings nicht mit dem 2000 auf dem Nokia 3210 herausgekommenen Original mithalten.

Snake war jedoch nicht nur ein Handyspiel, sondern existierte schon deutlich früher. Die erste Version existierte schon 1979 und hieß „Hyper-Wurm“. Dieses Spiel lief auf dem TRS-80, einem der ersten Seriencomputern der Welt. Jetzt bist du an der Reihe das Spiel nachzubauen.

Dazu brauchst du nur ein paar Teile aus unserem Shop!

Folgende Hardware benötigst du für das Snake Arduino Projekt

WARENKORB

Alle für dieses Projekt notwendigen Artikel landen mit einem Klick auf den Button direkt in deinem Warenkorb, sofern sie in unserem Shop verfügbar sind. Kontrolliere daher deinen Warenkorb genau!

Das fertige Snake Game in Action.
Das fertige Snake Game in Action!

Was ist ein Schieberegister?

Das wohl wichtigste Bauteil für dieses Projekt ist das Schieberegister 74HC595. Dieser integrierte Schaltkreis ermöglicht es uns die Ausgabekanäle der Arduino-Boards fast beliebig zu erweitern. Dies kommt uns bei diesem Projekt zugute, da wir deutlich mehr Ausgabekanäle benötigen, um die LED-Matrix anzusteuern.

Ein Schieberegister funktioniert folgendermaßen. Serielle Daten werden in parallele Daten umgewandelt. Das bedeutet, die Sequenz An-An-Aus-An-An-An-Aus-An (also 11011101) wird an das Schieberegister gesendet, welches diese Daten an seine eigenen Output-Pins (von 1 bis 8) schickt. Es schaltet also seinen Pin1 an, Pin2 auch, Pin 3 aus … und so weiter. Diese Pins bleiben in ihrem Zustand, bis über den Daten-In-Pin des Schieberegister neue Informationen ankommen.

Das Schieberegister 74HC595
das Schieberegister 74HC595

Das Schieberegister erhält die seriell gesendeten Daten über den DS Pin. Damit es die einzelnen Daten unterscheiden kann, wird gleichzeitig über den Shift Register Clock Pin (SHCP) eine Art Herzschlag gesendet. Als letztes benötigt das 74HC595 noch eine Reset-Verbindung zum Arduino-Board. Es werden somit nur drei digitale Outputs vom Arduino genutzt.

Interessanter Weise lassen sich mehrere Schieberegister wie in einer Reihenschaltung hintereinanderschalten. Dadurch erhöht sich die Anzahl möglicher Outputs, ohne dass mehr Arduino-Pins verwendet werden müssen.

Schieberegister 74HC595 in Reihenschaltung.
Reihenschaltung von zwei Schieberegistern

Weitere Informationen über Schieberegister kannst du dem Datenblatt entnehmen.

Das Schieberegister 74HC595 Verkabelung auf dem Breadboard.
Verkabelung der Schieberegister auf dem Breadboard.

So baust du dir dein Arduino Snake-Game

Als allerersten Schritt musst du dir die Arduino IDE auf deinem Computer installieren. Diese findest du hier.

Leider sind nicht alle Bibliotheken standardmäßig in der Arduino IDE verfügbar, aus diesem Grund musst du dir zunächst die „SchiftRegister74HC595“ Bibliothek herunterladen und in die Arduino IDE einbinden.

Unter Linux kannst du dir die Library einfach mit dem folgenden Terminalbefehl herunterladen:

git clone https://github.com/Simsso/ShiftRegister74HC595.git

Solltest du Windows nutzen folge diesem Link. Klicke dann auf „Code“ und „Download Zip“.

Download der ZIP-Datei von Github.
Klicke auf den grünen Button!

Die soeben von dir heruntergeladene Bibliothek wird nun in die Arduino IDE eingebunden. Dazu folge dem folgenden Pfad: Arduino IDE> Sketch> Bibliothek einbinden> ZIP Bibliothek hinzufügen.

So bekommst du den Code auf deinen Arduino

Damit Snake auf deinem Arduino läuft musst du den folgenden C++ Code in die Arduino IDE abtippen oder kopieren.

// https://www.blog.berrybase.de/

// SNAKE GAME on 8x8 LED matrix with Arduino and 2 74HC595 shift register.

// Pin connected to Pin 12 of 74HC595 (Latch)
int latchPin = 11;

// Pin connected to Pin 11 of 74HC595 (Clock)
int clockPin = 10;

// Pin connected to Pin 14 of 74HC595 (Data)
int dataPin = 12;

// Screen
byte led[8];

////////////////////////////
int X= A0;                           // X Axe                              

int Y= A1;                           // Y Axe        
///////////////////////////

// game variables
typedef struct Link 
{
  int x;
  int y;
  struct Link * next;
} Link;

Link * pHead = NULL;
Link * pTail = NULL;

int curDirection = 4;
int newDirection = 4;
int appleX = 5;
int appleY = 5;

unsigned long oldTimer, curTimer;

boolean dead = 0;

//////////////////////////

void setup()                      //Pins Setup 
{
 
  pinMode(X, INPUT);                       

  pinMode(Y, INPUT);

  // set pins to output
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
  // set button pins to input

  Serial.begin(9600);
  // clear screen
  clrscr();
}

//////////////////////////

void loop()                       //Hauptprogramm

{
  
  snakeInit();                    //Snake Intialisierung 
  screenUpdate();
  oldTimer = millis();
  curTimer = millis();

  while(!dead) 
  {
    curTimer = millis();
    
    setDirection();
    
    if(curTimer-oldTimer >= 320) {
      curDirection = newDirection;
      moveSnake(curDirection);
      screenUpdate();
      oldTimer = millis();
    }
    
    // update screen
    screenDisplay();
  }
  
  int count = 0;
  while(count<8) 
  {
    curTimer = millis();
    if(curTimer-oldTimer >= 100) {
      led[count]=B11111111;
      oldTimer = millis();
      count++;
    }
    screenDisplay();
  }
  
  clrscr();
  
  while(1) 
  {
    curTimer = millis();
    if(curTimer-oldTimer >= 700) {
      for(int i=0; i<8; i++) {
        led[i]=~led[i];
      }
      oldTimer = millis();
    }
    screenDisplay();
  }
  
  
}

//////////////////////////

void addHead(int x, int y)         //Snake Kopf hinzufügen
{
  Link *temp;
  temp = (Link*) malloc (sizeof(Link));
    
  // create new head
  temp->x = x;
  temp->y = y;
  temp->next = NULL;
    
  if(pHead!=NULL)
    pHead->next = temp;
    
  // point to new head
  pHead = temp;
}

//////////////////////////

void snakeInit()                    //Snake INIT
{
  int x = 3;
  int y = 3;
  for (int i=0; i<2; i++, x++) {
    addHead(x,y);
    if (i == 0)
      pTail = pHead;
  }
}

//////////////////////////

void setDirection()                 //Richtung
{           
  if(analogRead(Y)>600) {
    if(curDirection!=2)
      newDirection = 1;
  }
  if(analogRead(Y)<400) {
    if(curDirection!=1)
      newDirection = 2;
  }
  if(analogRead(X)>600) {
    if(curDirection!=4)
      newDirection = 3;
  }
  if(analogRead(X)<400) {
    if(curDirection!=3)
      newDirection = 4;
  }
}

//////////////////////////

void moveSnake(int direction)      //Snake Bewegung
{
  int newX = pHead->x;
  int newY = pHead->y;
  if(direction==1)
    newY--;
  if(direction==2)
    newY++;
  if(direction==3)
    newX--;
  if(direction==4)
    newX++;

  if(newX > 8)
    newX=1;
  if(newX < 1)
    newX=8;
  if(newY > 8)
    newY=1;
  if(newY < 1)
    newY=8;

  dead |= check(newX, newY);

  if(!dead) {
    if(newX==appleX && newY==appleY) {
      addHead(newX, newY);
      newApple();
    }
    else {
      Link *temp = pTail;
            
      // point to new tail
      pTail = pTail->next;
            
      // new head
      pHead->next = temp;
      pHead = temp;
            
      pHead->x = newX;
      pHead->y = newY;      
      pHead->next = NULL;
    } 
  }
}

//////////////////////////

void newApple()                   //Neuer Apfel setzen
{
  boolean check = 0;
  Link * ptr = pTail;
  do {
    check = 0;
    appleX = random(7) + 1;
    appleY = random(7) + 1;
    Serial.println(appleX);
    while(ptr!=NULL) {
      if(appleX==(ptr->x) && appleY==(ptr->y)) {
        check = 1;
        break;
      }
      ptr = ptr->next;
    }
  } while (check == 1);
}

//////////////////////////
    
boolean check(int x, int y)       //Prüfen
{
  Link *ptr;
  ptr = pTail;
  while(ptr!=NULL)
  {
    if(x==ptr->x && y==ptr->y)
      return 1;
    ptr=ptr->next;
  }
  
  return 0;
}


//////////////////////////
  
// display driver                

void screenUpdate()              //Screen Aktualisierung
{
  Link * ptr;
  ptr = pTail;
  
  clrscr();
  while(ptr!=NULL) {
    led[ptr->y-1] = led[ptr->y-1] | (1<<(8-ptr->x));
    ptr = ptr->next;
  }
  
  led[appleY-1] = led[appleY-1] | (1<<(8-appleX));
}  

//////////////////////////
  
void screenDisplay()             //Show Screen 

{
  byte row = B10000000;

  for (byte k = 0; k < 8; k++) {
    // Open up the latch ready to receive data
    digitalWrite(latchPin, LOW);
    
    shiftData(row); // if use PNP transitors
    // shiftData(row);
    shiftData(led[k]);
    // Close the latch, sending the data in the registers out to the matrix
    digitalWrite(latchPin, HIGH);
    row = row >> 1;
  }
}

//////////////////////////

void clrscr()                    //Clear Screen
{
  for(int i=0; i<8; i++) {
    led[i] = B00000000;
  }
}

//////////////////////////

void shiftData(byte data)        //Start Schifting 
{
  // Shift out 8 bits LSB first,
  // on rising edge of clock
  boolean pinState;

  //clear shift register read for sending data
  digitalWrite(dataPin, LOW);

  // for each bit in dataOut send out a bit
  for (int i=0; i<8; i++) 
  {
    //set clockPin to LOW prior to sending bit
    digitalWrite(clockPin, LOW);

    // if the value of data and (logical AND) a bitmask
    // are true, set pinState to 1 (HIGH)
    if (data & (1<<i)) 
    {
      pinState = HIGH;
    }
    else 
    {
      pinState = LOW;
    }

    //sets dataPin to HIGH or LOW depending on pinState
    digitalWrite(dataPin, pinState);

    //send bit out on rising edge of clock
    digitalWrite(clockPin, HIGH);
    digitalWrite(dataPin, LOW);
  }

  //stop shifting
  digitalWrite(clockPin, LOW);
}

Um den Code auf deinen Arduino zu laden, musst du zunächst in der Arduino IDE deinen Arduino auswählen, damit die IDE weiß mit welchem Board dein Computer verbunden ist. Nun kannst du deinen Arduino mit deinem Computer unter Zuhilfenahme des USB-Kabels verbinden. Den Code lädst du auf deinen Arduino mit Hilfe des Pfeils links – oben in der Ecke. Eine Ausführliche Anleitung kannst du dir auch hier bei YouTube ansehen.

So baust du die Schaltung auf

Damit du Snake spielen kannst musst du nicht nur den Code auf den Arduino laden, sondern auch alle Bauteile miteinander verbinden.

Der Schaltplan sieht auf den ersten Blick etwas komplex aus. Im Grunde werden aber nur die drei erwähnten digitalen Outputs vom Arduino- Board mit dem Schieberegister 74HC595 verbunden. Darüber hinaus wird der Chip mit GND und 5V+ verbunden.

Der komplette Schaltplan des Snake Projekts.
Der komplette Schaltplan.

Das fertige Snake Projekt.
Das fertige Snake Arduino Projekt.

Wichtig! Der Clock Pin des Schieberegisters (SHCP) muss über einen 100nF Keramikkondensator (Aufdruck 104) mit dem GND verbunden werden!

Die Pins der Matrix werden sowohl mit dem Schieberegister aus auch mit den Transistoren in folgender Weise verbunden:

Matrix:

Der Aufbau der LED Matrix.
Der Aufbau der LED-Matrix.

Pins : 13 , 3 , 4 , 10 , 6 , 11 ,15 , 16 (Matrix Rows(-ve)) →   (BC547)

Pins : 9 , 14 , 8 , 12 , 1 , 7 , 2 , 5 (Matrix Col(+ve)) →  (74HC595)

Anschluss der LED-Matrik für das Snake Projekt.
Anschluss der LED Matrix.

Nun must du noch den Joystick in deine Schaltung einbinden. Auf dem Schaltplan sieht das Ganze folgendermaßen aus:

Die Schaltung des Snake Projekts.
Die Schaltung des Snake Projekts.

Wie du sehen kannst wurden die Pins des Jopysticks auf die folgende Weise mit deinem Arduino verbunden:

Joystick           Arduino

GND →   GND

+5v →   5v

VRx →   A0 (X Axe)

VRy →   A1 (Y Axe)

SW →   RESET

Der Joystick zur Steuerung des Snake Spiels.
Der Joystick.

Jetzt ist dein Snake-Game fertig und du kannst spielen!

Jetzt hast du sowohl den Code auf deinen Arduino geladen als auch die Schaltung nachgebaut und du bist bereit zum Spielen. Das Spiel startet einfach nachdem du den Joystick bewegt hast.

Alle Teile für dieses Projekt kannst du in unserem Shop finden. Stöbere doch einfach ein bisschen durch unser Sortiment!

Da es wahrscheinlich eine Ewigkeit her ist, dass du Snake spielen konntest lassen wir dich nun direkt in Ruhe und wünschen dir viel Spaß beim Spielen.

Dein BerryBase-Team!

Du willst mehr heiße Arduino Projekte? Schaue dir jetzt hier unsere Sammlung an Tutorials an!

Wie hilfreich war dieser Beitrag?

Klicke auf die Sterne um zu bewerten!

Durchschnittliche Bewertung 5 / 5. Anzahl Bewertungen: 6

Bisher keine Bewertungen! Sei der Erste, der diesen Beitrag bewertet.

Kommentare

Hinterlasse ein Kommentar

XHTML: Sie können diese Tags verwenden: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>