Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Arduboy Clone avec Arduino Nano et écran OLED I2C

Composants et fournitures

Arduino Nano R3
× 1
Graphique OLED, 128 x 64
× 1
Sonnerie
× 1
Commutateur tactile, actionné par le haut
× 6
Cathode commune diffuse RVB
× 1
Résistance 221 ohm
× 3
Résistance 10k ohm
× 1

Outils et machines nécessaires

Imprimante 3D (générique)
Fer à souder (générique)

À propos de ce projet

Arduboy est un système de jeu miniature de la taille d'une carte de crédit. Il est installé avec un jeu 8 bits classique et peut être reprogrammé à partir d'une bibliothèque de jeux open source disponibles en ligne. Arduboy est open source, vous pouvez donc apprendre à coder et créer vos propres jeux. La version originale est basée sur un microcontrôleur ATmega32U4 et un écran OLED série 128x64 pixels.

La console dont la construction est représentée ci-dessous est composée d'Arduino Nano et de la version I2C de l'écran OLED qui peut être beaucoup plus facile à trouver à un prix inférieur. Vous pouvez télécharger les bibliothèques et le code nécessaires sur :

https://github.com/harbaum/Arduboy2

Si vous possédez une imprimante 3D, vous pouvez également télécharger les fichiers .STL d'une option de boîte possible dans laquelle la console est installée. Un guide d'installation détaillé est disponible sur le même site. Il est alimenté par un Arduino Nano avec une batterie lithium-ion de 3,7 V et il fonctionne plutôt bien.

J'ai testé de nombreux jeux sur cette console, qui fonctionnent tous très bien :

- ArduBreakout

- Flipper

- Shadow-Runner

- Serpent

- VIRUS-LQP-79

- Dix-neuf43

et bien d'autres...

Le schéma est présenté ci-dessous.

A titre d'exemple, je présente le code du jeu ArduBreakout, mais vous pouvez télécharger n'importe quel autre jeu sur le site d'Arduboy compatible avec cette version de console.

Code

  • Jeu ArduBreakout
Jeu ArduBreakoutArduino
/* Breakout Copyright (C) 2011 Sebastian Goscik Tous droits réservés. Modifications par Scott Allen 2016 (après modifications précédentes par ???) Cette bibliothèque est un logiciel libre; vous pouvez le redistribuer et/ou le modifier selon les termes de la licence publique générale limitée GNU telle que publiée par la Free Software Foundation ; soit la version 2.1 de la Licence, soit (à votre choix) toute version ultérieure. */#include // bloc dans l'EEPROM pour enregistrer les meilleurs scores#define EE_FILE 2Arduboy2 arduboy;BeepPin1 bip;const unsigned int FRAME_RATE =40; // Fréquence d'images en images par secondeconst unsigned int COLUMNS =13; //Colonnes de bricksconst unsigned int ROWS =4; //Rangées de bricksint dx =-1; //Mouvement initial du ballint dy =-1; //Mouvement initial de ballint xb; //Position de départ des boulesint yb; //Position booléenne de départ des boules libérées ; //Si la balle a été lâchée par le joueurboolean paused =false; //Si le jeu a été mis en pausebyte xPaddle; //Position X de paddleboolean isHit[ROWS][COLUMNS] ; // Tableau indiquant si les briques sont touchées ou notboolean bounced=false ; // Utilisé pour corriger le double rebond glitchbyte lives =3; //Quantité de niveau de livesbyte =1; //niveau actuel unsigned int score=0 ; //Score pour le gameunsigned int brickCount; // Quantité de briques hitboolean pad, pad2, pad3; // Tampon d'appui sur le bouton utilisé pour arrêter la répétition de la répétitionboolean oldpad, oldpad2, oldpad3;char text_buffer[16]; //Chaîne générale bufferboolean start=false; //Si dans le menu ou dans gameboolean initialDraw=false;//Si le tirage initial a eu lieuchar initials[3]; //Initiales utilisées dans le score élevé//Ball Bounds utilisés dans la détection de collisionbyte leftBall;byte rightBall;byte topBall;byte bottomBall;//Brick Bounds utilisés dans la détection de collisionbyte leftBrick;byte rightBrick;byte topBrick;byte bottomBrick;byte tick;void setup (){ arduboy.begin(); beep.begin(); arduboy.setFrameRate(FRAME_RATE); arduboy.initRandomSeed();}void loop(){ // interrompt le rendu jusqu'à ce qu'il soit temps pour la prochaine image if (!(arduboy.nextFrame())) return ; // Gère le timing et l'arrêt des tonalités beep.timer(); //La boucle de l'écran de titre passe de l'écran de titre //et aux meilleurs scores jusqu'à ce que FIRE soit enfoncé pendant que (!start) { start =titleScreen(); if (!start) { start =displayHighScores(EE_FILE); } } //Niveau initial de dessin if (!initialDraw) { //Efface l'écran arduboy.clear(); //Sélectionne la police //Dessine le nouveau niveau level =1; nouveauNiveau(); note =0 ; initialDraw=true ; } if (vie>0) { drawPaddle(); // Pause du jeu si FIRE a appuyé sur pad =arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON); if(pad ==true &&oldpad ==false &&release) { oldpad2 =false; //Force la boucle de pad 2 à s'exécuter une fois pause(); } oldpad =pad; drawBall(); if(brickCount ==LIGNES * COLONNES) { niveau++; nouveauNiveau(); } } else { drawGameOver(); if (score> 0) { enterHighScore(EE_FILE); } arduboy.clear(); initialDraw=false ; début=faux ; vies=3 ; nouveauNiveau(); } arduboy.display();}void movePaddle(){ //Déplacer vers la droite if(xPaddle  0) { if (arduboy.pressed(LEFT_BUTTON)) { xPaddle-=2; } }}void moveBall(){ tick++; if(released) { //Déplacer la balle if (abs(dx)==2) { xb +=dx/2; // La vitesse 2x vaut vraiment la vitesse 1.5 if (tick%2==0) xb +=dx/2; } else { xb +=dx; } yb=yb + dy; //Définir les limites leftBall =xb; boule droite =xb + 2 ; topBall =yb; bottomBall =yb + 2 ; //Rebond sur le bord supérieur if (yb <=0) { yb =2; dy =-dy; playTone (523, 250); } // Perdre une vie si le bord inférieur atteint if (yb>=64) { arduboy.drawRect(xPaddle, 63, 11, 1, 0); xPagaie =54 ; yb=60 ; libéré =faux ; des vies--; playToneTimed(175, 500); if (aléatoire (0, 2) ==0) { dx =1; } else { dx =-1; } } //Rebond sur le côté gauche if (xb <=0) { xb =2; dx =-dx; playTone (523, 250); } //Rebond du côté droit if (xb>=WIDTH - 2) { xb =WIDTH - 4; dx =-dx; playTone (523, 250); } //Rebondir sur la raquette if (xb+1>=xPaddle &&xb<=xPaddle+12 &&yb+2>=63 &&yb<=64) { dy =-dy; dx =((xb-(xPalette+6))/3); //Applique l'effet sur la balle // empêche le rebond direct if (dx ==0) { dx =(random(0,2) ==1) ? 1 :-1 ; } playTone(200, 250); } //Rebondir sur les briques pour (octet ligne =0 ; ligne =topBrick &&leftBall <=rightBrick &&rightBall>=leftBrick) { Score(); Nombre de briques++ ; isHit[ligne][colonne] =vrai ; arduboy.drawRect (10*colonne, 2+6*ligne, 8, 4, 0); // Collision verticale if (bottomBall> bottomBrick || topBall  rightBrick) { //Ne rebondit qu'une seule brique chaque balle se déplace if(!bounced) { dx =- dx; xb +=dx; rebondi =vrai; playTone(261, 250); } } } } } } //Réinitialiser le rebond rebondi =false; } else { //La balle suit la pagaie xb=xPaddle + 5; //Lâcher la balle si FIRE a appuyé sur pad3 =arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON); if (pad3 ==true &&oldpad3 ==false) { release =true; //Appliquer une direction aléatoire à la balle au relâchement if (random(0, 2) ==0) { dx =1; } else { dx =-1; } // S'assure que la boule se dirige vers le haut 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("Game Over"); arduboy.setCursor(31, 56); arduboy.print("Score :"); arduboy.print(score); arduboy.display(); arduboy.delayShort(4000);}void pause(){ paused =true; // Dessiner une pause à l'écran arduboy.setCursor(52, 45); arduboy.print("PAUSE"); arduboy.display(); while (pause) { arduboy.delayShort(150); //Reprendre la pause si FIRE est enfoncé pad2 =arduboy.pressed(A_BUTTON) || arduboy.pressed(B_BUTTON); if (pad2 ==true &&oldpad2 ==false &&release) { arduboy.fillRect(52, 45, 30, 11, 0); en pause=faux ; } oldpad2 =pad2; }}void Score(){ score +=(level*10);}void newLevel(){ //Undraw paddle arduboy.drawRect(xPaddle, 63, 11, 1, 0); //Retirer la balle arduboy.drawPixel(xb, yb, 0); arduboy.drawPixel(xb+1, yb, 0); arduboy.drawPixel(xb, yb+1, 0); arduboy.drawPixel(xb+1, yb+1, 0); //Modifier diverses variables pour réinitialiser le jeu xPaddle =54; yb =60 ; Nombre de briques =0 ; libéré =faux ; // Dessine de nouvelles briques et réinitialise leurs valeurs pour (byte row =0; row <4; row++) { for (byte column =0; column <13; column++) { isHit[row][column] =false; arduboy.drawRect (10*colonne, 2+6*ligne, 8, 4, 1); } } arduboy.display();}//Utilisé pour retarder les images lors de la lecture du bouton 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)) { renvoie vrai ; } renvoie faux ; arduboy.display();}boolean titleScreen(){ //Efface l'écran arduboy.clear(); arduboy.setCursor(16,22); arduboy.setTextSize(2); arduboy.print("BREAKOUT"); arduboy.setTextSize(1); arduboy.display(); if (pollFireButton (25)) { return true; } //Flash "Press FIRE" 5 fois for(byte i =0; i <5; i++) { // Dessine "Press FIRE" arduboy.setCursor(31, 53); arduboy.print("APPUYEZ SUR LE FEU !"); arduboy.display(); if (pollFireButton (50)) { return true; } //Supprime "Appuyez sur FIRE" arduboy.setCursor(31, 53); arduboy.print(" "); arduboy.display(); if (pollFireButton (25)) { return true; } } return false;}//Fonctionne par conception nootropique pour ajouter des scores élevésvoid enterInitials(){ byte index =0; arduboy.clear(); initiales[0] =' '; initiales[1] =' '; initiales[2] =' '; while (true) { arduboy.display(); arduboy.clear(); arduboy.setCursor(16,0) ; arduboy.print("Score ÉLEVÉ"); sprintf(text_buffer, "%u", score); arduboy.setCursor(88, 0); arduboy.print(text_buffer); arduboy.setCursor(56, 20); arduboy.print(initiales[0]); arduboy.setCursor(64, 20); arduboy.print(initiales[1]); arduboy.setCursor(72, 20); arduboy.print(initiales[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)) { initiales[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)) { initiales[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++; } else { retour; } } }}void enterHighScore(byte file){ // Chaque bloc d'EEPROM a 7 scores élevés, et chaque entrée de score élevé // fait 5 octets :3 octets pour les initiales et deux octets pour le score. adresse int =fichier * 7 * 5 + EEPROM_STORAGE_SPACE_START; octet salut, lo; char tmpInitials[3]; tmpScore entier non signé =0 ; // Traitement des scores élevés pour (octet i =0; i <7; i++) { hi =EEPROM.read(adresse + (5*i)); lo =EEPROM.read(adresse + (5*i) + 1); if ((hi ==0xFF) &&(lo ==0xFF)) { // Les valeurs ne sont pas initialisées, alors traitez cette entrée // comme un score de 0. tmpScore =0; } else { tmpScore =(salut <<8) | voila ; } if (score> tmpScore) { enterInitials(); for(byte j =i; j <7; j++) { hi =EEPROM.read(address + (5*j)); lo =EEPROM.read(adresse + (5*j) + 1); if ((hi ==0xFF) &&(lo ==0xFF)) { tmpScore =0; } else { tmpScore =(salut <<8) | voila ; } 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); // écrire la partition et les initiales dans l'emplacement actuel EEPROM.update(adresse + (5*j), ((score>> 8) &0xFF)); EEPROM.update(adresse + (5*j) + 1, (score &0xFF)); EEPROM.update(adresse + (5*j) + 2, initiales[0]); EEPROM.update(adresse + (5*j) + 3, initiales[1]); EEPROM.update(adresse + (5*j) + 4, initiales[2]); // tmpScore et tmpInitials contiennent maintenant ce que nous voulons // écrire dans le slot suivant. score =tmpScore ; initiales[0] =tmpInitials[0]; initiales[1] =tmpInitials[1]; initiales[2] =tmpInitials[2]; } note =0 ; initiales[0] =' '; initiales[1] =' '; initiales[2] =' '; retourner; } }}// Joue une tonalité à la fréquence spécifiée pour la durée spécifiée.void playTone(fréquence int non signée, durée int non signée){ beep.tone(beep.freq(fréquence), durée / (1000 / FRAME_RATE));} // Joue une tonalité à la fréquence spécifiée pendant la durée spécifiée en utilisant// un délai pour chronométrer la tonalité.// Utilisé lorsque beep.timer () n'est pas appelé. void playToneTimed (fréquence int non signée, durée int non signée) { beep.tone(beep.freq(fréquence)); arduboy.delayShort(durée); bip.noTone();}

Pièces et boîtiers personnalisés

3d_parts_ThLGvJvWga.rar

Schémas


Processus de fabrication

  1. Communication Arduino I2C avec Raspi 2 WIOT
  2. Console de jeu portable | Clone Arduboy
  3. Jeu Arduino Pong - Écran OLED
  4. Arduino Temp. Moniteur et horloge en temps réel avec affichage 3.2
  5. Capteur d'obstacles simple avec Arduino
  6. Jouer avec Nextion Display
  7. Arduino Nano :contrôler 2 moteurs pas à pas avec joystick
  8. Automates cellulaires basés sur Arduino et OLED
  9. Une entrée analogique isolée pour Arduino