Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
In this project we create a very small minigame-console that uses a gyroscope to get the inputs from the user. This way we don't have to worry about buttons and where to fit them, which makes it a lot easier to build. Because I wanted to make it portable, I added a battery shield and a small 3.7V Lipo battery. This game-console also works without the battery shield and the battery, but then it needs an external power supply over the micro USB port of the D1 mini.
I used an OLED 0.66" screen that can be directly stacked onto the battery shield or the Wemos D1 mini. This makes it very easy to assemble and also helps to keep the console compact.
For the case I used some balsa wood which was then covered with covering film.
Schematics
The only thing to solder is the gyroscope. You have to make the connections as shown in the picture. You may also want to add a switch between the battery and the battery-module, because if you solder the battery to the module there would be no way to turn the device off. After you soldered the gyro to the battery-module the three modules (Wemos D1 mini, Battery Shield, OLED Display) can be stacked together with some header pins.
Wemos Minigame
ArduinoHere is the code that you can upload to the Wemos D1 mini. You need to install the libraries "Adafruit_GFX" and "Adafruit_SSD1306".
I programmed four minigames and also added a function for charging (so that the screen is not on while charging). You can switch between the games by tilting the console far left/right. The brightness is also slightly adjustable by tilting the device forwards/backwards.
I programmed four minigames and also added a function for charging (so that the screen is not on while charging). You can switch between the games by tilting the console far left/right. The brightness is also slightly adjustable by tilting the device forwards/backwards.
#include<Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_RESET);
const int MPU_addr=0x68; // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
void write_setup(int coordx, int coordy, int T_size){
display.setTextSize(T_size);
display.setCursor(coordx, coordy);
}
void setup(){
Wire.begin();
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.println("Hello");
display.display();
delay(1000);
}
int jump(int t){
return int(0.7*t*t - 11*t + 42);
}
void read_gyro(int16_t* AcX, int16_t* AcY, int16_t* AcZ){
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,14,true); // request a total of 14 registers
*AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
*AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
*AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
}
void title(char Str[]){
display.clearDisplay();
write_setup(0, 1, 2);
display.println(Str);
display.display();
delay(1000);
display.clearDisplay();
}
void jump(){
while(true){
title("Jump");
display.fillRect(0,46,64,2,1);
float adder = 1.9;
bool b = true;
int y = 42;
int x = 15;
int t = 0;
bool jumb = false;
for(int j = 0; true; ++j){
int b1x = 63;
int b1y = random(28, 41);
int b1_height = 46 - b1y;
int b1_width = random(int(adder)*2, int(adder)*6);
adder += 0.1;
for(int i = 63 + b1_width + random(0, int(adder)*15); i > -b1_width; i -= int(adder)){
read_gyro(&AcX, &AcY, &AcZ);
display.fillScreen(0);
display.fillRect(i,b1y,b1_width,b1_height,1);
display.fillRect(0,46,64,2,1);
if(AcZ < -22800){jumb = true;}
if(jumb && t<15){
++t;
y = jump(t);
}
else{
jumb = false;
t = 0;
y = 42;
}
display.drawCircle(x,y,3,1);
write_setup(45,10,1);
display.print(j);
display.display();
delay(1);
if(i > 12 - b1_width && i < 19 && y + 4 > b1y){
write_setup(1,11,1);
display.print("Crash!");
display.display();
delay(1500);
jump();
}
if(AcX > 12000){gravity();}
else if(AcX < -8000){shoot();}
if(AcY > 12000){display.dim(true);}
else if(AcY < -12000){display.dim(false);}
}
}
}
}
void gravity(){
title("Catch");
int x = 31;
int y = 20;
int Ay = 0;
int Ax = 0;
int t0 = millis();
int t_rem = 10000;
int count = 0;
bool done = false;
while(!done){
int bx = random(8, 64);
int by = random(8, 48);
while(abs(x-bx) > 5 || abs(y-by) > 5){
Ax = 0;
Ay = 0;
for(int i = 0; i < 5; i++){
read_gyro(&AcX, &AcY, &AcZ);
Ax += AcX;
Ay += AcY;
delay(3);
}
Ax /= 5;
Ay /= 5;
x = -3*int((Ax - 550)/400) + 30;
y = -3*int((Ay + 265)/400) + 20;
display.clearDisplay();
if(x > 63){x = 63;}
else if(x < 0){x = 0;}
if(y > 47){y = 47;}
else if(y < 0){y = 0;}
write_setup(0,1,1);
if((t_rem-(millis()-t0))/1000 > 12000){done = true; break;}
display.print((t_rem-(millis()-t0))/1000);
display.fillCircle(x, y, 3, 1);
display.drawCircle(bx, by, 3, 1);
display.display();
delay(1);
if(AcX < -12000){jump();}
if(AcY > 12000){display.dim(true);}
else if(AcY < -12000){display.dim(false);}
}
if(!done){count += 1;}
}
display.clearDisplay();
write_setup(2,15,1);
display.print("Score: ");
display.print(count);
display.display();
delay(2000);
gravity();
}
void shoot(){
title("Shoot");
int x = 0;
int py = 42;
int px = 0;
bool shot = true;
int f1x = random(0, 64);
int f1y = -random(2, 50);
int f2x = random(0,64);
int f2y = -random(2, 15);
int score = 0;
int Ax = 0;
while(true){
while(true){
for(int i = 0; i < 3; i++){
read_gyro(&AcX, &AcY, &AcZ);
Ax += AcX;
delay(3);
}
Ax /= 3;
display.clearDisplay();
x = -3*int((Ax - 550)/400) + 30;
Ax = 0;
if(x > 59){x = 59;}
else if(x < -5){x = -5;}
display.fillRect(x, 45, 11, 3, 1);
if(shot){px = x+5; shot = false;}
display.fillRect(x+4, 42, 3, 3, 1);
display.drawRect(px, py, 1, 3, 1);
display.fillCircle(f1x, f1y, 2, 1);
display.fillCircle(f2x, f2y, 2, 1);
display.display();
delay(1);
if(py < -1){
shot = true;
py = 40;
}
if(abs(px-f1x) < 4 && py < f1y){
shot = true;
py = 42;
f1x = random(0, 64);
f1y = -random(5*(int(score/20)+1), 30*(int(score/12)+1));
score += 1;
}
else if(abs(px-f2x) < 4 && py < f2y){
shot = true;
py = 42;
f2x = random(0, 64);
f2y = -random(4*(int(score/15)+1), 40*(int(score/12)+1));
score += 1;
}
py -= 4*(int(score/15)+1);
f1y += 1 + int(score/30);
f2y += 1 + int(score/15);
if(f1y > 46 || f2y > 46){
delay(100);
write_setup(3, 10, 1);
display.print("Hit!");
display.display();
delay(1000);
display.clearDisplay();
write_setup(3, 10, 1);
display.print("Score: ");
display.print(score);
display.display();
delay(2000);
shoot();
}
if(AcX < -12000){track();}
else if(AcX > 12000){jump();}
if(AcY > 12000){display.dim(true);}
else if(AcY < -12000){display.dim(false);}
}
}
}
void track(){
title("Track");
int x;
int Ax = 0;
int coord[54];
int p = 15;
unsigned int dist = 0;
for(int i = 0; i < 54; i+=2){
coord[i] = random(0,65);
coord[i+1] = random(0,49);
}
int line1[2] = {30, 48};
int line2[2] = {37, 0};
int line3[2] = {28, -48};
while(true){
for(int i = 0; i < 3; i++){
read_gyro(&AcX, &AcY, &AcZ);
Ax += AcX;
delay(3);
}
Ax /= 3;
display.clearDisplay();
x = -3*int((Ax - 550)/400) + 30;
Ax = 0;
if(x > 59){x = 59;}
else if(x < -5){x = -5;}
for(int i = -3; i < 4; i++){
display.drawLine(line1[0]+i, line1[1], line2[0]+i, line2[1], 1);
display.drawLine(line2[0]+i, line2[1], line3[0]+i, line3[1], 1);
}
for(int i = 0; i < 54; i+=2){
display.drawPixel(coord[i], coord[i+1], 1);
}
display.fillCircle(x, 42, 3, 0);
display.drawCircle(x, 42, 4, 1);
display.display();
delay(1);
float h = p*(line2[0]-line1[0])/64;
if(abs(x - (line1[0] + h)) > 8 + abs(4*h/p) && p < 48){
if(AcX < -12000){charging();}
else if(AcX > 12000){shoot();}
if(AcY > 12000){display.dim(true);}
else if(AcY < -12000){display.dim(false);}
display.fillCircle(x, 42, 4, 0);
display.drawCircle(x, 42, 3, 1);
display.display();
delay(150);
display.fillCircle(x, 42, 3, 0);
display.drawCircle(x, 42, 2, 1);
display.display();
delay(150);
display.fillCircle(x, 42, 2, 0);
display.drawCircle(x, 42, 1, 1);
display.display();
delay(200);
display.clearDisplay();
write_setup(1,5,1);
display.println("Distance: ");
display.print(dist);
display.display();
delay(2000);
track();
}
p += 2 + dist/500;
line1[1] += 2 + dist/500;
line2[1] += 2 + dist/500;
line3[1] += 2 + dist/500;
dist += 1;
if(line2[1] > 48){
line1[0] = line2[0]; line1[1] = line2[1];
line2[0] = line3[0]; line2[1] = line3[1];
line3[0] = random(3, 61); line3[1] = -48;
p = 15;
}
if(AcX < -12000){charging();}
else if(AcX > 12000){shoot();}
if(AcY > 12000){display.dim(true);}
else if(AcY < -12000){display.dim(false);}
}
}
void charging(){
display.clearDisplay();
write_setup(0,1,1);
display.println("Charge");
display.display();
delay(2000);
display.clearDisplay();
display.display();
while(true){
read_gyro(&AcX, &AcY, &AcZ);
if(AcX > 12000){track();}
delay(10);
}
}
void loop(){
gravity();
}
Comments