Cześć!
Arduino i drukarka 3D daje nam tyle możliwości, że można zrobić prawie wszystko. Dziś pokaże wam jak zrobiłem mini “konsole”.
W majsterkowie jest już konsola z grą PONG lecz nie w wersji przenośnej ale jako konsola podpinana do telewizora, polecam zobaczyć.
Osobiście chciałem zrobić coś mniejszego, przenośnego z wykorzystaniem druku 3D, zobaczcie co z tego wyszło.
PO CO?
W dzisiejszych czasach moc obliczeniowa smartfonów jest olbrzymia, więc po co budować mini “konsole” na której zagramy w jedną gierkę gdy możemy grać w wiele wypasionych tytułów na naszych telefonach? Otóż nie chodzi o samo granie ale o zrobienie czegoś samemu, w ten sposób na pewno można się wiele nauczyć oraz połączyć to z zabawą.
MATERIAŁY:
Arduino (najlepiej Nano)
wyświetlacz LCD graficzny 84x48px – Nokia 5110
bateria i klip na baterię 9V
2 potencjometry (5k Ohm) + dwie gałki
przełącznik on-off
- płytka stykowa (do prototypu)
koszulki termokurczliwe
przewody
filament do druku
taśma izolacyjna
8 śrubek
Zaczynamy od złożenia wszystkiego w całość na płytce stykowej. Wszystko łączymy jak rysunku:
U mnie wygląda to tak:
Teraz możemy wgrać program, szkic nie jest w całości mój został tylko przeze mnie lekko zmodyfikowany (oryginał).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
/* Arduino PONG lipiec 2017 */ #define PIN_RESET 7 //podłączenie wyświetlacza #define PIN_SCE 6 #define PIN_DC 5 #define PIN_SDIN 4 #define PIN_SCLK 3 #define LCD_C LOW //parametry wyświetlacza #define LCD_D HIGH #define LCD_X 84 #define LCD_Y 6 int barWidth = 16; //ustawienia i parametry gry int barHeight = 4; int ballPerimeter = 4; unsigned int bar1X = 0; unsigned int bar1Y = 0; unsigned int bar2X = 0; unsigned int bar2Y = LCD_Y * 8 - barHeight; int ballX = 0; int ballY = 0; boolean isBallUp = false; boolean isBallRight = true; byte pixels[LCD_X][LCD_Y]; unsigned long lastRefreshTime; const int refreshInterval = 150; byte gameState = 1; byte ballSpeed = 2; byte player1WinCount = 0; byte player2WinCount = 0; byte hitCount = 0; void setup(){ LcdInitialise(); restartGame(); } void loop(){ unsigned long now = millis(); if(now - lastRefreshTime > refreshInterval){ update(); refreshScreen(); lastRefreshTime = now; } } void restartGame(){ ballSpeed = 1; gameState = 1; ballX = random(0, 60); ballY = 20; isBallUp = false; isBallRight = true; hitCount = 0; } void refreshScreen(){ if(gameState == 1){ for(int y = 0; y < LCD_Y; y++){ for(int x = 0; x < LCD_X; x++){ byte pixel = 0x00; int realY = y * 8; if(x >= ballX && x <= ballX + ballPerimeter -1 && ballY + ballPerimeter > realY && ballY < realY + 8 ){ byte ballMask = 0x00; for(int i = 0; i < realY + 8 - ballY; i++){ ballMask = ballMask >> 1; if(i < ballPerimeter) ballMask = 0x80 | ballMask; } pixel = pixel | ballMask; } if(x >= bar1X && x <= bar1X + barWidth -1 && bar1Y + barHeight > realY && bar1Y < realY + 8 ){ byte barMask = 0x00; for(int i = 0; i < realY + 8 - bar1Y; i++){ barMask = barMask >> 1; if(i < barHeight) barMask = 0x80 | barMask; } pixel = pixel | barMask; } if(x >= bar2X && x <= bar2X + barWidth -1 && bar2Y + barHeight > realY && bar2Y < realY + 8 ){ byte barMask = 0x00; for(int i = 0; i < realY + 8 - bar2Y; i++){ barMask = barMask >> 1; if(i < barHeight) barMask = 0x80 | barMask; } pixel = pixel | barMask; } LcdWrite(LCD_D, pixel); } } } else if(gameState == 2){ } } void update(){ if(gameState == 1){ int barMargin = LCD_X - barWidth; int pot1 = analogRead(A0); //pozycje potencjometrów int pot2 = analogRead(A1); bar1X = pot1 / 2 * LCD_X / 512; bar2X = pot2 / 2 * LCD_X / 512; if(bar1X > barMargin) bar1X = barMargin; if(bar2X > barMargin) bar2X = barMargin; //ruch piłki if(isBallUp) ballY -= ballSpeed; else ballY += ballSpeed; if(isBallRight) ballX += ballSpeed; else ballX -= ballSpeed; if(ballX < 1){ isBallRight = true; ballX = 0; } else if(ballX > LCD_X - ballPerimeter - 1){ isBallRight = false; ballX = LCD_X - ballPerimeter; } if(ballY < barHeight){ if(ballX + ballPerimeter >= bar1X && ballX <= bar1X + barWidth){ // ball bounces from bar1 isBallUp = false; if(ballX + ballPerimeter/2 < bar1X + barWidth/2) isBallRight = false; else isBallRight = true; ballY = barHeight; if(++hitCount % 10 == 0 && ballSpeed < 5) ballSpeed++; }else{ gameState = 2; player2WinCount++; } } if(ballY + ballPerimeter > LCD_Y * 8 - barHeight){ if(ballX + ballPerimeter >= bar2X && ballX <= bar2X + barWidth){ isBallUp = true; if(ballX + ballPerimeter/2 < bar2X + barWidth/2) isBallRight = false; else isBallRight = true; ballY = LCD_Y * 8 - barHeight - ballPerimeter; if(++hitCount % 10 == 0 && ballSpeed < 5) ballSpeed++; }else{ gameState = 2; player1WinCount++; } } }else if(gameState == 2){ for(int i =0; i < 4; i++){ LcdWrite(LCD_C, 0x0D ); delay(300); LcdWrite(LCD_C, 0x0C ); delay(300); } restartGame(); } } void LcdInitialise(void){ pinMode(PIN_SCE, OUTPUT); pinMode(PIN_RESET, OUTPUT); pinMode(PIN_DC, OUTPUT); pinMode(PIN_SDIN, OUTPUT); pinMode(PIN_SCLK, OUTPUT); delay(200); digitalWrite(PIN_RESET, LOW); delay(500); digitalWrite(PIN_RESET, HIGH); LcdWrite(LCD_C, 0x21 ); LcdWrite(LCD_C, 0xB1 ); LcdWrite(LCD_C, 0x04 ); LcdWrite(LCD_C, 0x14 ); LcdWrite(LCD_C, 0x0C ); LcdWrite(LCD_C, 0x20 ); LcdWrite(LCD_C, 0x80 ); LcdWrite(LCD_C, 0x40 ); LcdWrite(LCD_C, 0x0C ); } void LcdWrite(byte dc, byte data){ digitalWrite(PIN_DC, dc); digitalWrite(PIN_SCE, LOW); shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data); digitalWrite(PIN_SCE, HIGH); } |
Program zajmuje tylko 9% pamięci, więc można pobawić się w jego rozbudowę lub dodanie innych gierek.
Wszystko powinno już chodzić, jeżeli nie sprawdź dokładnie wszystkie połączenia.
Czas na wydrukowanie obudowy, wydrukowałem ją z Red Neon PLA od F3D Filament na niebieskiej taśmie malarskiej(dlatego pierwsza warstwa się nie błyszczy), warstwa 0.3 mm, całość drukowała się ok. 3,5 godziny, a koszt filamentu to ok. 3 zł. Obudowę zaprojektowałem samemu i jestem z niej bardzo zadowolony, STL na samym dole artykułu.
Wydrukowana obudowa.
Dla osób nie mających dostępu do drukarki 3D dobrym rozwiązaniem może być uniwersalna obudowa np. KRADEX Z34, w której wystarczy wykonać potrzebne otwory, LCD można przykleić np. klejem na gorąco.
Przykręcamy wyświetlacz za pomocą 4 śrubek.
Do potencjometrów lutujemy przewody i zakładamy koszulki termokurczliwe.
Wkręcamy je do obudowy(przez to, że umieściłem potencjometr zbyt blisko LCD musiałem go trochę przyciąć co wiąże się z lekkim ryzykiem, w finalnym projekcie poprawiłem ten błąd, więc nie będziecie musieli tego robić).
Teraz do klipsa na baterię lutujemy włącznik.
Wkładamy przełącznik.
Łączymy wspólne przewody.
Podpinamy wszystko do Arduino Nano.
Tak prezentuje się gotowy środek. Dla bezpieczeństwa obkleiłem Arduino taśmą izolacyjną, żeby chronić elektronikę przed ewentualnym zwarciem. Wszystko jest mocno upchane w środku(nawet bateria nie ma obudowy bo ledwo wchodziła) i nic nie powinno się ruszać.
Teraz wystarczy skręcić obudowę za pomocą 4 śrubek M3 20 mm.
Wkładamy gałki z potencjometrów ja miałem kupione ale można je również wydrukować(przykład).
GOTOWE!
Wystarczy włączyć i można się cieszyć swoją nową zabawką.
Zdjęcia robione telefonem, więc wyświetlacz wydaję się nieostry ale w rzeczywistości wszystko jest spoko.
super projekt ale jakoś nielubie używania ardurino do gotowych projektów, atmega jest łatwo dostepna i tania
Arduino nano z chin ma cene podobną do atmegi i innych elementów elektronicznych wymaganych do uruchomienia tego AVR’a. Więc często używa się nano bądz innego arduino z chin zamiast suchego AVR’a :)
Właśnie po to są płytki z serii nano/pro, aby można było ich w prosty sposób użyć w prototypach czy jednostkowych egzemplarzach – tak że użycie w tym przypadku Arduino jest całkowicie uzasadnione.
Co prawda ja bym użył pro mini (bo mniejszy) i wcisnął gdzieś wyłącznik podświetlenia… Ale to takie moje fanaberie :)
Estetyka ładna, to mi się podoba, nie podoba mi się arduino, dużo pewniejszym i estetyczniejszym rozwiązaniem byłaby jakaś atmega na płytce zaprojektowanej i wykonanej i płytka wpinana do ekranu.
Podoba, nie podoba ;) Ważne, że działa. Chętnie spróbuję coś takiego złożyć. Mam tylko pytanie, co mają zrobić osoby nie dysponujące drukarką 3D?
Np. Posłużyć się katalogiem obudów serii Z, następnie paroma prostymi narzędziami.
Sprawdź sobie mój projekt “Kazik” – też gra na Arduino, zrobiona bez drukarki.
Uaktualniłem artykuł o tą kwestię.