How To Save Serial Port Data to a Variable?
Hello, I am streaming Input Data from a hardware device with sensors through the Serial Port and into Unity. Here is my code streaming into Unity. I need to save the data that is being printed to the Console Log to a variable that I can use. Any ideas?
using UnityEngine;
using System.Collections;
using System.IO.Ports;
public class CountTest : MonoBehaviour {
SerialPort sp = new SerialPort("COM9", 57600);
void Start () {
sp.Open ();
sp.ReadTimeout = 1;
}
void Update ()
{
try{
print (sp.ReadLine());
}
catch(System.Exception){
}
Answer by Thomas-Mountainborn · Sep 24, 2015 at 06:50 PM
string line = sp.ReadLine();
...that's about it. I'm not sure I see what the problem is.
However, you should know that .ReadLine() blocks the thread until a message is received. Since you put that line in the Update() loop, the main Unity thread will be blocked by this script, and either block the game entirely or cause severe frame rate drops, even when your device is sending messages regularly. Because the DataReceived event does not work in Unity's Mono version, you will need to read the serial port input on a separate thread and feed it back to the main thread in a safe way.
Here is the code to do so:
public class SerialComms
{
private const string PORT = "COM3";
private SerialPort _port;
public int LatestLine{ get; set; }
private bool _runThread = true;
public SerialComms()
{
_port = new SerialPort(PORT, 9600);
_port.Open();
Thread pollingThread = new Thread(RunPollingThread) { IsBackground = true };
pollingThread.Start();
}
public void Stop()
{
_runThread = false;
_port.Close();
}
private void RunPollingThread()
{
while (_runThread)
{
PollArduino();
}
}
private void PollArduino()
{
if (!_port.IsOpen)
return;
LatestLine = _port.ReadLine();
}
}
In your MonoBehaviour, you will have to create an instance of this SerialComms class, and check the LatestLine property in the Update() loop. Also, be sure to Stop() it in OnApplicationQuit().
Hey man , do you wanna help me on my little project ? I am reading values from an accelerometer&gyro i get 3 values from Arduino and have to rotate an object accordingly. I am facing the same issue , my data gets too slow to Unity and update waits for the readline. I wanna do it on threads as you suggested but I don't understand if I do it correctly because Unity freeze.
Here is my code
public class SerialThread : $$anonymous$$onoBehaviour {
SerialComms sc = new SerialComms();
void Update(){
if (sc.LatestLine != null) {
string value = sc.LatestLine;
string[] vec = value.Split (',');
print ("ax= " + vec [0] + " ay= " + vec [1] + " az= " + vec [2]);
}
}
}
I've used the SerialComms , but i make a change to funciton LatestLine , i've set it to string , ins$$anonymous$$d of int .
What do you think ?
And the SerialComms class is unchanged? I don't know why Unity would be waiting on the ReadLine to return then, since it's not running on its main thread. Are you sure that's what's causing the slow downs? Can you take a look in the profiler and see what's going on exactly?
Answer by Surfninja · Sep 25, 2015 at 07:27 PM
@ThomasMountainborn : Thank you for the reply, The first line about string line = sp.ReadLine(); is what I was trying to achieve only I need an integer. Sorry I wasn't clear in my original statement but I basically am looking for this:
int A = sp.ReadLine(); int B = 5;
A * B = x;
Debug.Log(x);
Any data you read from the serial port is either given as a string or as bytes. If you want to get a number out of it, you will have to write the number as a string or as a series of bytes on your device, and then read them back in the same way in Unity. If you wrote the number as a string (so a series of ascii characters, most likely), you can simply do
int value = int.Parse(sp.ReadLine());
Or a variant thereof, using int.TryParse() for safety, for instance.
Thank you for the helpackages thus far. I'm in a very remote location where it's a time consu$$anonymous$$g process to get information online since I'm basically using dial up. Do you have a direction I could be spending my time to improve my skills specifically for this project? Or if you have the time I would really appreciate it if you could walk me through this issue and I could learn along the way. I would really appreciate this...
@$$anonymous$$$$anonymous$$ountainborn: So I think Im making progress but still not quite there. So I added your line, came up with an error but the new Visual Studio has helpful tips. It said to add private object unitA; at the top of my script, then your code: int unitA = int.Parse(sp.ReadLine()); inside the void Start. I try to Debug,Log my unitA to see if its working and my continual error message is: Null UnityEngine.Debug:Log(Object) Count:Update() (at Assets/Count.cs:26) Heres my full code from both ends. Arduino Hardware Sensor Device Sending Data Through Serial Port:
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LS$$anonymous$$303_U.h>
#include <math.h>
float count = 0;
void setup() {
Serial.begin(57600);
}
void loop() {
count = count +1;
if(count == 10000)
count = 0;
Serial.print("Test: ");
Serial.println(count);
delay(1000);
}
And my Unity Code:
using UnityEngine;
using System.Collections;
using System.IO.Ports;
public class Count : $$anonymous$$onoBehaviour {
SerialPort sp = new SerialPort("CO$$anonymous$$9", 57600);
private object unitA;
void Start () {
sp.Open ();
sp.ReadTimeout = 5;
int unitA = int.Parse(sp.ReadLine());
}
void Update ()
{
try
{
Debug.Log(unitA);
//print (sp.ReadLine());
}
catch(System.Exception){
}
}
The code you just posted shows me that your understanding of C# or program$$anonymous$$g in general is just too limited to finish this project. I could tell you exactly what you're doing wrong, but you will run into another issue immediately. So I advise you to take your time, do some basic C# tutorials first and then some Unity tutorials, and come back to your project only once you fully understand what you are doing.
Your answer
Follow this Question
Related Questions
Crouching and sprinting doenst work in this script 0 Answers
Comparing a variable (The right answer) to user input. 2 Answers
Subtraction Error 0 Answers
Vibrating Xbox 360 controller without using Xinput? 0 Answers