Controlling an Arduino from Unity

Later this month I’ll be doing a talk for LUUG (London Unity Usergroup) on using Arduinos with Unity, so to prepare for that I’ve gone through the basic processes of talking to the Arduino from Unity.

The video cannot be shown at the moment. Please try again later.

For this tutorial, you’ll need…


A PC (Mac may have issues with the serial parts)
Unity (4.1.5 used in this tutorial)
An Arduino (I have used an Uno R3)
A green, a yellow and a red LED.
3x 220 ohm resistors
A breadboard
Some jumpers (Little bits of wire)
My project example

And that’s about it.

The Unity code is all in C#

NotSubset

1. When starting this process you’ll need to make sure that the API compatibility level is set to .NET 2.0 and NOT .NET 2.0 Subset. Check the thumbnail for a visual example.

2. It would be best to create the circuit first. I’ve used Fritzing to draw the diagram out.

RYG LED
One I made earlier

 

 

3. Once the circuit has been created, you’ll need to open the RYG.ino file in Arduino and compile, then upload it. This is just a simple script that will change the LEDs over every second and make sure that the circuit is correct. Around this point you should note the COM port the Arduino is on (Tools/Serial Port).

 

int gLed = 10; //corresponds to Pin 10 on the Arduino
int yLed = 11; // Pin 11
int rLed = 12; // Pin 12

void setup() {
pinMode(gLed, OUTPUT); //Sets all the LED pins to Output on start up
pinMode(yLed, OUTPUT);
pinMode(rLed, OUTPUT);

digitalWrite(gLed, LOW);//turns all LEDs off.
digitalWrite(yLed, LOW);
digitalWrite(rLed, LOW);
}

void loop() {

digitalWrite(gLed, HIGH); //turns Green on
delay(1000); // Waits a second
digitalWrite(gLed, LOW); //Green off
digitalWrite(yLed, HIGH); // Yellow on
delay(1000); // Waits a second
digitalWrite(yLed, LOW); // Yellow Off
digitalWrite(rLed, HIGH); //Red On
delay(1000);
digitalWrite(rLed, LOW);
}

unity4. If all is well, the it’s time to get Unity into this. Open up the project contained in the zip and have a look around. You should see three cubes, red, yellow and green. When the project runs the cubes will rotate, I’ve done this so we can witness an issue with the SerialPort.ReadLine() method later. For now we’ll look at the next Arduino example.

5. The RYGFromUnity.ino file is a little different from before. The first thing you’ll need to note is the use of Serial.begin (9600); line. This opens up the Arduino so data can be sent and recieved, and also used for debugging, which will cause an issue with Unity, but more on that in a bit.

The next bit of importance is Serial.readBytesUntil(lf, myCol, 1);
This will cause the Arduino to read in any data coming in through serial until one of two events happen. Either a line feed character is detected; this is identified by lf which is set to 10 and is the first argument or a certain amount of bytes have been read in. This is the third argument and for this example is set to just one byte. The data is stored in the variable myCol, which is set to char and a limit of 20. In readBytesUntil this is the second argument. Or another way to explain it is Serial.readBytesUntil(terminatorCharacter, buffer, byteLimit);

Still with me?

To actually do something with this data we need a comparison. In this example I’ve written it as


if(strcmp(myCol,"r")==0){
       digitalWrite(rLed, HIGH);       
       digitalWrite(yLed, LOW);   
       digitalWrite(gLed, LOW);
   }

If the byte is “r” then turn the red LED on and turn off the others.

That’s it from the Arduino side.

6. The Unity side.

If you look in the project, you’ll see a file named Sending.cs. This is applied to an empty gameObject called Init. This script brings in

using System.IO.Ports;
using System.Threading;

In the class, you’ll notice public static SerialPort sp = new SerialPort("COM4", 9600);

It is important that you check the COM port the Arduino is on and if it is different, then change the string in this line.

When this script comes alive, it’ll open a connection to the Arduino in this function (OpenConnection) it will set the Read.Timeout. This is important as according to Mono

1) There is no event notification for received serial data. If you want to receive data, one must set a timeout and watch for received data by polling ReadByte() when you think there might be data.

http://www.mono-project.com/HowToSystemIOPorts

This means that when receiving data, which I’ll move onto at a later date, you need to know when to check for it, and in most cases you won’t know so it’ll need to be done in the Update. 🙁

In my example you’ll note that sp.ReadTimeout is set to 16. This is so the scene can maintain a framerate of near to 60fps. (16*60 – 960ms). The reason for this is that if the Arduino is not sending any data, Unity will pause for the duration set in ReadTimeout. A number of 200 will drop the frame rate to 5fps. This would be bad and can be seen in my Ultrasonic test from earlier in the year.

This will result in ugly errors, which I am choosing to ignore.

Errors

7. Unity sending data.

In my example I have a simple script which calls a function on the Sending script.

using UnityEngine;
using System.Collections;

public class CallGreen : MonoBehaviour {
   void OnMouseDown() {
     print("Clicked");
     Sending.sendGreen();
   }
}

This is calling

    public static void sendGreen(){
      sp.Write("g");
    }

Which sends the character “g” to the Arduino and is picked up in the bit explained in step 5.

Step 8. Run.

So if all is well, the project should run, the Arduino should be hooked up to the PC and when you hit each cube, the corresponding LED lights up.

Congrats, Unity is controlling the Arduino!

This entry was posted in Arduino, Unity. Bookmark the permalink.

5 Responses to Controlling an Arduino from Unity

  1. Michael says:

    EXCELLENT tutorial Darren!!!

    I love having the ability to create nice user interfaces with Unity. When I stumbled across this tutorial I was totally amazed.

    I’ve replaced the cubes in the scene with a On and Off button (unity GUI) which correspond to Arduino’s digitalWrite High and Low with one LED. And surprisingly it worked.

    Next up is to get this to work with a HC-05 to be able to get this LED to turn on/off I sure hope I can figure it out?

    P.S. Im on an intel Mac and have had no issues.

  2. jonathan says:

    Congratulations for the great help tutorial to the community … I’m learning a lot from your videos … and wanted to understand how to’s When You click on the LED cube and delete When You click on the same LED light?

  3. marc says:

    Hi i watched the video and was wondering if you know if unity can send data to a micro controller. I cant seem to find answer anywhere. What i want to do is use unity to make a gui to control a motor. can i send values such as rpm to the controller from unity, not simply on off. I cannot seem to find the answer to this question (or maybe i m not asking correctly)

    thank you for any guidance you can provide

    • Darrenlloyd says:

      Yes, definitely. You can send float data from unity. I’m copying and pasting bits from an example I have so this isn’t tested, but you’ll need something like…

      using UnityEngine;
      using System.Collections;
      using System;
      using System.IO.Ports;
      using System.Threading;
      using System.IO;
      public class Arduinoing : MonoBehaviour
      {
      public static SerialPort sp;
      void Start()
      {
      sp = new SerialPort(("COM6"), 9600, Parity.None, 8, StopBits.One);
      sp.ReadTimeout = 16;
      sp.Open();
      }

      void Update()
      {
      try
      {
      string message = sp.ReadLine();

      vals = message.Split(',');
      val0 = vals[0];
      val1 = vals[1];
      }
      catch (TimeoutException) { }

      if (Input.GetKeyDown(KeyCode.UpArrow))
      {
      sp.Write("u"); //or send whatever you need, doesn't have to be a char or by keypress
      }

      }
      void OnApplicationQuit()
      {
      sp.Close();
      }
      }

Leave a Reply

Your email address will not be published. Required fields are marked *

Current day month ye@r *