Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console

Onderdelen en Benodigdheden

Microchip ATtiny85 1
Grafische OLED, 128x64 1
SparkFun microB USB Breakout 1
Arduino Nano R3 (voor programmeren ATtiny85) 1

Benodigde Tools en Machines

  • Solderbout
  • 3D-printer

Apps en Online Services

  • Autodesk Fusion 360
  • Arduino IDE

Over dit Project

Inspiratie en Vorig Project

In december 2017 bouwde ik een Handheld Arduino Pong Console met Arduino Nano, OLED-scherm en twee knoppen.

ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console

Die was wel wat groot en onhandig. Recentelijk wilde ik oude projecten hercreëren, maar nu een heel kleine console voor Snake.

ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console

De Gekozen Componenten

Voor een kleine console kon ik geen Arduino-devboard gebruiken, dus koos ik de ATtiny85.

ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console

De ATtiny85 heeft voldoende I/O: twee ADC-pinnen, een I2C-poort en een GPIO-pin. Ik koos een eenvoudige 2-as joystick/schakelaar module – makkelijk te interfacen, alleen 3 signaalpinnen nodig.

ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console

Voor het display: DFRobot's 128x64 OLED-scherm – klein formaat, voldoende resolutie.

ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console

Solderen van het Systeem

Eerst soldeerde ik een ATtiny85 op een SOP-8 naar DIP-8 breakout PCB en vervolgens op een klein perforatieprintplaatje. Daarna twee headers: één voor programmeren, één voor het scherm. Vervolgens de analoge joystick-pinnen aansluiten en bedraden. Tot slot een micro-USB breakout bord voor voeding.

ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console
ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console

Behuizing Ontwerpen

De behuizing is ontworpen in Fusion 360. Ik begon met het maken en positioneren van de gebruikte componenten, daarna de behuizing eromheen.

ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console
ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console

Ik wilde een arcade-kastje uit de jaren '80 nabootsen, maar heel klein. Hieronder enkele renders:

ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console
ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console

De Game Programmeren

Snake is eenvoudig te programmeren. Maximale slangenlengte is 30 (RAM besparen): na 29 pixels eten wint de speler. Voor segmentbijhouder: een 2D-array met geordende paren per segment.

ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console

Bij elke stap van de kop cascaderen vorige posities naar beneden. Bij eten van een segment: nieuw segment op willekeurig punt. Botsingcontrole: itereren door segmentcoördinaten en controleren of kop-coördinaten overeenkomen. Ook botsing met muren = verlies.

ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console

Snake Spelen

Ik startte de console, wachtte tot het scherm voedsel en eerste segment laadde. Dan stuurt de joystick de slang in de juiste richting terwijl hij het voedsel opvraat. Leuk spel, geweldige tijdverdrijver in een miniatuur formaat.

ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console

Code

  • ATtiny85 Code
ATtiny85 Code (C/C++)
//#include 
#include 
U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g(U8G2_R0, /* clock=*/ 2, /* data=*/ 0, /* reset=*/ U8X8_PIN_NONE);

#define MAX_LENGTH 30
#define X 0
#define Y 1
#define JOYSTICK_X 2
#define JOYSTICK_Y 3
#define DIR_THRESH 300

uint8_t segmentPositions[MAX_LENGTH][2];
uint8_t headPosition[2] = {63, 31};
uint8_t foodPosition[2];
uint8_t tempPosition0[2];
uint8_t tempPosition1[2];
int segmentLength = 1;

void gameUpdate();
enum DIRECTIONS { RIGHT, DOWN, LEFT, UP } currentDirection;

void setup() {
  //TinyWireM.begin();
  u8g.begin();
  u8g.setPowerSave(0);
  pinMode(JOYSTICK_X, INPUT);
  pinMode(JOYSTICK_Y, INPUT);
  randomSeed(analogRead(0));
  beginGame();
}

void loop() {
  u8g.firstPage();
  do {
    gameUpdate();
    u8g.setColorIndex(1);
  } while(u8g.nextPage());
}

void beginGame(){
  currentDirection = RIGHT;
  spawnFood();
  delay(1000);
}

bool checkCollisions(){
  for(int i=1; i= 128) return 1;
  else if(headPosition[Y] <= 0 || headPosition[Y] >= 64) return 1;
  return false;
}

void spawnFood(){
  int randomX = random(5, 123);
  int randomY = random(5, 60);
  foodPosition[X] = randomX;
  foodPosition[Y] = randomY;
}

void checkFoodEaten(){
  if(headPosition[X] == foodPosition[X] || headPosition[Y] == foodPosition[Y]){
    segmentLength += 1;
    spawnFood();
  }
}

void updateDirection(){
  int joy_x_val = analogRead(JOYSTICK_X);
  int joy_y_val = analogRead(JOYSTICK_Y);
  if(joy_x_val <= DIR_THRESH) currentDirection = LEFT;
  else if(joy_x_val >= 1023-DIR_THRESH) currentDirection = RIGHT;
  else if(joy_y_val <= DIR_THRESH) currentDirection = UP;
  else if(joy_y_val >= 1023-DIR_THRESH) currentDirection = DOWN;
}

void displaySegments(){
  for(int segment=0; segment < segmentLength; segment++){
    u8g.drawPixel(segmentPositions[segment][X], segmentPositions[segment][Y]);
  }
  u8g.drawPixel(foodPosition[X], foodPosition[Y]);
}

void gameUpdate(){
  updateDirection();
  tempPosition0[X] = headPosition[X];
  tempPosition0[Y] = headPosition[Y];
  switch(currentDirection){
    case UP: headPosition[Y] -= 1; break;
    case DOWN: headPosition[Y] += 1; break;
    case LEFT: headPosition[X] -= 1; break;
    case RIGHT: headPosition[X] += 1; break;
  }
  // Update segmentposities relatief aan kop
  for(int segment=1; segment < segmentLength; segment+= 2){
    tempPosition1[X] = segmentPositions[segment][X];
    tempPosition1[Y] = segmentPositions[segment][Y];
    segmentPositions[segment][X] = tempPosition0[X];
    segmentPositions[segment][Y] = tempPosition0[Y];
    tempPosition0[X] = segmentPositions[segment+1][X];
    tempPosition0[Y] = segmentPositions[segment+1][Y];
    segmentPositions[segment+1][X] = tempPosition1[X];
    segmentPositions[segment+1][Y] = tempPosition1[Y];
  }
  displaySegments();
  checkFoodEaten();
  if(checkCollisions()) endGame();
  if(segmentLength >= MAX_LENGTH) endGame();
  delay(50);
}

void endGame(){
  segmentLength = 1;
  headPosition[0] = 63;
  headPosition[1] = 31;
  beginGame();
}

Zorg dat je eerst de U8g2lib installeert.

Aangepaste Onderdelen en Behuizingen

(Bestanden beschikbaar op projectpagina)

Schema's

ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console

Productieproces

  1. TinyML Taaldetector met Edge Impulse op Arduino Nano 33 BLE Sense
  2. Bouw een real-time gyroscoop-spel met Arduino Nano & MPU-6050 sensor
  3. Arduino Digitale Dobbelsteen: Bouw Je Eigen LCD-willekeurige Getalgenerator
  4. Bouw Je Eigen 37-LED Roulette-spel met Arduino Nano
  5. Draagbare Afstandsdetector – Arduino Nano DIY Kit met HC-SR04, 18650 Accu en 3D-geprinte Behuizing
  6. Een audio-reactieve bureaulamp bouwen met Arduino Nano
  7. Koper Elektrolyseren Project: Bouw een Slim Systeem met Arduino UNO
  8. NeoPixel Matrix Pong op Arduino Nano: Bouw je eigen neon Pong-spel
  9. Indrukwekkende Lichtsequenties Maken met Arduino en Shift Register
  10. Slimme stopcontact: 120V Arduino-gebaseerde slimme uitgang met Real-Time Clock
  11. Arduino Beveiligingssysteem: Slimme Bewegingsdetectie & Alarm