Arduino to Unity3D Communication

Hello

First of all, let me say, im very new to this forum and Arduino, so if im posting in the wrong forum, please send me the right way :slight_smile:

I have a problem with the communication between the arduino and unity, unity completely freezes up whenever i try to run the game im making, and i have no idea why.

I am fairly sure that the problem is in the unity part of my code, but i cant be sure, if i outcomment serialPort.ReadLine(); in unity, the game doesnt freeze over.

Here is some code, first the Arduino program:

#define LED 13
#define BUTTON 7

int val = 0;

void setup(){
  Serial.begin(9600);
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT);
}

void loop(){
  Serial.flush();
  
  val = digitalRead(BUTTON); //read the state of the button
  
  if(val == 1){
    Serial.print("I'm High\n");
    digitalWrite(LED,HIGH);  //Turn on the LED
  }else if(val == 0){
    Serial.print("I'm Low\n");
    digitalWrite(LED,LOW); //Turn off the LED
  }
  delay(20);
}

It’s pretty simple right now, but im only in the beginning of the project, and my first priority was to establish a connection between the Arduino and Unity.
Here is the Unity Code:

using UnityEngine;
using System;
using System.Collections;
using System.IO.Ports;

public class SerialPortListener : MonoBehaviour {
	public static string COMPort = "COM3"; //Define the Comport Unity should listen to
	public bool portOpen = false; //If the port is open this boolean is true
	public SerialPort serialPort = new SerialPort(COMPort,9600);
	public bool errorHandling = false; //semi-unused variable at the moment.
	
	public string incomingData = ""; //The Incoming data will be stored in this variable
	
	public int updateInterval = 4; //the delay between updates
	public int updateSlower = 0; //container
	
	public bool useData = false;


	
	// Use this for initialization
	void Start () {
		OpenConnection(); // Open the connection
		if(serialPort.IsOpen){
			Debug.Log("I'm open");
		}
	}

	// Update is called once per frame
	void Update (){
		updateSlower ++; //Recieve data every 4 frames
		if(portOpen && serialPort.IsOpen && updateSlower >= updateInterval){ //
			RecieveInput();
			updateSlower = 0;
		}
	}
	
	public void OpenConnection(){
		if(serialPort != null){ //See if there is a serialport connected
			if( serialPort.IsOpen){ //if the port is already open, then close it.(it shouldnt be open)
				serialPort.Close();
				
				Debug.Log("Closing port as it was already open");
			}else{
				serialPort.Open(); // open the port
				serialPort.ReadTimeout =100; //define the timeout
				portOpen = true;
				
				if( errorHandling){
					Debug.Log("Port open = " + serialPort.IsOpen);
				}
			}
		}else{ //errorcodes
			if(serialPort.IsOpen){
				Debug.Log("Port is already open");
			}else{
				Debug.Log("Port == Null");
			}
		}
	}

	void RecieveInput(){
		try{
			incomingData = serialPort.ReadLine();	//Read the serialport, this is where Unity freezes
										//if i outcomment this line, it works just fine,
										//well, except that i dont recieve anything.
			if(errorHandling){
				Debug.Log("data = " + incomingData);
			}
			useData = true;
		}catch(Exception errorpiece){
			if(useData){
				Debug.Log("Error 1: " + errorpiece);
				useData = false;
			}
		}
	}
}

If i change the Timeout to a value which is less than the delay in the arduino script, then i just get a regular timeout error, but if it is as it is right now, then Unity will freeze and i wont get any response from the program at all, i cant stop the game, i cant quit unity, the only way to quit it is to end the process in the task manager.

I have tried asking some friends about this problem, but they are just as lost as i am, I have tried searching for similar problems, but i havnt found anything which could help me.

Thanks for reading, i’m looking forward to your replies.

Thanks in advance

  • Jeand

Edit: Found out that i can make unity respond again, after having started the game, by unplugging the Arduino while the game is running.

  Serial.flush();

Please explain what you understand this call to do, and why it is here.

    public SerialPort serialPort = new SerialPort(COMPort,9600);

There are plenty of other attributes that may need to be set - start bits, stop bits, parity, write timeout, read timeout, write buffer size, read buffer size, etc.

I've been reading various tutorials about printing to the serial, one of them mentioned that he used Serial.flush to make sure that the port was "cleared" before a new loop started so there wouldn't be any leftover data.

In regards to the other attributes that needs to be set, i've been following an example on google code: http://code.google.com/p/unity-arduino-serial-connection/, and from what i've been able to learn from it, no other attributes are being set, i might have missed something though.

Serial.flush() deletes any unread data in the read buffer. Since you never read anything, it hardly seems necessary to care what is in the buffer.

If you are going to add code to read from the buffer, deleting random amounts of unread data hardly seems the appropriate thing to do.

Thanks, i've tried outcommenting the serial.Flush() command, it still freezes unity up when i run it though :/

So, you are not getting any data from the Arduino. Unity "freezes" because there is no serial data to read.

Are you sure that COM3 is the correct port?

Try sending something from Unity TO the Arduino, and having the Arduino blink the LED once for each character read. Watch the RX light, too. It should blink when data arrives, too.

COM3 is the right port, or at least that's what my device manager tells me, i'll try sending some data the other way and see what happens.

But if unity freezes because there is no data to read, why does it not freeze when i unplug the arduino?

Jeand: COM3 is the right port, or at least that's what my device manager tells me, i'll try sending some data the other way and see what happens.

But if unity freezes because there is no data to read, why does it not freeze when i unplug the arduino?

A theory could be, that your windows box expects a "\r\n" sequence (Environment.Newline is defined this way on windows), while you're only sending "\n".

Have you tried reading from the port without using the unity framework, but f.ex. using a .NET program (or even the serial monitor?). A template for a .net C# program:

using System;
using System.IO.Ports;

namespace B.Serial
{
    class Program
    {
        static void Main(string[] args)
        {
            SerialPort p = new SerialPort("COM3", 9600);
            p.DataReceived += (s, e) =>
            {
                var c = p.ReadExisting();
                Console.Write(c);
            };
            p.Open();
            Console.ReadKey();
            p.Close();
        }
    }
}

The monitor that comes with arduino shows that some data is being sent, but when i try with some program called "serial port monitor" then i can't seem to see any data, though i dont know if thats just me being a noob and not setting the program up correctly.(its some software made by Eltima).

I have not been able to find out how to send data to the Arduino from Unity and then making the LED blink, yet.

Edit:

Seems like "Serial Monitor" does recieve some data, though its coming at a much slower rate than what i intended it to write at, that might just be the program itself though.

Anyway, the computer is recieving data from the Arduino.

Jeand: Anyway, the computer is recieving data from the Arduino.

Is it the right data the computer is receiving? Is it "I'm high"/"I'm low" as it should be? Is there a "newline" after?

About your C#: What happens if you replaces your ReadLine() with a ReadByte() or ReadChar() or ReadExisting() You should get rid of the bool portOpenand only use the serialPort.IsOpen. You'll get a NullReferenceException here:

if(serialPort != null){ //See if there is a serialport connected
 [...]
}else{ //errorcodes
  if(serialPort.IsOpen){
    Debug.Log("Port is already open");
  }else{
    Debug.Log("Port == Null");
  }
}

.. because you're accessing your serialPort even though it's null.

Heh, yeah, This is gonna be a bit embarrasing >_>

It seems like I already tried changing the "ReadLine" to "ReadExisting" earlier, then changed it to \r\n in the arduino script, this caused the game to lock up.

After rereading my scripts again i found this error and changed it back to "ReadLine", after which the script works just fine.

So yeah, if I hadnt cocked it up we'd have fixed this days ago, thanks for the help and patience you've shown me :)