Introduction: Make a Punching Bag in Arduino and Unity Using a Joystic and Balloon

About: Hi eveyone, my name is Raed, I'm a computer science student from Jordan, I'm passionate about learning and developing mobile games in Unity3D. I love to explore new ways and methods such as sensors as inputs f…

this instructable simply is about reading input from an arduino joystic but with a slight twist! we are going to turn our joystick into a punching bag :) and even better we will visualize the whole process in unity3D

please note this whole instructable is available as a playlist on my youtube channel, if your looking for a more detailed instructions please watch the link below :

playlist

Step 1: Lets Collect the Components

all you need for this is

1- joystick

2- balloon

3- silicon and lighter

4- 4 male to female wires

Step 2: Lets Make Our Punching Bag

1- inflate the balloon to a size of your preference

2- wrap the head of the balloon's knot to the knob of the joystick

*if we were to punch the balloon at this time it wouldn't move the joystick as the knot serves as a joint so we will need to:

3- using hot silicon attach the knot to the knob

and congratulations our punching bag is ready :)

Step 3: Arduino Code

in arduino we simply are going to read the joystick x and y values, but the main question is when do I send my values and how to make sense of them. do I want send it all the time? the answer is no, as you will see later we will be adding force in unity and having it added constantly regardless of how small would cause it to behave like crazy, so we need to determine a value that indicates a joystick has moved enough ie was punched

notice that the joystick at resting position doesn't give you 0,0 but instead a median value between 0 and maximum reading which is by default 1023 , i mapped the values for easier calculations from (0, 255);so our resting position is about(124,124) and then I determined that half way between 124 and 255(186) and 124 and 0(62) will be indicative of significant movement and thats when I need to sen my values

void setup() {
// put your setup code here, to run once:
  Serial.begin(9600);
  
  
}
void loop() {
  // put your main code here, to run repeatedly:
  int x = analogRead(A0);
  int y = analogRead(A2);
  
  x = map(x, 0, 1023, 0, 255);
  y = map(y, 0, 1023, 0, 255);
  
  if (x > 185 || x < 62 || y > 185 || y < 62) {
    Serial.flush();
    
    Serial.print(x);
    Serial.print(','); 
    Serial.print(y);
    
    Serial.println();
    delay(20);
  }
  delay(20);//writetimout
}

Step 4: Unity Code Part1

in this part we will make the punching bag and as always please make sure that your unity projects allows serial Communication by

edit>project settings>player> scroll down to optimization and change api compatibility to .NET 2.0

1- create a cylinder which will be out punching bag

2-attach a rigidbody component to it. a rigidbody simply allow the object to be subjected to laws of unity physics such as gravity, force , mass...etc

3- attach a spring joint to it and make sure to place the pivot (center of rotation) at the top center of the cylinder

4-now we need to change some physics properties in our joint and rigidbody to make the bag more resilient

a-change angular drag to 10

b-change spring to 70

c-set the damper to 40

Step 5: Unity Part 2 Lets Read and Move the Bag

you can follow the video tutorial for step by step explanation or simply attach the following script to your cylinder and have fun :)

using UnityEngine;
using System.Collections; using System.IO.Ports;
public class Punch : MonoBehaviour {
    public int  x , y ;
    public int power;
    public float angle;
    public AudioSource player;
    private Vector3 punchDir;
    private Rigidbody punchingBag;
    private SerialPort stream = new SerialPort(@"\\.\" + "COM11", 9600);
	// Use this for initialization
	void Start () {
        
        stream.Open();
        stream.ReadTimeout=25;
        StartCoroutine(readData());
        punchingBag = GetComponent();
    }
	
	// Update is called once per frame
	void Update () {
        punchDir = new Vector3(x, 0, y);
        angle = Vector2.Angle(Vector2.up, punchDir);
        if (angle < 0) {
            Debug.Log("negative Value");
        }
	}
    public void punchIt(int _x ,int _y) {
       
        punchDir = new Vector3(_x, 0f, _y);
        punchingBag.AddForce(power * punchDir);
        player.Play();
    }
    IEnumerator readData() {
        while (true) {
            if (stream.IsOpen)
            {
                try
                {
                    string value = stream.ReadLine();
                    string[] values = value.Split(',');
                    int x1 = int.Parse(values[0]);
                    int y1 = int.Parse(values[1]);
                    Debug.Log(x1);
                    if (x1 >= 62 && x1 <= 185)
                    {
                        x1 = 0;
                    }
                    else if (x1 > 185)
                    {
                        x1 = -1;
                    }
                    else if (x1 < 62)
                    {
                        x1 = 1;
                    }
                  
                    if (y1 >= 62 && y1 <= 185)
                    {
                        y1 = 0;
                    }
                    else if (y1 > 185)
                    {
                        y1 = -1;
                    }
                    else if (y1 < 62)
                    {
                        y1 = 1;
                    }
                   
                    Debug.Log(x1);
                    //Debug.Log(y1);
                    punchIt(x1, y1);
                }
                catch (System.Exception)
                {
                   // Debug.Log("TimeOut Exception");
                }
            }
            yield return null;
        }
       
    }
}