Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct here to familiarize yourself with the rules and how to post constructively.

  2. Unity 2022.1 is now available as the latest Tech release.
    Dismiss Notice
  3. Improve your project's performance with our new guide on profiling in Unity.
    Dismiss Notice

Help Wanted Problem receiving info from an Arduino in Unity

Discussion in 'Scripting' started by Latchh, Nov 20, 2020.

  1. Latchh

    Latchh

    Joined:
    Aug 10, 2020
    Posts:
    46
    I have an arduino hooked up to a rotary encoder which I am using to send information to Unity, with the intention of having these data control the player movement.

    However, I am having a problem where Unity will incorrectly read the string I am sending from the Arduino. I have tried a few variations of code on the arduino side, but they all end up with the same problem.

    At the moment, the Arduino counts the increment on the rotary encoder, returning a number between 0 and 1023. Unity polls the Arduino to read the latest value each time Update() is called.

    I have copied both codes I am using below. I am expecting to print a number between 0-1023 to the Unity console. This generally works, but occasionally the printed number is not the same number that the arduino is sending. For example, the following numbers should be read by Unity when it polls the Arduino:
    [500, 512, 520, 530, 541]
    But instead Unity will read something like:
    [500, 512, 2, 0, 530].

    I have also tried things like having the Arduino accumulate from 0, then whenever Unity polls the Arduino it will also send a signal telling the Arduino to reset it's counter back to 0, as I was hoping that dealing with smaller integers/string lengths might solve my problem, however I still had the same issue.

    I am assuming that this is an issue of the data sent from the Arduino becoming malformed when Unity attempts to read it, as the serial monitor for the Arduino always shows the expected output. However, after playing around with it for a while and trying to google some similar problems I have been unable to come up with a solution. I was wondering if anyone has experienced any similar issues, or has any idea about how I might fix this?

    To provide some additional information, the "malformed" readouts on the Unity side always seem to be single integers (so a string with length of 1), it will never randomly spit out an unexpected 3-digit number. Also, oddly this problem only seems to occur when the rotary encoder is moving quickly. So it is not an issue of the string length sent by the Arduino itself, but might be related to the frequency at which Unity is reading information from the Arduino. The way the code is set up, Unity will only receive something from the Arduino if the rotary encoder has moved between Update() calls. I have tried playing around with the baud rate, however this did not solve my problem either.

    The Unity code:
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using UnityEngine;
    4. using System.IO.Ports;
    5. using System.Linq;
    6.  
    7. public class TestArduino : MonoBehaviour
    8. {
    9.     SerialPort sp3;
    10.    
    11.     private string xx;
    12.  
    13.     void Start()
    14.     {
    15.         sp3 = new SerialPort("COM3", 250000);
    16.         sp3.DtrEnable = false;
    17.         sp3.ReadTimeout = 1;
    18.         sp3.WriteTimeout = 1;
    19.         sp3.Open();
    20.     }
    21.  
    22.     void Update()
    23.     {
    24.         if (Input.GetKeyDown(KeyCode.Escape) && sp3.IsOpen)
    25.             sp3.Close();
    26.  
    27.         xx = CheckForRecievedData();
    28.         if (xx != string.Empty)
    29.         {
    30.             print(xx);
    31.            
    32.         }
    33.     }
    34.     public string CheckForRecievedData()
    35.     {
    36.         try
    37.         {
    38.             string inData = sp3.ReadLine();
    39.             sp3.BaseStream.Flush();
    40.             sp3.DiscardInBuffer();
    41.             return inData;
    42.         }
    43.         catch { return string.Empty; }
    44.     }
    45. }
    and the Arduino code:
    Code (CSharp):
    1. #define encoderBlack 3
    2. #define encoderOrange 4
    3. #define encoderWhite 5
    4. int pinA = LOW;
    5. // int pinZ = LOW; // signals full rotation, unnecessary
    6. int pinB = LOW;
    7.  
    8. int lastPinA = LOW;
    9.  
    10. int encoderPos = 0;
    11. int posMax = 1024;
    12.  
    13. void setup() {
    14.   pinMode(pinA, INPUT);
    15.   // pinMode(encoderOrange, INPUT);
    16.   pinMode(pinB, INPUT);
    17.   Serial.begin(250000);
    18. }
    19.  
    20. void loop() {
    21.   pinA = digitalRead(encoderBlack);
    22.   // pinZ = digitalRead(encoderOrange);
    23.   pinB = digitalRead(encoderWhite);
    24.  
    25.   if(pinA != lastPinA) {
    26.     if (pinB == pinA) {
    27.  
    28.       encoderPos--; // Counter-CW
    29.       if (encoderPos < 0) {
    30.         encoderPos = posMax - 1;
    31.       }
    32.       Serial.print(encoderPos);
    33.       Serial.println();
    34.     }
    35.     else {
    36.       encoderPos++; // CW
    37.       if (encoderPos >= posMax) {
    38.         encoderPos = 0;
    39.       }
    40.       Serial.print(encoderPos);
    41.       Serial.println();
    42.     }
    43.   }
    44.   lastPinA = pinA;
    45. }
    Thanks
     
    Last edited: Nov 25, 2020
    ngjinping likes this.
  2. Latchh

    Latchh

    Joined:
    Aug 10, 2020
    Posts:
    46
    Bumping this post because I made a lot of changes and included new info, and still unanswered
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    24,873
    Gotta warn you, not a lot of people here use Unity with low-level serial port stuff the way you do above with the Arduino. I personally have not written code to hit a UART port since the early 90s, and it was a lot different then.

    Usually serial is handled by a driver that services UART interrupts to read each character, so as not to drop characters. At the current state of Windows / Mac / .NET serial port driver I'm not sure how that surfaces to your application level, but I imagine on the Arduino interest boards you might find some people with working Unity code.
     
  4. Latchh

    Latchh

    Joined:
    Aug 10, 2020
    Posts:
    46
    Ok thanks Kurt, I'll try my luck over on the arduino forums
     
  5. Latchh

    Latchh

    Joined:
    Aug 10, 2020
    Posts:
    46
    I ended up solving my own problem, so I thought I would post here in case anyone experiences something similar.

    It seems like the problem I had was due to the frequency at which the Arduino was printing data, where if the frequency was particularly high I had malformed strings on the Unity end. Maybe this is due to the Arduino writing new data to the top of the queue before Unity had finished reading the previous string?

    Either way, simply limiting the arduino to only run Serial.println() at a fixed interval (using millis() and % or something similar) solved my problem - no more malformed strings on the Unity end.
     
    Kurt-Dekker likes this.
  6. ngjinping

    ngjinping

    Joined:
    Dec 10, 2020
    Posts:
    1
    I'm now facing the same problem with you, but i am still a beginner to coding, I can't really understand how to limit to only run Serial.println() at a fixed interval. Would you help me please?
    Here is my code, if it can help.
     

    Attached Files:

unityunity