Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Arduboy Clone con Arduino Nano y pantalla OLED I2C

Componentes y suministros

Arduino Nano R3
× 1
OLED gráfico, 128 x 64
× 1
Buzzer
× 1
Interruptor táctil, accionado por la parte superior
× 6
Cátodo común difuso RGB
× 1
Resistencia 221 ohm
× 3
Resistencia de 10k ohmios
× 1

Herramientas y máquinas necesarias

Impresora 3D (genérica)
Soldador (genérico)

Acerca de este proyecto

Arduboy es un sistema de juego en miniatura del tamaño de una tarjeta de crédito. Viene instalado con un juego clásico de 8 bits y se puede reprogramar desde una biblioteca de juegos de código abierto disponible en línea. Arduboy es de código abierto para que pueda aprender a codificar y crear sus propios juegos. La versión original se basa en el microcontrolador ATmega32U4 y la pantalla OLED serial de 128x64 píxeles.

La consola cuya construcción se representa a continuación está compuesta por Arduino Nano y la versión I2C de la pantalla OLED que puede ser mucho más fácil de encontrar a un precio menor. Puede descargar las bibliotecas y el código necesarios en:

https://github.com/harbaum/Arduboy2

Si posee una impresora 3D, también puede descargar archivos .STL de una posible opción de caja en la que está instalada la consola. Una guía de instalación detallada está disponible en el mismo sitio. Está alimentado por un Arduino Nano con una batería de iones de litio de 3.7v y funciona bastante bien.

Probé muchos juegos en esta consola, y todos funcionan muy bien:

- ArduBreakout

- Pinball

- Shadow-Runner

- Serpiente

- VIRUS-LQP-79

- Diecinueve43

y muchos más ...

El esquema se muestra a continuación.

Como ejemplo, estoy presentando el código del juego ArduBreakout, pero puedes descargar cualquier otro juego en el sitio de Arduboy compatible con esta versión de la consola.

Código

  • ArduBreakout Game
Juego ArduBreakout Arduino
 / * Breakout Copyright (C) 2011 Sebastian Goscik Todos los derechos reservados. Modificaciones de Scott Allen 2016 (después de cambios anteriores de ???) Esta biblioteca es software gratuito; puede redistribuirlo y / o modificarlo según los términos de la Licencia Pública General Reducida GNU publicada por la Free Software Foundation; ya sea la versión 2.1 de la Licencia o (a su elección) cualquier versión posterior. * / # incluye  // bloque en EEPROM para guardar puntuaciones altas # define EE_FILE 2Arduboy2 arduboy; BeepPin1 beep; const unsigned int FRAME_RATE =40; // Velocidad de fotogramas en fotogramas por segundoconst unsigned int COLUMNS =13; // Columnas de bricksconst unsigned int ROWS =4; // Filas de bricksint dx =-1; // Movimiento inicial de la bola dy =-1; // Movimiento inicial de ballint xb; // Posición inicial de las bolas yb; // Posicion de salida booleana lanzada; // Si la pelota ha sido lanzada por el jugador boolean paused =false; // Si el juego ha sido pausedbyte xPaddle; // Posición X de paddleboolean isHit [FILAS] [COLUMNAS]; // Matriz de si los ladrillos son golpeados o no booleanos rebotados =falso; // Se usa para arreglar el glitchbyte de doble rebote vidas =3; // Cantidad de vidasbyte nivel =1; // Nivel actualunsigned int score =0; // Puntuación para el juego sin firmar int brickCount; // Cantidad de ladrillos hitboolean pad, pad2, pad3; // Búfer de pulsación de botón utilizado para detener la pausa repetida booleana oldpad, oldpad2, oldpad3; char text_buffer [16]; // Cadena general bufferboolean start =false; // Si está en el menú o en gameboolean initialDraw =false; // Si ha ocurrido el sorteo inicialchar initials [3]; // Iniciales usadas en puntaje alto // Ball Bounds usados ​​en la detección de colisiones byte leftBall; byte rightBall; byte topBall; byte bottomBall; // Brick Límites usados ​​en la detección de colisiones byte leftBrick; byte rightBrick; byte topBrick; byte bottomBrick; byte tick; void setup () {arduboy.begin (); beep.begin (); arduboy.setFrameRate (FRAME_RATE); arduboy.initRandomSeed ();} void loop () {// pausar el procesamiento hasta que llegue el momento del siguiente cuadro if (! (arduboy.nextFrame ())) return; // Maneja el tiempo y la parada de los tonos beep.timer (); // El bucle de la pantalla de título cambia de la pantalla de título // y las puntuaciones más altas hasta que se presiona FIRE while (! Start) {start =titleScreen (); if (! start) {start =displayHighScores (EE_FILE); }} // Dibujo de nivel inicial if (! InitialDraw) {// Limpia la pantalla arduboy.clear (); // Selecciona la fuente // Dibuja el nuevo nivel level =1; nuevo nivel(); puntuación =0; initialDraw =verdadero; } si (vive> 0) {drawPaddle (); // Pausar el juego si se presiona FUEGO pad =arduboy.pressed (A_BUTTON) || arduboy.pressed (B_BUTTON); if (pad ==true &&oldpad ==false &&liberado) {oldpad2 =false; // Obliga al pad loop 2 a ejecutarse una vez pause (); } oldpad =pad; drawBall (); if (brickCount ==FILAS * COLUMNAS) {nivel ++; nuevo nivel(); }} else {drawGameOver (); if (puntuación> 0) {enterHighScore (EE_FILE); } arduboy.clear (); initialDraw =falso; inicio =falso; vidas =3; nuevo nivel(); } arduboy.display ();} void movePaddle () {// Mover a la derecha if (xPaddle  0) {if (arduboy.pressed (LEFT_BUTTON)) {xPaddle- =2; }}} void moveBall () {tick ++; if (soltado) {// Mueve la bola if (abs (dx) ==2) {xb + =dx / 2; // 2x velocidad es realmente 1,5 velocidad if (tick% 2 ==0) xb + =dx / 2; } más {xb + =dx; } yb =yb + dy; // Establecer límites leftBall =xb; bola derecha =xb + 2; topBall =yb; bottomBall =yb + 2; // Rebota en el borde superior if (yb <=0) {yb =2; dy =-dy; playTone (523, 250); } // Pierde una vida si golpea el borde inferior if (yb> =64) {arduboy.drawRect (xPaddle, 63, 11, 1, 0); xPaddle =54; yb =60; liberado =falso; vidas--; playToneTimed (175, 500); si (aleatorio (0, 2) ==0) {dx =1; } más {dx =-1; }} // Rebota en el lado izquierdo if (xb <=0) {xb =2; dx =-dx; playTone (523, 250); } // Rebota en el lado derecho if (xb> =ANCHO - 2) {xb =ANCHO - 4; dx =-dx; playTone (523, 250); } // Rebotar en la paleta if (xb + 1> =xPaddle &&xb <=xPaddle + 12 &&yb + 2> =63 &&yb <=64) {dy =-dy; dx =((xb- (xPaddle + 6)) / 3); // Aplica efecto a la pelota // previene el rebote directo si (dx ==0) {dx =(random (0,2) ==1)? 1:-1; } playTone (200, 250); } // Rebotar ladrillos para (byte fila =0; fila  =topBrick &&leftBall <=rightBrick &&rightBall> =leftBrick) {Score (); brickCount ++; isHit [fila] [columna] =verdadero; arduboy.drawRect (10 * columna, 2 + 6 * fila, 8, 4, 0); // Colisión vertical if (bottomBall> bottomBrick || topBall  rightBrick) {// Solo rebota una vez el ladrillo cada movimiento de la bola if (! Rebota) {dx =- dx; xb + =dx; rebotado =verdadero; playTone (261, 250); }}}}}} // Restablecer el rebote rebotado =falso; } else {// La pelota sigue a la paleta xb =xPaddle + 5; // Suelta la bola si presiona FUEGO pad3 =arduboy.pressed (A_BUTTON) || arduboy.pressed (B_BUTTON); if (pad3 ==true &&oldpad3 ==false) {liberado =verdadero; // Aplicar dirección aleatoria a la bola al soltar if (random (0, 2) ==0) {dx =1; } más {dx =-1; } // Se asegura de que la bola vaya hacia arriba 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);} vacío drawPaddle () {arduboy.drawRect (xPaddle, 63, 11, 1, 0); movePaddle (); arduboy.drawRect (xPaddle, 63, 11, 1, 1);} vacío 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 ("Fin del juego"); arduboy.setCursor (31, 56); arduboy.print ("Puntuación:"); arduboy.print (puntuación); arduboy.display (); arduboy.delayShort (4000);} void pause () {paused =true; // Dibuja una pausa en la pantalla arduboy.setCursor (52, 45); arduboy.print ("PAUSA"); arduboy.display (); while (pausado) {arduboy.delayShort (150); // Reanuda la pausa si se presiona FUEGO pad2 =arduboy.pressed (A_BUTTON) || arduboy.pressed (B_BUTTON); if (pad2 ==true &&oldpad2 ==false &&liberado) {arduboy.fillRect (52, 45, 30, 11, 0); paused =falso; } oldpad2 =pad2; }} void Score () {score + =(nivel * 10);} void newLevel () {// Deshacer paleta arduboy.drawRect (xPaddle, 63, 11, 1, 0); // Deshacer bola arduboy.drawPixel (xb, yb, 0); arduboy.drawPixel (xb + 1, yb, 0); arduboy.drawPixel (xb, yb + 1, 0); arduboy.drawPixel (xb + 1, yb + 1, 0); // Modifica varias variables para reiniciar el juego xPaddle =54; yb =60; brickCount =0; liberado =falso; // Dibuja nuevos ladrillos y restablece sus valores para (byte fila =0; fila <4; fila ++) {para (byte columna =0; columna <13; columna ++) {isHit [fila] [columna] =falso; arduboy.drawRect (10 * columna, 2 + 6 * fila, 8, 4, 1); }} arduboy.display ();} // Se usa para retrasar imágenes mientras se lee el botón inputboolean pollFireButton (int n) {for (int i =0; i  0) {sprintf (text_buffer, "% c% c% c% u", iniciales [0], iniciales [1], iniciales [2], puntuación); arduboy.setCursor (x + 24, y + (i * 8)); arduboy.print (text_buffer); arduboy.display (); }} if (pollFireButton (300)) {devolver verdadero; } falso retorno; arduboy.display ();} boolean titleScreen () {// Limpia la pantalla arduboy.clear (); arduboy.setCursor (16,22); arduboy.setTextSize (2); arduboy.print ("BREAKOUT"); arduboy.setTextSize (1); arduboy.display (); if (pollFireButton (25)) {devolver verdadero; } // Flash "Presione FUEGO" 5 veces para (byte i =0; i <5; i ++) {// Dibuja "Presione FUEGO" arduboy.setCursor (31, 53); arduboy.print ("¡PRESIONE FUEGO!"); arduboy.display (); if (pollFireButton (50)) {devolver verdadero; } // Elimina "Press FIRE" arduboy.setCursor (31, 53); arduboy.print (""); arduboy.display (); if (pollFireButton (25)) {devolver verdadero; }} return false;} // Función por diseño nootrópico para agregar puntajes altos void enterInitials () {byte index =0; arduboy.clear (); iniciales [0] =''; iniciales [1] =''; iniciales [2] =''; while (verdadero) {arduboy.display (); arduboy.clear (); arduboy.setCursor (16,0); arduboy.print ("PUNTUACIÓN ALTA"); sprintf (text_buffer, "% u", puntuación); arduboy.setCursor (88, 0); arduboy.print (text_buffer); arduboy.setCursor (56, 20); arduboy.print (iniciales [0]); arduboy.setCursor (64, 20); arduboy.print (iniciales [1]); arduboy.setCursor (72, 20); arduboy.print (iniciales [2]); para (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 + (índice * 8), 28, 56 + (índice * 8) + 6, 28, 1); arduboy.delayShort (70); if (arduboy.pressed (LEFT_BUTTON) || arduboy.pressed (B_BUTTON)) {if (índice> 0) {índice--; playToneTimed (1046, 80); }} if (arduboy.pressed (RIGHT_BUTTON)) {if (índice <2) {índice ++; playToneTimed (1046, 80); }} if (arduboy.pressed (UP_BUTTON)) {iniciales [índice] ++; playToneTimed (523, 80); // A-Z 0-9:-? ! - / '' if (iniciales [índice] =='0') {iniciales [índice] =''; } if (iniciales [índice] =='!') {iniciales [índice] ='A'; } if (iniciales [índice] =='[') {iniciales [índice] ='0'; } if (iniciales [índice] =='@') {iniciales [índice] ='!'; }} if (arduboy.pressed (DOWN_BUTTON)) {iniciales [índice] -; playToneTimed (523, 80); if (iniciales [índice] =='') {iniciales [índice] ='?'; } if (iniciales [índice] =='/') {iniciales [índice] ='Z'; } if (iniciales [índice] ==31) {iniciales [índice] ='/'; } if (iniciales [índice] =='@') {iniciales [índice] =''; }} if (arduboy.pressed (A_BUTTON)) {playToneTimed (1046, 80); si (índice <2) {índice ++; } else {volver; }}}} void enterHighScore (archivo de bytes) {// Cada bloque de EEPROM tiene 7 puntajes altos, y cada entrada de puntaje alto // tiene 5 bytes de longitud:3 bytes para las iniciales y dos bytes para el puntaje. int dirección =archivo * 7 * 5 + EEPROM_STORAGE_SPACE_START; byte hola, lo; char tmpInitials [3]; unsigned int tmpScore =0; // Procesamiento de puntaje alto para (byte i =0; i <7; i ++) {hi =EEPROM.read (dirección + (5 * i)); lo =EEPROM.read (dirección + (5 * i) + 1); if ((hi ==0xFF) &&(lo ==0xFF)) {// Los valores no están inicializados, así que trate esta entrada // como una puntuación de 0. tmpScore =0; } más {tmpScore =(hola <<8) | lo; } if (puntuación> tmpScore) {enterInitials (); para (byte j =i; j <7; j ++) {hi =EEPROM.read (dirección + (5 * j)); lo =EEPROM.read (dirección + (5 * j) + 1); if ((hi ==0xFF) &&(lo ==0xFF)) {tmpScore =0; } más {tmpScore =(hola <<8) | lo; } tmpInitials [0] =(char) EEPROM.read (dirección + (5 * j) + 2); tmpInitials [1] =(char) EEPROM.read (dirección + (5 * j) + 3); tmpInitials [2] =(char) EEPROM.read (dirección + (5 * j) + 4); // escribe la puntuación y las iniciales en la ranura actual EEPROM.update (dirección + (5 * j), ((puntuación>> 8) &0xFF)); EEPROM.update (dirección + (5 * j) + 1, (puntuación &0xFF)); EEPROM.update (dirección + (5 * j) + 2, iniciales [0]); EEPROM.update (dirección + (5 * j) + 3, iniciales [1]); EEPROM.update (dirección + (5 * j) + 4, iniciales [2]); // tmpScore y tmpInitials ahora contienen lo que queremos // escribir en el siguiente espacio. score =tmpScore; iniciales [0] =tmpInitials [0]; iniciales [1] =tmpInitials [1]; iniciales [2] =tmpInitials [2]; } puntuación =0; iniciales [0] =''; iniciales [1] =''; iniciales [2] =''; regreso; }}} // Reproduce un tono en la frecuencia especificada durante la duración especificada.void playTone (frecuencia int sin firmar, duración int sin firmar) {beep.tone (beep.freq (frecuencia), duración / (1000 / FRAME_RATE));} // Reproduce un tono a la frecuencia especificada durante la duración especificada usando // un retardo para medir el tiempo del tono .// Se usa cuando no se llama beep.timer (). beep.tone (beep.freq (frecuencia)); arduboy.delayShort (duración); beep.noTone ();} 

Piezas y carcasas personalizadas

3d_parts_ThLGvJvWga.rar

Esquemas


Proceso de manufactura

  1. Comunicación de Arduino I2C con Raspi 2 WIOT
  2. Consola de juegos portátil | Clon de Arduboy
  3. Juego Arduino Pong - Pantalla OLED
  4. Arduino Temp. Monitor y reloj en tiempo real con pantalla 3.2
  5. Sensor de obstáculos simple con Arduino
  6. Jugando con Nextion Display
  7. Arduino Nano:Controla 2 motores paso a paso con joystick
  8. Voltímetro de bricolaje con Arduino y una pantalla Nokia 5110
  9. Autómatas celulares basados ​​en Arduino y OLED
  10. Contador Geiger de mano con Arduino Nano
  11. Una entrada analógica aislada para Arduino