Een Schuif Controller.

by PenguinLuigi in Circuits > Arduino

113 Views, 0 Favorites, 0 Comments

Een Schuif Controller.

Schermafbeelding 2024-03-24 212516.png
Rhythm_Dodge_Screenshot_2.png

Voor dit project heb ik een controller gemaakt voor een game (gemaakt in Unity) waar ik mee bezig ben. De hudige game heet Rhythm Dodge. In Unity vang ik op wat de Arduino opstuurt via de Serial Port, om zo de speler in-game te laten bewegen. De behuizing bevat meerdere infrarode beam break sensoren. Deze sensoren roepen de Serial.println(); functie aan, afhankelijk van welke sensoren doorbroken word.

Mijn documentatie is in het Nederlands geschreven. En mijn code in het Engels.

Supplies

Elektronische componenten:

  • Arduino Uno
  • Breadboard
  • Breadboard Printplaat
  • Infrarode Beam Break Sensoren (4 paren)
  • Draadbruggen set
  • Laptop (Met game)

Materialen voor de behuizing:

  • Hout
  • Houtlijm
  • Plakband

Gereedschap/Apparaten:

  • Boormachine
  • Houtzaag
  • Schuurpapier
  • Striptang
  • Soldeerbout
  • Lasersnijder

Concept

EEXL_QeVUAA90tQ.jpg

Eerst was ik van plan iets met bellenblaas te gaan doen, daarna met bellenblaas en mijn game. En uiteindelijk ben ik gaan focussen op het maken van een controller voor mijn game. Geïnspireerd door ritme spellen arcade kasten met een aanraak paneel (cirkel). Zelf heb ik ze nog niet kunnen spelen, dus ik hoopte met mijn controller een klein beetje hetzelfde ervaring te recreëren. (Personen bij arcade kast afbeelding bron: https://twitter.com/bemanistyle/status/1172567569892438016).

Testen Met Buttons

FFROXMXLU5J445U.jpg

Voordat ik het project heb gemaakt heb ik eerst de juist componenten besteld en deze individueel uitgetest. Het hielp om met de ITTT lessen mee te doen en hulp te vragen aan de docenten en mijn medestudenten. Door deze kleine testjes heb ik bijvoorbeeld geleerd een LED met een button te activeren. En later meerdere LEDS met meerdere buttons te activeren. Vervolgens ging ik kijken of ik de button statussen op kon vangen in Unity. Dit heb ik getest door een Debug.Log("Hello World") te activeren wanneer een knop werd ingedrukt.

Elektronische Schema

Arduino_Sketch.png

Testen Met Infrared Beam Break Sensoren

20240324_230627.jpg
20240318_110303.jpg

Mijn volgende stap was om de infrarode beam break sensoren uit te proberen. Eraan toe komen te testen ging heel stroef. Dit komt doordat in het begin de uiteindes van de kabels van de sensoren steeds uit de breadboard vielen. Later kreeg ik van de docent kleine zwarte plastic uitsteeksel om te verbinden aan de uiteindes van de kabels. Zodat de infrarode beam break sensoren steviger in mijn breadboard gestoken konden worden. Zodra ik dit had gedaan voor alle kabels, probeerde ik eerst input te vangen via 1 sensor. Zodra dit lukte stapte ik over naar een links-links, links-rechts, rechts-links en rechts-rechts input. Via 4 sensoren, opgesplitst in 4 pins.

In het begin gebruikte ik ongeveer 16 "if" statements in mijn code, maar omdat ik dat niet netjes vond, heb ik gekeken naar hoe classes werken in de Arduino IDE. Het bijhouden van de sensoren(laser) in een class, maakte mijn code wat overzichtelijker.

De Arduino IDE Code

// Main code: Laser_Input.ino
#include "Laser.h"

Laser laserLL(7, "LL"); // create a laser object and attach it to the pin.
Laser laserLR(6, "LR"); // create a laser object and attach it to the pin.
int leftSideHasNoHands = 0;
int previousLeftSideHasNoHands = 0;

Laser laserRL(5, "RL"); // create a laser object and attach it to the pin.
Laser laserRR(4, "RR"); // create a laser object and attach it to the pin.
int rightSideHasNoHands = 0;
int previousRightSideHasNoHands = 0;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  laserLL.update();
  laserLR.update();

  laserRL.update();
  laserRR.update();
 
  checkLeftSide();
  checkRightSide();
}

// Keeps track of whether or not one of the left side lasers is broken.
void checkLeftSide()
{
  leftSideHasNoHands = !laserLL.getHasHand() && !laserLR.getHasHand();

  if (leftSideHasNoHands && !previousLeftSideHasNoHands)
  {
    Serial.println("LM");
  }
  else if (!leftSideHasNoHands && previousLeftSideHasNoHands)
  {
    // Nothing (yet)
  }

  previousLeftSideHasNoHands = leftSideHasNoHands;
}

// Keeps track of whether or not one of the right side lasers is broken.
void checkRightSide()
{
  rightSideHasNoHands = !laserRL.getHasHand() && !laserRR.getHasHand();

  if (rightSideHasNoHands && !previousRightSideHasNoHands)
  {
    Serial.println("RM");
  }
  else if (!rightSideHasNoHands && previousRightSideHasNoHands)
  {
    // Nothing (yet)
  }

  previousRightSideHasNoHands = rightSideHasNoHands;
}


// Laser.cpp
#include "Laser.h"

Laser::Laser(int pin, String name)
{
  laserPin   = pin;
  laserName = name;

  laserState = 0;
  previousLaserState = 0;

  hasHand = false;

  // initialize the sensor pin as an input:
  pinMode(laserPin, INPUT);

  digitalWrite(laserPin, HIGH);
}

void Laser::update()
{
  // read the state of the pushbutton value:
  laserState = digitalRead(laserPin);

  if (laserState && !previousLaserState) // No hand (unbroken laser)
  {
    // Serial.println("No Hand " + laserName);
    hasHand = false;
  }
  else if (!laserState && previousLaserState) // Hand entered (broken laser)
  {
    // Serial.println("Hand Entered " + laserName);
    Serial.println(laserName);
    hasHand = true;
  }

  previousLaserState = laserState;
}

bool Laser::getHasHand()
{
  return hasHand;
}

int Laser::getState()
{
  return laserState;
}

int Laser::getPreviousState()
{
  return previousLaserState;
}


// Laser.h
#ifndef Laser_h
#define Laser_h

#include <Arduino.h>

class Laser
{
  private:
    int laserPin;
    String laserName;
    bool hasHand;
    unsigned char laserState;
    unsigned char previousLaserState;

  public:
    Laser(int pin, String name);
    void update();
    bool getHasHand();
    int getState();
    int getPreviousState();
};


#endif

De Code in Unity

Een gedeelte van de code in Unity:

public class HandMovement : MonoBehaviour
{
    [Header("Left Hand")]
    private float m_LHandXDirection;

    [Header("Right Hand")]
    private float m_RHandXDirection;

    [Header("Arduino")]
    private SerialPort serialPort = new SerialPort("COM8", 9600);
    private string m_LaserStateL = "LM";
    private string m_LaserStateR = "RM";

    private void Start()
    {
        serialPort.Open();
        serialPort.ReadTimeout = 1;
    }

    private void Update()
    {
        if (serialPort.IsOpen)
        {
            try
            {
                CheckReadLineValue();
            }
            catch(System.Exception e)
            {
                Debug.LogError(e.Message);
            }
        }
        else
        {
            Debug.Log("Serial Port is not open");
        }
    }

    private void CheckReadLineValue()
    {
        string readLine = serialPort.ReadLine();

        if (readLine.Contains("LL") || readLine.Contains("LM") || readLine.Contains("LR"))
        {
            switch (readLine)
            {
                case "LL":
                    m_LHandXDirection = -1f;

                    break;
                case "LM":
                    m_LHandXDirection = 0f;

                    break;
                case "LR":
                    m_LHandXDirection = 1f;

                    break;
                default:
                    break;
            }

            m_LaserStateL = readLine;
        }

        if (readLine.Contains("RL") || readLine.Contains("RM") || readLine.Contains("RR"))
        {
            switch (readLine)
            {
                case "RL":
                    m_RHandXDirection = -1f;

                    break;
                case "RM":
                    m_RHandXDirection = 0f;

                    break;
                case "RR":
                    m_RHandXDirection = 1f;

                    break;
                default:
                    break;
            }

            m_LaserStateR = readLine;
        }
    }
}

Solderen

20240318_212929.jpg

Het solderen was enorm vervelend. De eerste keer dat ik ging solderen, lukte het alles "vast" te solderen. Maar toen begon de horror. De eerste keer dat 1 kabel stuk ging dacht ik "Oh dat repareer ik snel", maar iedere keer dat ik een kabel opnieuw soldeerde, brak een andere af. Dit zou als martel techniek gebruikt kunnen worden. Uiteindelijk ben ik uit haast de kabels ook door elkaar heen gaan solderen. Inplaats van netjes bij de bijbehorende kabels.

Uiteindelijk bleek het zo te zijn, dat ik niet lang genoeg mijn soldeerbout aan de printplaat vasthield. Waardoor het meer was alsof ik de onderkant aan het vastplakken was. Dan echt de kabel aan de printplaat te solderen. Na opnieuw al mijn foutieve soldeer pogingen te repareren, zat alles weer vast.

Behuizing

20240322_140201.jpg
ITTT Behuizing Iteratie
20240322_151212.jpg

De behuizing is gemaakt van meerdere lagen hout. De onderste laag om de ontvangers op te leggen. Daarbovenop een plank om je handen op te leggen. In deze plank zijn gaten geboord zodat de ontvangers geraakt kunnen worden door de lasers. Natuurlijk komen er ook muren zodat er nog een plank bovenop kan komen, waar dan de lasers aan vastgemaakt zijn. Hier bovenop komt een doos waar de Arduino in ligt.

Playtesten

ITTT Schuif Controller

Het werkt! Alleen werkte de controller de eerste keer per ongeluk gespiegeld, maar dat is makkelijk opgelost door mijn Unity code aan te passen. Of de pin volgorde aan te passen.

Conclusie

Ik heb veel geleerd van dit project. Zoals hout verzamelen op school, lasersnijden (een beetje), de machines in de houtwerkplaats gebruiken, hoe je een Arduino gebruikt en verbind met Unity en hoe je niet moet solderen. Als ik meer tijd had gehad, had ik graag Velostat willen leren gebruiken of andere methodes. Om te kijken welke het beste werkt.

Bedankt voor het lezen van mijn documentatie!