Sending a string data from unity to arduino uno

Hello, I`m trying to send a string data from unity to Arduino Uno
The object in Unity rotates and the servo motor also rotates according to the angle of the Unity object. The angle of the Unity object is transmitted to Arduino through serial communication. However, when running Unity and Arduino, Unity displays “Port Open!”, but the servo motor does not rotate. Can you help me with this part?

Below is my code. The first one is unity 3D scripts and the second one is Arduino code.

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

public class SerialCommunication : MonoBehaviour {
    public static SerialPort arduino = new SerialPort("COM6", 9600);
    public GameObject Object;
    float angle;

    void Start () {
        OpenConnection();
    }

    void Update () {
        angle = Object.transform.eulerAngles.y;       
        sendAngle(angle.ToString());
    }

    public void OpenConnection(){
        if(arduino != null){
            if(arduino.IsOpen){
                arduino.Close();
                print("Closing port, because it was already open!");
            }
            else{
                arduino.Open();
                arduino.ReadTimeout = 16;
                print("Port Opend!");
            }
        }
        else{
            if(arduino.IsOpen){
                print("Port is arleady opened");
            }
            else{
                print("Port == null");
            }
        }
    }
    public void sendAngle(string data){
        arduino.Write(data);
    }
}
#include<Servo.h>

#define Servopin 7
Servo servo;
float angle = 90.0;

void setup() {
  servo.attach(Servopin);
  servo.write(angle);
  Serial.begin(9600);
}

void loop() {
  if(Serial.available()){
    String serialData = Serial.readString();
    angle = serialData.toFloat();
    servo.write(angle);
    delay(100);
  }
}

Thank You!

This might help! Made this 2 years ago

1 Like

Well, this essentially does the opposite of what was asked, however an important key point can be extracted from this. Using “println” instead of “print” means we add a new line character to the output that can be detected on the receiving end in order to tell where a new string starts and where one ends. It looks like that readString on the arduino side does not really care about line ends but terminates only based on a timeout. I don’t have an arduino, so I can’t verify, that’s just what the docs imply. If that’s really the case it makes the implementation a bit more difficult. You either have to reduce the timeout and ensure the sending side is waiting long enough before sending the next string so the receiver actually recognises the “end” of the string. Or use a terminating character (usually new line) and detect that on the receiving side to split up the incoming data stream into “packets” that can be processed properly.

Just to be clear: What you’re currently doing is sending out your desired angle as a string once every frame. That would never work at all. The default timeout is 1 second. But you never really wait between your “sends”. At 9600 baud you only get a datarate of about 960 bytes per second. At a framerate of 60 fps you could send out max 16 bytes per frame. This leaves not much space for inserting a detectable pause. So using new line characters (or any other distiguishable character) would be much more reliable. Also you should limit your sendrate. If Unity runs without vsync or on a 120Hz monitor you would get much higher rates that the serial interface can’t handle at all. So your sendbuffer would fill up and you get data loss or exceptions. Either way it certainly won’t work as you want.

Also note you have a delay(100); in your receiving code. That means you only “read a string” 10 times a second while you blast out data on the Unity side. This just doesn’t work together. You really have to plan your protocol and keep the data rates in mind.

1 Like