Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

Arduboy Clone mit Arduino Nano und I2C OLED-Display

Komponenten und Verbrauchsmaterialien

Arduino Nano R3
× 1
Grafik-OLED, 128 x 64
× 1
Summer
× 1
Tastschalter, von oben betätigt
× 6
RGB diffundierte gemeinsame Kathode
× 1
Widerstand 221 Ohm
× 3
Widerstand 10k Ohm
× 1

Notwendige Werkzeuge und Maschinen

3D-Drucker (generisch)
Lötkolben (generisch)

Über dieses Projekt

Arduboy ist ein Miniaturspielsystem in der Größe einer Kreditkarte. Es wird mit einem klassischen 8-Bit-Spiel installiert und kann aus einer online verfügbaren Bibliothek von Open-Source-Spielen umprogrammiert werden. Arduboy ist Open Source, sodass Sie das Programmieren lernen und Ihre eigenen Spiele erstellen können. Die Originalversion basiert auf dem Mikrocontroller ATmega32U4 und einem seriellen OLED-Display mit 128x64 Pixeln.

Die Konsole, deren Aufbau unten dargestellt ist, besteht aus Arduino Nano und der I2C-Version des OLED-Displays, die zu einem niedrigeren Preis viel einfacher zu finden ist. Sie können die erforderlichen Bibliotheken und den Code herunterladen unter:

https://github.com/harbaum/Arduboy2

Wenn Sie einen 3D-Drucker besitzen, können Sie auch .STL-Dateien einer möglichen Box-Option herunterladen, in der die Konsole installiert ist. Eine detaillierte Installationsanleitung ist auf derselben Site verfügbar. Es wird von einem Arduino Nano mit einem Lithium-Ionen-Akku von 3,7 V betrieben und funktioniert recht gut.

Ich habe viele Spiele auf dieser Konsole getestet, die alle großartig funktionieren:

- ArduBreakout

- Flipper

- Schattenläufer

- Schlange

- VIRUS-LQP-79

- Neunzehn43

und vieles mehr...

Das Schema ist unten gezeigt.

Als Beispiel präsentiere ich den Code für das ArduBreakout-Spiel, aber Sie können jedes andere Spiel auf der Arduboy-Site herunterladen, das mit dieser Konsolenversion kompatibel ist.

Code

  • ArduBreakout-Spiel
ArduBreakout-SpielArduino
/* Breakout Copyright (C) 2011 Sebastian Goscik Alle Rechte vorbehalten. Änderungen von Scott Allen 2016 (nach früheren Änderungen von ???) Diese Bibliothek ist freie Software; Sie können es unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben und/oder modifizieren; entweder Version 2.1 der Lizenz oder (nach Ihrer Wahl) eine spätere Version. */#include // Block im EEPROM um Highscores zu speichern#define EE_FILE 2Arduboy2 arduboy;BeepPin1 beep;const unsigned int FRAME_RATE =40; // Bildrate in Bildern pro Sekundeconst unsigned int COLUMNS =13; //Spalten von bricksconst unsigned int ROWS =4; //Bricksint-Reihen dx =-1; // Anfängliche Bewegung des Ballints dy =-1; //Anfängliche Bewegung von Ballint xb; // Startposition der Kugelnint yb; //Balls Startpositionboolean freigegeben; //Wenn der Ball vom Spieler freigegeben wurdeboolean pausiert =false; //Wenn das Spiel angehalten wurdebyte xPaddle; //X-Position von Paddleboolean isHit[ROWS][COLUMNS]; //Array, ob Steine ​​getroffen werden oder nichtboolean bounced=false; // Wird verwendet, um Double-Bounce-Glitchbyte-Leben zu beheben =3; //Menge des Livebyte-Levels =1; //Aktuelles Levelunsigned int score=0; //Punktzahl für das Spielunsigned int brickCount; //Anzahl der Bricks hitboolean pad, pad2, pad3; // Knopfdruckpuffer wird verwendet, um die Pausenwiederholung zu stoppen boolean oldpad, oldpad2, oldpad3;char text_buffer[16]; //Allgemeiner String bufferboolean start=false; //If in menu oder in gameboolean initialDraw=false;//Wenn das initiale Draw passiert istchar initials[3]; //Initialen verwendet in Highscore //Ball Bounds verwendet in Kollisionserkennungbyte leftBall;byte rightBall;byte topBall;byte bottomBall;//Brick Bounds verwendet in Kollisionserkennungbyte leftBrick;byte rightBrick;byte topBrick;byte bottomBrick;byte tick;void setup () {arduboy.begin(); beep.begin(); arduboy.setFrameRate (FRAME_RATE); arduboy.initRandomSeed();}void loop(){ // pausiere das Rendern, bis es Zeit für den nächsten Frame ist if (!(arduboy.nextFrame())) return; // Behandeln Sie das Timing und das Stoppen von Tönen beep.timer(); //Titelbildschirmschleife wechselt vom Titelbildschirm //und Highscores, bis FIRE gedrückt wird while (!start) { start =titleScreen(); if (!start) { start =displayHighScores(EE_FILE); } } //Anfangsebene zeichnen if (!initialDraw) { //Löschen des Bildschirms arduboy.clear(); // Wählt Schriftart // Zeichnet die neue Ebene level =1; Neues level(); Punktzahl =0; initialDraw=true; } if (lives>0) { drawPaddle(); // Spiel pausieren, wenn FIRE gedrückt wurde =arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON); if(pad ==true &&oldpad ==false &&freigegeben) { oldpad2 =false; // Erzwingt, dass Pad-Loop 2 einmal ausgeführt wird pause (); } oldpad =pad; drawBall(); if(brickCount ==ROWS * COLUMNS) { level++; Neues level(); } } else { drawGameOver(); if (Score> 0) { enterHighScore(EE_FILE); } arduboy.clear(); initialDraw=false; start=falsch; Leben=3; Neues level(); } arduboy.display();}void movePaddle(){ //Nach rechts bewegen if(xPaddle  0) { if (arduboy.pressed (LEFT_BUTTON)) { xPaddle-=2; } }}movid moveBall(){tick++; if (freigegeben) { // Ball bewegen if (abs (dx) ==2) { xb + =dx/2; // 2x Geschwindigkeit ist wirklich 1,5 Geschwindigkeit if (tick%2==0) xb +=dx/2; aufrechtzuerhalten. Sonst { xb +=dx; } yb=yb + dy; // Grenzen setzen leftBall =xb; rechter Ball =xb + 2; topBall =yb; BottomBall =yb + 2; // Von der oberen Kante abprallen if (yb <=0) {yb =2; dy =-dy; playTone(523, 250); } // Verliere ein Leben, wenn die Unterkante getroffen wird if (yb>=64) { arduboy.drawRect (xPaddle, 63, 11, 1, 0); xPaddel =54; yb=60; freigegeben =falsch; Leben--; playToneTimed(175, 500); wenn (zufällig (0, 2) ==0) { dx =1; } sonst { dx =-1; }} // Von der linken Seite abprallen if (xb <=0) {xb =2; dx =-dx; playTone(523, 250); } // Von der rechten Seite abprallen, wenn (xb>=WIDTH - 2) {xb =WIDTH - 4; dx =-dx; playTone(523, 250); } // Paddel abprallen if (xb+1>=xPaddle &&xb<=xPaddle+12 &&yb+2>=63 &&yb<=64) {dy =-dy; dx =((xb-(xPaddel+6))/3); // Wendet Spin auf den Ball an // verhindert geraden Abprall if (dx ==0) { dx =(random (0,2) ==1)? 1:-1; } playTone(200, 250); } //Bounce off Bricks for (byte row =0; row =topBrick &&leftBall <=rightBrick &&rightBall>=leftBrick) { Score(); brickCount++; isHit[Zeile][Spalte] =wahr; arduboy.drawRect(10*Spalte, 2+6*Zeile, 8, 4, 0); //Vertikale Kollision if (bottomBall> bottomBrick || topBall  rightBrick) { //Breize nur einen Stein pro Ballbewegung if(!bounced) { dx =- dx; xb +=dx; aufgeprallt =wahr; playTone(261, 250); } } } } } } // Zurücksetzen Bounce Bounce =false; aufrechtzuerhalten. Else {//Ball folgt Paddel xb=xPaddle + 5; // Ball loslassen, wenn FIRE gedrückt wurde pad3 =arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON); if (pad3 ==wahr &&oldpad3 ==falsch) { freigegeben =wahr; // Beim Loslassen zufällige Richtung auf den Ball anwenden if (random (0, 2) ==0) { dx =1; } sonst { dx =-1; } // Stellt sicher, dass die Kugel nach oben geht dy =-1; } oldpad3 =pad3; }}void drawBall () {// arduboy.setCursor (0,0); // arduboy.print (arduboy.cpuLoad ()); // arduboy.print(" "); arduboy.drawPixel(xb, yb, 0); arduboy.drawPixel(xb+1, yb, 0); arduboy.drawPixel(xb, yb+1, 0); arduboy.drawPixel(xb+1, yb+1, 0); moveBall(); arduboy.drawPixel(xb, yb, 1); arduboy.drawPixel(xb+1, yb, 1); arduboy.drawPixel(xb, yb+1, 1); arduboy.drawPixel(xb+1, yb+1, 1);}void drawPaddle(){ arduboy.drawRect(xPaddle, 63, 11, 1, 0); movePaddle(); arduboy.drawRect (xPaddle, 63, 11, 1, 1);}void drawGameOver () { arduboy.drawPixel (xb, yb, 0); arduboy.drawPixel(xb+1, yb, 0); arduboy.drawPixel(xb, yb+1, 0); arduboy.drawPixel(xb+1, yb+1, 0); arduboy.setCursor(37, 42); arduboy.print("Spiel vorbei"); arduboy.setCursor(31, 56); arduboy.print("Ergebnis:"); arduboy.print (Score); arduboy.display(); arduboy.delayShort(4000);}void pause(){ pausiert =wahr; // Pause auf den Bildschirm zeichnen arduboy.setCursor (52, 45); arduboy.print("PAUSE"); arduboy.display(); während (pausiert) {arduboy.delayShort(150); //Pause aufheben, wenn FIRE gedrückt wird pad2 =arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON); if (pad2 ==true &&oldpad2 ==false &&freigegeben) {arduboy.fillRect(52, 45, 30, 11, 0); pausiert=falsch; } oldpad2 =pad2; }}void Score () { score +=(level * 10);}void newLevel () { // Paddle ausziehen arduboy.drawRect (xPaddle, 63, 11, 1, 0); // Kugel ausziehen arduboy.drawPixel (xb, yb, 0); arduboy.drawPixel(xb+1, yb, 0); arduboy.drawPixel(xb, yb+1, 0); arduboy.drawPixel(xb+1, yb+1, 0); // Verschiedene Variablen ändern, um das Spiel zurückzusetzen xPaddle =54; yb =60; brickCount =0; freigegeben =falsch; // Zeichnet neue Bausteine ​​und setzt ihre Werte zurück für (byte row =0; row <4; row++) { for (byte column =0; column <13; column++) { isHit[row][column] =false; arduboy.drawRect(10*Spalte, 2+6*Zeile, 8, 4, 1); }} arduboy.display();} // Wird verwendet, um Bilder beim Lesen der Schaltfläche zu verzögern inputboolean pollFireButton (int n) { for (int i =0; i  0) { sprintf(text_buffer, "%c%c%c %u", initials[0], initials[1], initials[2], score); arduboy.setCursor(x + 24, y + (i*8)); arduboy.print (text_buffer); arduboy.display(); } } if (pollFireButton(300)) { return true; } falsch zurückgeben; arduboy.display();}boolean titleScreen(){ //Löschen des Bildschirms arduboy.clear(); arduboy.setCursor(16,22); arduboy.setTextSize(2); arduboy.print("AUSBRUCH"); arduboy.setTextSize(1); arduboy.display(); if (pollFireButton (25)) { true zurückgeben; } //Flash "Press FIRE" 5 mal for(byte i =0; i <5; i++) { // Zeichnet "Press FIRE" arduboy.setCursor (31, 53); arduboy.print("FEUER DRÜCKEN!"); arduboy.display(); if (pollFireButton (50)) { true zurückgeben; } // Entfernt "FEUER drücken" arduboy.setCursor (31, 53); arduboy.print(" "); arduboy.display(); if (pollFireButton (25)) { true zurückgeben; } } false zurückgeben;} // Funktion von nootropischem Design zum Hinzufügen von Highscoresvoid enterInitials () { Byteindex =0; arduboy.clear(); Initialen[0] =' '; Initialen[1] =' '; Initialen[2] =' '; while (wahr) {arduboy.display(); arduboy.clear(); arduboy.setCursor(16,0); arduboy.print("HOHE SCORE"); sprintf(text_buffer, "%u", Punktzahl); arduboy.setCursor(88, 0); arduboy.print (text_buffer); arduboy.setCursor(56, 20); arduboy.print(initials[0]); arduboy.setCursor(64, 20); arduboy.print (Initialen [1]); arduboy.setCursor(72, 20); arduboy.print (Initialen [2]); for(byte i =0; i <3; i++) {arduboy.drawLine (56 + (i*8), 27, 56 + (i*8) + 6, 27, 1); } arduboy.drawLine(56, 28, 88, 28, 0); arduboy.drawLine(56 + (Index*8), 28, 56 + (Index*8) + 6, 28, 1); arduboy.delayShort(70); if (arduboy.pressed(LEFT_BUTTON) || arduboy.pressed(B_BUTTON)) { if (index> 0) { index--; playToneTimed(1046, 80); } } if (arduboy.pressed(RIGHT_BUTTON)) { if (index <2) { index++; playToneTimed(1046, 80); } } if (arduboy.pressed(UP_BUTTON)) { Initialen[index]++; playToneTimed(523, 80); // A-Z 0-9 :-? !-/ ' ' if (initials[index] =='0') { initials[index] =' '; } if (initials[index] =='!') { initials[index] ='A'; } if (initials[index] =='[') { initials[index] ='0'; } if (initials[index] =='@') { initials[index] ='!'; }} if (arduboy.pressed(DOWN_BUTTON)) { Initialen[index]--; playToneTimed(523, 80); if (initials[index] ==' ') { initials[index] ='?'; } if (initials[index] =='/') { initials[index] ='Z'; } if (initials[index] ==31) { initials[index] ='/'; } if (initials[index] =='@') { initials[index] =' '; }} if (arduboy.pressed(A_BUTTON)) {playToneTimed(1046, 80); if (index <2) { index++; } sonst { zurück; } } }}void enterHighScore(byte file){ // Jeder EEPROM-Block hat 7 Highscores und jeder Highscore-Eintrag // ist 5 Byte lang:3 Bytes für Initialen und zwei Bytes für die Punktzahl. int-Adresse =Datei * 7 * 5 + EEPROM_STORAGE_SPACE_START; Byte hallo, lo; char tmpInitials[3]; unsigned int tmpScore =0; // Highscore-Verarbeitung for(byte i =0; i <7; i++) { hi =EEPROM.read(address + (5*i)); lo =EEPROM.read(Adresse + (5*i) + 1); if ((hi ==0xFF) &&(lo ==0xFF)) { // Die Werte sind nicht initialisiert, also behandle diesen Eintrag // als eine Punktzahl von 0. tmpScore =0; } else { tmpScore =(hi <<8) | siehe; } if (Score> tmpScore) { enterInitials(); for(byte j =i; j <7; j++) { hi =EEPROM.read (Adresse + (5*j)); lo =EEPROM.read(Adresse + (5*j) + 1); if ((hi ==0xFF) &&(lo ==0xFF)) {tmpScore =0; } else { tmpScore =(hi <<8) | siehe; } tmpInitials[0] =(char)EEPROM.read(Adresse + (5*j) + 2); tmpInitials[1] =(char)EEPROM.read(Adresse + (5*j) + 3); tmpInitials[2] =(char)EEPROM.read(Adresse + (5*j) + 4); // Punktzahl und Initialen in den aktuellen Steckplatz schreiben EEPROM.update(Adresse + (5*j), ((Punktzahl>> 8) &0xFF)); EEPROM.update(Adresse + (5*j) + 1, (Score &0xFF)); EEPROM.update(Adresse + (5*j) + 2, Initialen[0]); EEPROM.update(Adresse + (5*j) + 3, Initialen[1]); EEPROM.update(Adresse + (5*j) + 4, Initialen[2]); // tmpScore und tmpInitials enthalten jetzt das, was wir // in den nächsten Slot schreiben wollen. Score =tmpScore; initials[0] =tmpInitials[0]; Initialen[1] =tmpInitials[1]; Initialen [2] =tmpInitials [2]; } Punktzahl =0; Initialen[0] =' '; Initialen[1] =' '; Initialen[2] =' '; Rückkehr; } }} // Spielt einen Ton mit der angegebenen Frequenz für die angegebene Dauer.void playTone(unsigned int frequency, unsigned int Duration){ beep.tone(beep.freq(frequency), duration / (1000 / FRAME_RATE));} // Spielt einen Ton mit der angegebenen Frequenz für die angegebene Dauer mit // einer Verzögerung zum Timing des Tons. // Wird verwendet, wenn beep.timer() nicht aufgerufen wird.void playToneTimed(unsigned int frequency, unsigned int Duration){ beep.tone (beep.freq (Frequenz)); arduboy.delayShort(Dauer); beep.noTone();}

Kundenspezifische Teile und Gehäuse

3d_parts_ThLGvJvWga.rar

Schaltpläne


Herstellungsprozess

  1. Arduino I2C-Kommunikation mit Raspi 2 WIOT
  2. Handheld-Spielkonsole | Arduboy-Klon
  3. Arduino Pong-Spiel - OLED-Display
  4. Arduino-Temp. Monitor und Echtzeituhr mit 3.2 Display
  5. Einfacher Hindernissensor mit Arduino
  6. Mit Nextion Display spielen
  7. Arduino Nano:Steuerung von 2 Schrittmotoren mit Joystick
  8. DIY Voltmeter mit Arduino und einem Nokia 5110 Display
  9. Arduino- und OLED-basierte zelluläre Automaten
  10. Ein isolierter Analogeingang für Arduino