Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Arduboy Clone com Arduino Nano e display I2C OLED

Componentes e suprimentos

Arduino Nano R3
× 1
OLED gráfico, 128 x 64
× 1
Buzzer
× 1
Interruptor tátil, acionado pela parte superior
× 6
Cátodo comum difuso RGB
× 1
Resistor 221 ohm
× 3
Resistor 10k ohm
× 1

Ferramentas e máquinas necessárias

Impressora 3D (genérica)
Ferro de soldar (genérico)

Sobre este projeto




Arduboy é um sistema de jogo em miniatura do tamanho de um cartão de crédito. Ele vem instalado com um jogo clássico de 8 bits e pode ser reprogramado a partir de uma biblioteca de jogos de código aberto disponíveis online. Arduboy é um software livre para que você possa aprender a codificar e criar seus próprios jogos. A versão original é baseada no microcontrolador ATmega32U4 e display OLED serial de 128x64 Pixels.

O console cuja construção é representada abaixo é composto por Arduino Nano e a versão I2C do display OLED que pode ser muito mais fácil de encontrar por um preço menor. Você pode baixar as bibliotecas e códigos necessários em:

https://github.com/harbaum/Arduboy2

Se você possui uma impressora 3D, também pode baixar arquivos .STL de uma possível opção de caixa na qual o console está instalado. Um guia de instalação detalhado está disponível no mesmo site. Ele é alimentado por um Arduino Nano com uma bateria de íon de lítio de 3,7v e funciona muito bem.

Testei muitos jogos neste console, todos os quais funcionam muito bem:

- ArduBreakout

- Pinball

- Shadow-Runner

- Cobra

- VIRUS-LQP-79

- Dezenove 43

e muitos mais...

O esquema é mostrado abaixo.

A título de exemplo, estou apresentando o código do jogo ArduBreakout, mas você pode baixar qualquer outro jogo no site do Arduboy compatível com esta versão do console.

Código

  • Jogo ArduBreakout
Jogo ArduBreakout Arduino
 / * Breakout Copyright (C) 2011 Sebastian Goscik Todos os direitos reservados. Modificações por Scott Allen 2016 (após as alterações anteriores por ???) Esta biblioteca é um software livre; você pode redistribuí-lo e / ou modificá-lo sob os termos da GNU Lesser General Public License conforme publicada pela Free Software Foundation; tanto a versão 2.1 da Licença, ou (por sua opção) qualquer versão posterior. * / # include  // bloco em EEPROM para salvar pontuações mais altas # define EE_FILE 2Arduboy2 arduboy; BeepPin1 beep; const unsigned int FRAME_RATE =40; // Taxa de quadros em quadros por segundoconst unsigned int COLUMNS =13; // Colunas de tijolosconst unsigned int ROWS =4; // Linhas de bricksint dx =-1; // Movimento inicial do ballint dy =-1; // Movimento inicial do ballint xb; // Bolas iniciando possitionint yb; // Bolas iniciando possitionboolean liberadas; // Se a bola foi lançada pelo playerboolean paused =false; // Se o jogo foi pausadobyte xPaddle; // posição X de paddleboolean isHit [ROWS] [COLUMNS]; // Array de se os tijolos são atingidos ou notboolean bumped =false; // Usado para consertar o glitchbyte de salto duplo lives =3; // Quantidade de níveis de bytes de vida =1; // Current levelunsigned int score =0; // Pontuação para o gameunsigned int brickCount; // Quantidade de tijolos hitboolean pad, pad2, pad3; // Buffer de pressionamento de botão usado para interromper a pausa de repetição boolean oldpad, oldpad2, oldpad3; char text_buffer [16]; // String geral bufferboolean start =false; // Se no menu ou no gameboolean initialDraw =false; // Se o desenho inicial aconteceu char initials [3]; // Iniciais usados ​​na alta pontuação // Limites de bola usados ​​na detecção de colisão byte leftBall; byte rightBall; byte topBall; byte bottomBall; // Limites de tijolo usados ​​na detecção de colisãobyte leftBrick; byte rightBrick; byte topBrick; byte bottomBrick; byte tick; configuração de vazio () {arduboy.begin (); beep.begin (); arduboy.setFrameRate (FRAME_RATE); arduboy.initRandomSeed ();} void loop () {// pausa a renderização até a hora do próximo quadro if (! (arduboy.nextFrame ())) return; // Gerencia o tempo e a interrupção dos tons beep.timer (); // O loop da tela de título muda da tela de título // e das pontuações mais altas até que FIRE seja pressionado while (! Start) {start =titleScreen (); if (! start) {start =displayHighScores (EE_FILE); }} // Desenho de nível inicial if (! InitialDraw) {// Limpa a tela arduboy.clear (); // Seleciona a fonte // Desenha o novo nível level =1; novo nível(); pontuação =0; initialDraw =true; } if (lives> 0) {drawPaddle (); // Pausa o jogo se FIRE pressionado pad =arduboy.pressed (A_BUTTON) || arduboy.primido (B_BUTTON); if (pad ==true &&oldpad ==false &&lançado) {oldpad2 =false; // Força o loop 2 do teclado a ser executado uma vez pause (); } oldpad =pad; drawBall (); if (brickCount ==LINHAS * COLUNAS) {nível ++; novo nível(); }} else {drawGameOver (); if (pontuação> 0) {enterHighScore (EE_FILE); } arduboy.clear (); initialDraw =false; início =falso; vidas =3; novo nível(); } arduboy.display ();} void movePaddle () {// Mover para a direita se (xPaddle  0) {if (arduboy.pressed (LEFT_BUTTON)) {xPaddle- =2; }}} void moveBall () {tick ++; if (liberado) {// Mova a bola if (abs (dx) ==2) {xb + =dx / 2; // 2x a velocidade é realmente 1,5 velocidade if (tick% 2 ==0) xb + =dx / 2; } else {xb + =dx; } yb =yb + dy; // Definir limites leftBall =xb; Bola direita =xb + 2; topBall =yb; bola inferior =yb + 2; // Salta para fora da borda superior if (yb <=0) {yb =2; dy =-dy; playTone (523, 250); } // Perde uma vida se a borda inferior atingir if (yb> =64) {arduboy.drawRect (xPaddle, 63, 11, 1, 0); xPaddle =54; yb =60; lançado =falso; vidas--; playToneTimed (175, 500); if (aleatório (0, 2) ==0) {dx =1; } senão {dx =-1; }} // Salta do lado esquerdo if (xb <=0) {xb =2; dx =-dx; playTone (523, 250); } // Salta para o lado direito if (xb> =WIDTH - 2) {xb =WIDTH - 4; dx =-dx; playTone (523, 250); } // Saltar na raquete if (xb + 1> =xPaddle &&xb <=xPaddle + 12 &&yb + 2> =63 &&yb <=64) {dy =-dy; dx =((xb- (xPaddle + 6)) / 3); // Aplica giro na bola // evita salto direto if (dx ==0) {dx =(random (0,2) ==1)? 1:-1; } playTone (200, 250); } // Rebatimento dos tijolos para (byte linha =0; linha  =topBrick &&leftBall <=rightBrick &&rightBall> =leftBrick) {Score (); brickCount ++; isHit [linha] [coluna] =verdadeiro; arduboy.drawRect (10 * coluna, 2 + 6 * linha, 8, 4, 0); // Colisão vertical if (bottomBall> bottomBrick || topBall  rightBrick) {// Só pula uma vez que cada tijolo se move if (! Quicou) {dx =- dx; xb + =dx; devolvido =verdadeiro; playTone (261, 250); }}}}}} // Reset Bounce bounce =false; } else {// A bola segue a raquete xb =xPaddle + 5; // Solte a bola se FIRE pressionado pad3 =arduboy.pressed (A_BUTTON) || arduboy.primido (B_BUTTON); if (pad3 ==true &&oldpad3 ==false) {release =true; // Aplicar direção aleatória à bola no lançamento if (random (0, 2) ==0) {dx =1; } senão {dx =-1; } // Garante que a bola vá para cima 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 ("Pontuação:"); arduboy.print (pontuação); arduboy.display (); arduboy.delayShort (4000);} void pause () {paused =true; // Desenhe uma pausa na tela arduboy.setCursor (52, 45); arduboy.print ("PAUSE"); arduboy.display (); enquanto (em pausa) {arduboy.delayShort (150); // Retome a pausa se FIRE for pressionado pad2 =arduboy.pressed (A_BUTTON) || arduboy.primido (B_BUTTON); if (pad2 ==true &&oldpad2 ==false &&lançado) {arduboy.fillRect (52, 45, 30, 11, 0); pausado =falso; } oldpad2 =pad2; }} void Score () {score + =(level * 10);} void newLevel () {// Undraw paddle arduboy.drawRect (xPaddle, 63, 11, 1, 0); // Retirar 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); // Altera várias variáveis ​​para reiniciar o jogo xPaddle =54; yb =60; brickCount =0; lançado =falso; // Desenha novos blocos e redefine seus valores para (byte row =0; row <4; row ++) {for (byte column =0; column <13; column ++) {isHit [row] [column] =false; arduboy.drawRect (10 * coluna, 2 + 6 * linha, 8, 4, 1); }} arduboy.display ();} // Usado para atrasar as imagens durante a leitura do botão inputboolean pollFireButton (int n) {for (int i =0; i  0) {sprintf (text_buffer, "% c% c% c% u", iniciais [0], iniciais [1], iniciais [2], pontuação); arduboy.setCursor (x + 24, y + (i * 8)); arduboy.print (text_buffer); arduboy.display (); }} if (pollFireButton (300)) {return true; } retorna falso; arduboy.display ();} boolean titleScreen () {// Limpa a tela 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 vezes para (byte i =0; i <5; i ++) {// Desenha "Press FIRE" arduboy.setCursor (31, 53); arduboy.print ("PRESS FIRE!"); arduboy.display (); if (pollFireButton (50)) {return true; } // Remove "Pressione FIRE" arduboy.setCursor (31, 53); arduboy.print (""); arduboy.display (); if (pollFireButton (25)) {return true; }} return false;} // Função por design nootrópico para adicionar pontuações altasvoid enterInitials () {byte index =0; arduboy.clear (); iniciais [0] =''; iniciais [1] =''; iniciais [2] =''; while (true) {arduboy.display (); arduboy.clear (); arduboy.setCursor (16,0); arduboy.print ("HIGH SCORE"); sprintf (text_buffer, "% u", pontuação); arduboy.setCursor (88, 0); arduboy.print (text_buffer); arduboy.setCursor (56, 20); arduboy.print (iniciais [0]); arduboy.setCursor (64, 20); arduboy.print (iniciais [1]); arduboy.setCursor (72, 20); arduboy.print (iniciais [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 (index> 0) {index--; playToneTimed (1046, 80); }} if (arduboy.pressed (RIGHT_BUTTON)) {if (índice <2) {índice ++; playToneTimed (1046, 80); }} if (arduboy.pressed (UP_BUTTON)) {iniciais [índice] ++; playToneTimed (523, 80); // A-Z 0-9:-? ! - / '' if (iniciais [índice] =='0') {iniciais [índice] =''; } if (iniciais [índice] =='!') {iniciais [índice] ='A'; } if (iniciais [índice] =='[') {iniciais [índice] ='0'; } if (iniciais [índice] =='@') {iniciais [índice] ='!'; }} if (arduboy.pressed (DOWN_BUTTON)) {iniciais [índice] -; playToneTimed (523, 80); if (iniciais [índice] =='') {iniciais [índice] ='?'; } if (iniciais [índice] =='/') {iniciais [índice] ='Z'; } if (iniciais [índice] ==31) {iniciais [índice] ='/'; } if (iniciais [índice] =='@') {iniciais [índice] =''; }} if (arduboy.pressed (A_BUTTON)) {playToneTimed (1046, 80); if (índice <2) {índice ++; } else {return; }}}} void enterHighScore (arquivo de bytes) {// Cada bloco de EEPROM tem 7 pontuações máximas e cada entrada de pontuação // tem 5 bytes de comprimento:3 bytes para as iniciais e dois bytes para a pontuação. endereço interno =arquivo * 7 * 5 + EEPROM_STORAGE_SPACE_START; byte oi, lo; char tmpInitials [3]; sem sinal int tmpScore =0; // Processamento de pontuação alta para (byte i =0; i <7; i ++) {hi =EEPROM.read (address + (5 * i)); lo =EEPROM.read (endereço + (5 * i) + 1); if ((hi ==0xFF) &&(lo ==0xFF)) {// Os valores não foram inicializados, portanto, trate esta entrada // como uma pontuação de 0. tmpScore =0; } else {tmpScore =(hi <<8) | lo; } if (pontuação> tmpScore) {enterInitials (); para (byte j =i; j <7; j ++) {hi =EEPROM.read (endereço + (5 * j)); lo =EEPROM.read (endereço + (5 * j) + 1); if ((hi ==0xFF) &&(lo ==0xFF)) {tmpScore =0; } else {tmpScore =(hi <<8) | lo; } tmpInitials [0] =(char) EEPROM.read (endereço + (5 * j) + 2); tmpInitials [1] =(char) EEPROM.read (endereço + (5 * j) + 3); tmpInitials [2] =(char) EEPROM.read (endereço + (5 * j) + 4); // escreve a pontuação e as iniciais no slot atual EEPROM.update (address + (5 * j), ((score>> 8) &0xFF)); EEPROM.update (endereço + (5 * j) + 1, (pontuação &0xFF)); EEPROM.update (endereço + (5 * j) + 2, iniciais [0]); EEPROM.update (endereço + (5 * j) + 3, iniciais [1]); EEPROM.update (endereço + (5 * j) + 4, iniciais [2]); // tmpScore e tmpInitials agora contêm o que desejamos // escrever no próximo slot. pontuação =tmpScore; iniciais [0] =tmpIniciais [0]; iniciais [1] =tmpIniciais [1]; iniciais [2] =tmpIniciais [2]; } pontuação =0; iniciais [0] =''; iniciais [1] =''; iniciais [2] =''; Retorna; }}} // Toca um tom na freqüência especificada para a duração especificada.void playTone (freqüência int sem sinal, duração int sem sinal) {beep.tone (beep.freq (freqüência), duração / (1000 / FRAME_RATE));} // Toca um tom na frequência especificada durante a duração especificada usando // um retardo para cronometrar o tom.// Usado quando beep.timer () não está sendo chamado.void playToneTimed (frequência int sem sinal, duração int sem sinal) { beep.tone (beep.freq (frequência)); arduboy.delayShort (duração); beep.noTone ();} 

Peças personalizadas e gabinetes

3d_parts_ThLGvJvWga.rar

Esquemas


Processo de manufatura

  1. Comunicação Arduino I2C com Raspi 2 WIOT
  2. Console de jogos portátil | Arduboy Clone
  3. Jogo Arduino Pong - Tela OLED
  4. Arduino Temp. Monitor e relógio em tempo real com tela 3.2
  5. Sensor de obstáculo simples com Arduino
  6. Brincando com Nextion Display
  7. Arduino Nano:Controle 2 motores de passo com joystick
  8. Voltímetro DIY com Arduino e um visor Nokia 5110
  9. Arduino e autômatos celulares baseados em OLED
  10. Uma entrada analógica isolada para Arduino