- Home /
Communication between Unity and Arduino Yun via WiFI
Hello community,
I got my hands on an Arduino Yun and have been trying to establish a WiFi communication between the Yun and Unity. I set up a scene in Unity with a button and a default image. By pressing the button a LED on the Yun switches on and off. The LED status is displayed in the Unity scene by the color of the default image. Sounds easy, but it turns out it's not that easy. Especially with no prior experience about arduino. Well, google, my old dear friend, helped and found me some sources to build on. Including a thread of @ben_kidd who tried something very similar a few years ago with a wifi shield instead of a Yun.
Link:Here
After a little bit of tinkering and adjusting I got where I am now: At a somewhat frustrating dead end.
Problem:
I got my two main scripts, Network_Script(C#) and YunServer_sketch(err... C/C++) working without compiling errors. But the connection between Yun and Unity doesnt seem to hold. After a few Debug.Log() and Serial.println trial runs I found out that there is communication during start up. Yun seems to get a somewhat initialising byte and Unity is able to Debug.Log() a whole client.println() command from Yun. But immidiatly after the first tradeoff no more further communication happens.
1. C# - Network_Script
using UnityEngine;
using System.Collections;
using System;
using System.IO;
using System.Net.Sockets;
public class Network_Script : MonoBehaviour
{
bool socketReady = false;
TcpClient mySocket;
public NetworkStream theStream;
StreamWriter theWriter;
StreamReader theReader;
public String Host = "INSERT the public IP of router or Local IP of Arduino";
public Int32 Port = 5555;
public bool lightStatus;
void Start ()
{
SetupSocket ();
}
// Check the stream for now data and change lightStatus
void FixedUpdate ()
{
while (theStream.DataAvailable) {
string recievedData = ReadSocket ();
Debug.Log (recievedData);
if (recievedData == "Light on") {
lightStatus = true;
}
if (recievedData == "Light off") {
lightStatus = false;
}
}
}
// Sets up the Socket
public void SetupSocket()
{
try {
mySocket = new TcpClient(Host, Port);
theStream = mySocket.GetStream();
theWriter = new StreamWriter(theStream);
theReader = new StreamReader (theStream);
socketReady = true;
}
catch (Exception e) {
Debug.Log ("Socket error: " + e);
}
}
public void WriteSocket (string theLine)
{
if (!socketReady) {
Debug.Log ("Socket not ready.");
return;
}
String tmpString = theLine;
theWriter.Write (tmpString);
theWriter.Flush ();
Debug.Log ("Socket ready and Line sent :" + tmpString);
}
public String ReadSocket()
{
if (!socketReady)
return "";
if (theStream.DataAvailable)
return theReader.ReadLine ();
return "NoData";
}
public void CloseSocket()
{
if (!socketReady)
return;
theWriter.Close ();
theReader.Close ();
mySocket.Close ();
socketReady = false;
}
public void MainTainConnection()
{
if (!theStream.CanRead)
SetupSocket ();
}
}'
1. YunServer_Sketch
#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>
YunServer server(5555);
boolean alreadyConnected = false;
void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Bridge.begin();
digitalWrite(13, HIGH);
delay (2000);
digitalWrite(13, LOW);
server.begin();
}
void loop() {
YunClient client = server.accept();
if (client.connected()){
client.println("Connected");
Serial.println("Client: " + client);
process(client);
}
delay(50);
}
void process (YunClient client){
char command = client.read();
client.println(command);
client.flush();
if(command == "1"){
digitalWrite(13, HIGH);
client.println("Light on");
Serial.println("On");
}
if (command == "0"){
digitalWrite(13, LOW);
client.println("Light off");
Serial.println("Off");
}
delay(50);
}
I hope you can help me getting back on track.
with kind regards Sebastian
Does the button in the scene call WriteSocket(), and if so do you get the debug.log() you put in it? Because otherwise it doesn't look like WriteSocket() is being called.
Just to be on the safe side, you should also try writing a loop in your Arduino script that toggles the light on and off and sends the update data, to see if data can be sent. Try also writing a Unity function that sends data regularly to see if Unity's data is sent.
In your Arduino script, it looks like you're checking to see if command == "1"
, but you want to check if command == '1'
- just a single tick, not quotes. Quotes indicate string, single tick is char. Dunno if that's tripping you up, if I had my Uno with me I'd test, but it's something else to check.
Also, in C#, StreamReader.ReadLine() wants to read until it hits a carriage return or newline. From the documentation,
A line is defined as a sequence of characters followed by a line feed ("\n"), a carriage return ("\r"), or a carriage return immediately followed by a line feed ("\r\n"). The string that is returned does not contain the ter$$anonymous$$ating carriage return or line feed. The returned value is nullNothingnullptrunita null reference (Nothing in Visual Basic) if the end of the input stream is reached.
Also, it looks like YunClient is deprecated, BridgeClient is what you should be using, I think.
Those are my initial thoughts - good luck!
Oh also, to see if your process(YunClient client)
function is being called, you should do a Serial.println(command)
as well.
@$$anonymous$$arschallN Thanks for your reply. I posted my current status and scripts a few hours ago. It will be visible once a moderator checked it.(although I'm not sure if this is the norm, since this is my first post in Unity-Answers)
YunClient is deprecated, yes. I'll try and see if there are any changes in behaviour when using BridgeClient and BridgeServer. I just felt safer using the depracted method, since Bridge seemed to have to much to do with the REST method, which I don't want to use.
That's what "\r\n" does, I see. I use it in my current c# script because it was in the original script, which I tinkered with. I kind of used it on the Yun side with "client.readStringUntil(10)", as 10 equals the ASCII code for line feed without realising what it really does. I will definitly add this to the write message of my arduino sketch. This should clear up the freeze in unity, when I try to send a string from Yun.
Not knowing the difference between " and ' definitly tripped me, forcing me to use a round about way of reading information.
Thanks for telling me all this. Once I get back to my Yun Setup I will try implementing this knowledge and keep you updated.
Any updates? I'm curious to know if you've gotten it working.
Hey,
I applied your tipps and did some more research.
I changed the Yun libraries to Bridge ones (BridgeClient, BridgeServer). $$anonymous$$y scripts behaviour did not change, so there was no reason for me to feel insecure about using Bridge libraries.
As for carriage return and line feed, I found out that there is no need to add them additionally as they are included in *.println command (Description
That means, as my Yun currently receives integer values from Unity correctly and there should be no issue in how Yun replies to Unity, the problem lies in how Unity receives Yuns' replies. As in my post below mentioned, Unity keeps freezing when function ReadSocket() is called. This issue seems to lie within the StreamReader and the asynchronous communication as explained here. The ReadSocket() function is apparently supposed to be called in a sub thread so it won't clog the main thread and cause Unity to freeze. But I did not have time to take a look at Threading in Unity and in general to go past this hopefully last obstacle, yet.
Answer by Chaosspirit · Mar 04, 2017 at 09:15 AM
Hello community,
I wasn't able to establish a proper communication between Unity and Yun in which both talk to another. Everytime Yun would send a string, Unity stops writing altogether and doesn't receive anything. But at least I got a one way communication working, in which Unity sends a string and Yun interprets it correctly. I will post my current scripts here, for those that are interested. If you want to add something, feel free to leave your thoughts here.
Unity - C#
using System;
using UnityEngine;
using System.Net.Sockets;
using System.Collections;
using System.IO;
public class Network_Script : MonoBehaviour {
public int value;
internal Boolean socketReady = false;
TcpClient mySocket;
NetworkStream theStream;
StreamWriter theWriter;
StreamReader theReader;
String Host = "SERVER - IP"; // eg String Host = "192.168.1.1";
Int32 Port = ANYPORT; // eg Int32 Port = 5555;
String reader;
void Start(){
SetupSocket ();
}
void Update(){
WriteSocket (value.ToString());
}
public void SetupSocket(){
try{
mySocket = new TcpClient(Host, Port);
theStream = mySocket.GetStream();
theWriter = new StreamWriter(theStream);
theReader = new StreamReader(theStream);
socketReady = true;
}
catch (Exception e){
Debug.Log ("Socket error: " + e);
}
}
public void WriteSocket(string theLine){
if (!socketReady)
return;
String foo = theLine + "\r\n";
theWriter.Write (foo);
theWriter.Flush ();
}
//This part didn't work for me, but I'll leave it here just in case someone else wants to tinker around.
/*public String ReadSocket(){
if (!socketReady)
return "";
try {
return theReader.ReadLine ();
} catch (Exception e) {
Debug.Log ("Error ReadSocket: " + e);
return "";
}
}*/
public void CloseSocket(){
if (!socketReady)
return;
theWriter.Close ();
theReader.Close ();
mySocket.Close ();
socketReady = false;
}
}
Arduino Yun Sketch - C/C++
#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>
#define PORT 5555
YunServer server(PORT);
YunClient client;
static boolean clientActive = false;
String saveString;
int value;
void setup()
{
Bridge.begin();
server.noListenOnLocalhost();
server.begin();
client = server.accept();
}
void loop ()
{
client = server.accept();
if (!clientActive)
Serial.println("New client connection.");
clientActive = true;
if(client.available() > 0)
{
Serial.print("From client: \"");
saveString = client.readStringUntil(10); // 10 equals the ASCII Code for line feed in byte, or at least there ends the information we want to interpret
value= saveString.toInt();
Serial.println(value);
Serial.println("\"");
client.flush();
}
}
with kind regards
Sebastian
PS: I posted this question on the Arduino - Forum as well. There have been no replies yet, but there might be some later.
Arduino Forum - Question
Your answer
Follow this Question
Related Questions
Can't auto find Arduino without crashing 0 Answers
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Unity5 filled my SSD? 0 Answers