Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth

Onderdelen en Benodigdheden

Arduino Nano R3 × 2
SparkFun 9DoF Sensor Stick × 1
Draadjes (generic) × 1
NeoPixel Strip × 1
HC-05 Bluetooth Module × 1
9V Batterij (generic) × 1

Nodige Tools

  • Soldeerbout (generic)

Apps & Online Services

  • Arduino IDE

Over dit Project

Dit project heeft 3 delen: het spelbord/display, de controller, en de master router (Python-script).

Deel 1 – Het Display

Het display is een 15x10 NeoPixel-matrix aangedreven door een Arduino Nano. Het regelt de spel-logica en ontvangt input van het Python-script op de host-computer. Er wordt een bal weergegeven die groeit en verder naar beneden beweegt – dit geeft de illusie van diepte en een bal die op je afkomt. Als een slag gedetecteerd wordt, wordt de bal teruggetekend 'weg van je'.

Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth

Punten

De balrichting (links/rechts) verandert bij elke slag. Mis je de bal, scoort de COM. Mislukt de COM de bal (25% kans), scoort jij. Dit ontwerp is geïnspireerd op Wii Sports Tennis. De score wordt getoond wanneer de COM tegen de speler scoort.

Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth

Highscore

Er is een lopende highscore opgeslagen in een I2C EEPROM op adres 0x04. Het houdt een byte bij met de highscore. Scoor je hoger, dan wordt het adres overschreven. Als de COM 10 bereikt, is het game over. Logica overzicht:

Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth

De Matrix Maken

Het bouwen van de matrix kost tijd. Volg de gids die ik gemaakt heb.

Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth
Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth

Deel 2 – De Controller

De controller is een andere Arduino Nano met een 9DoF-stick (alleen 3,3V!) en een HC-05 BLE-module. Als de versnelling op de X- of Y-as een drempel overschrijdt, stuurt hij een '1' via serie naar de host-PC, waar het naar het display wordt doorgestuurd. De Nano meet de X- en Y-versnelling op vast interval en checkt of de waarden boven/onder 1,5G vallen. Voor de I2C 9DoF-stick heb je de SparkFun-library nodig (download hier) en een tutorial voor aansluiting en basisprogramma's hier.

Voor de raquet gebruikte ik een doos en knipte een raquetvorm uit karton. Eroverheen wit papier met een ontwerp. Een 9V-batterij voedt het geheel – loop de batterij via de Vin-pin op de Nano, anders krijg je ongeregelde 9V! Interna van de raquet:

Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth

Communiceren via Bluetooth

Hoe communiceren raquet en display? Een geheim: ze praten niet direct met elkaar! Een Python-script gebruikt de binnenkomende Bluetooth COM-poort en de matrix COM-poort om informatie door te sturen. Het synchroniseert ook beide systemen, want ze resetten allebei bij serial-initialisatie. De raquet stuurt '1' naar Python via Bluetooth, Python stuurt '1' naar de matrix. Er zit een debounce van 1 seconde op om buffer-overloop te voorkomen (alleen 32-bit buffers).

De Raquet Bouwen

Klik door de afbeeldingen voor de stapsgewijze bouw:

Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth
Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth
Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth
Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth
Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth
Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth

Veel plezier met je nieuwe tennisspel!

Code

Matrix Code (C/C++) – Op de Arduino aan de matrix

#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#include <Wire.h>
#include <EEPROM.h>

#define PIN 6
#define EEPROM_ADR 0x50
#define HS_ADR 0x02
#define NOTE_C1 33
#define SPKR_PIN 3

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(15, 10, PIN,
  NEO_MATRIX_BOTTOM + NEO_MATRIX_LEFT + NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
  NEO_GRB + NEO_KHZ800);

int ball_x = 7, ball_y = 2, radius = 1, r_incr = 1;
bool isSwung = false;
int ball_x_dir = 1, ball_y_dir = 1;
bool isDirRight = true;
int score = 0, COM_score = 0, highscore = 0;
int framerate = 50;
int serial_data;
String score_string = "";
uint16_t colors[] = {matrix.Color(255,0,0), matrix.Color(0,255,0), matrix.Color(150,200,0)};
int melody[] = {0};
int tempo[] = {0};
static unsigned long lastFrame = 0;

void setup() {
  Serial.begin(9600);
  matrix.begin();
  matrix.fillScreen(0);
  matrix.setTextColor(colors[1]);
  randomSeed(analogRead(A2));
  display_scores();
  highscore = read_HS();
  Serial.println(highscore, DEC);
  matrix.setCursor(0,1);
  matrix.print("HS: "); matrix.show(); delay(1000);
  matrix.fillScreen(0);
  matrix.setCursor(0,1);
  matrix.print(highscore, DEC); matrix.show(); delay(1000);
  score_string = "";
}

void loop() {
  if ((lastFrame + framerate) < millis()) {
    update_frame();
    lastFrame = millis();
  }
}

void update_frame() {
  serial_data = Serial.parseInt();
  if (serial_data) isSwung = true;
  else isSwung = false;

  if (ball_y >= 5 && ball_y < 7 && isSwung) {
    if (isDirRight) { ball_x_dir = -1; ball_y_dir = -1; }
    else { ball_x_dir = 1; ball_y_dir = -1; }
    r_incr = -1;
  }
  else if (ball_y >= 8) {
    COM_score += 1; end_round();
  }
  else if (ball_y <= 2) {
    isDirRight = !isDirRight;
    int randNum = random(4);
    Serial.println(randNum);
    if (randNum == 2) { // 25% kans COM mist
      score += 1;
      if (score > highscore) write_HS();
      end_round();
    } else {
      if (isDirRight) { ball_x_dir = 1; ball_y_dir = 1; }
      else { ball_x_dir = -1; ball_y_dir = 1; }
      r_incr = 1;
    }
  }
  ball_x += ball_x_dir;
  ball_y += ball_y_dir;
  radius += r_incr;
  matrix.fillScreen(0);
  matrix.fillCircle(ball_x, ball_y, radius, colors[2]);
  matrix.show();
}

void end_round() {
  if (COM_score >= 10) end_game();
  isDirRight = true; r_incr = 1;
  ball_x_dir = 1; ball_y_dir = 1;
  ball_x = 7; ball_y = 2; radius = 1;
  display_scores();
  matrix.fillScreen(0);
  matrix.fillCircle(ball_x, ball_y, radius, colors[2]);
  matrix.show();
}

void end_game() {
  matrix.fillScreen(0);
  matrix.setCursor(0,1);
  matrix.setTextColor(colors[0]);
  matrix.drawLine(3,0,12,9,colors[0]);
  matrix.drawLine(11,0,2,9,colors[0]);
  matrix.show(); delay(500);
  while(1) { }
}

void display_scores() {
  matrix.fillScreen(0);
  matrix.setTextColor(colors[1]);
  matrix.setCursor(0,1);
  score_string = String(score) + "-" + String(COM_score);
  scrollText(score_string);
  matrix.fillScreen(0); delay(2000); matrix.show();
}

void scrollText(String text) {
  int x = matrix.width();
  for (int i=0; i<24; i++) {
    matrix.fillScreen(0);
    matrix.setCursor(x,2);
    matrix.print(text);
    x -= 1;
    matrix.show(); delay(150);
  }
}

void write_HS() { EEPROM.write(0x04, int(score)); }
int read_HS() { return EEPROM.read(0x04); }

Raquet Code (C/C++)

#include <Wire.h>
#include <SPI.h>
#include <SparkFunLSM9DS1.h>

LSM9DS1 imu;
#define LSM9DS1_M 0x1E
#define LSM9DS1_AG 0x6B
#define PRINT_SPEED 10

static unsigned long lastPrint = 0;
float accelx = 0, accely = 0;

void setup() {
  Serial.begin(9600);
  imu.settings.device.commInterface = IMU_MODE_I2C;
  imu.settings.device.mAddress = LSM9DS1_M;
  imu.settings.device.agAddress = LSM9DS1_AG;
  if (!imu.begin()) { while (1); }
}

void loop() {
  if ((lastPrint + PRINT_SPEED) < millis()) {
    if (imu.accelAvailable()) { imu.readAccel(); }
    lastPrint = millis();
  }
  accelx = imu.calcAccel(imu.ax);
  accely = imu.calcAccel(imu.ay);
  if (accelx <= -1.5 || accelx >= 1.5) {
    Serial.print(1); delay(600);
  }
  else if (accely <= -1.5 || accely >= 1.5) {
    Serial.print(1); delay(600);
  }
}

Python Code

import serial
import time

matrix_port = "COM3"
raquet_port = "COM9"

matrix = serial.Serial(matrix_port, 9600)
racquet = serial.Serial(raquet_port, 9600)

time.sleep(10)
while 1:
    data = racquet.read()
    print(data)
    if data == "1":
        print("hit")
        matrix.write("1")
        time.sleep(1)
    time.sleep(0.05)

Schema's

Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth
Arduino Tennisspel – Virtuele Raquet Ervaring met NeoPixel, Sensoren & Bluetooth

Productieproces

  1. TinyML Taaldetector met Edge Impulse op Arduino Nano 33 BLE Sense
  2. Bouw een real-time gyroscoop-spel met Arduino Nano & MPU-6050 sensor
  3. Arduino Digitale Dobbelsteen: Bouw Je Eigen LCD-willekeurige Getalgenerator
  4. Een Arduino Iron Man bouwen: onderdelen, sensoren en stapsgewijze handleiding
  5. Find Me: Slimme Item Locator met Arduino en Bluetooth
  6. DIY Arduino Luchtbevochtiger Controller met Relais – Veilige Hoogspanningsopstelling
  7. Realtime afstandsmeting met Arduino Sonar & Processing visualisatie
  8. MobBob: Bouw Je Eigen Arduino Robot, Naadloos Bestuurd via Android Smartphone
  9. Een audio-reactieve bureaulamp bouwen met Arduino Nano
  10. NeoPixel Matrix Pong op Arduino Nano: Bouw je eigen neon Pong-spel
  11. Bouw een Aangepaste Arduino Joystick Stuurwiel voor Gaming