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.

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

Leave a Reply

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