Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Android device - Can't read message from Arduino

Discussion in 'Editor & General Support' started by AnthonyFerryDG, May 15, 2018.

  1. AnthonyFerryDG

    AnthonyFerryDG

    Joined:
    Dec 20, 2016
    Posts:
    2
    Hello there,

    I'm trying to create an app that will be able to communicate with some Arduinos via USB on an Android device. For that, i'm using the Physicaloid library to communicate with the serial port. I managed to send messages to the Arduino (like if the arduino gets the message "on", it turns on a LED), but when it's time to send a string from Arduino to the Android device, things are going a bit weird. For example, when I send "Hello there", sometime I receive "llo there", other times "Hello th" or maybe "llo th". It's a bit random but something is certain, I can't receive the entire message.

    PS: I made an Android plugin for that.

    Here are the scripts I'm using.

    /* -------------------------------------------------------------------*/
    Arduino:

    #define HELLO "hello\r\n"
    #define GOODBYE "goodbye\r\n"
    #define ANSWER "oh, Hi !"

    #define LED 13

    void setup() {
    pinMode(LED, OUTPUT);

    Serial.begin(9600);
    Serial.setTimeout(100);
    }

    void loop() {
    if (Serial.available() > 0){

    Serial.flush();
    String message = Serial.readString();

    if (message.equals(HELLO)) {
    digitalWrite(LED, HIGH);
    Serial.print(ANSWER);
    } else if (message.equals(GOODBYE)) {
    digitalWrite(LED, LOW);
    }
    }
    }

    /* -------------------------------------------------------------------*/

    Java :

    package com.anthonyferry.myplugin;

    import android.content.Context;
    import com.physicaloid.lib.Physicaloid;
    import com.physicaloid.lib.usb.driver.uart.ReadLisener;
    import java.io.UnsupportedEncodingException;

    public class SerialPortCommunicator {

    static Physicaloid _physicaloid;
    static Context _context;
    static String message;

    public static void initialize(Context context, int baudRate){
    _context = context;
    _physicaloid = new Physicaloid(context);
    _physicaloid.setBaudrate(baudRate);
    }

    public static boolean open(){
    if(_physicaloid.open()) {

    // When we get a message from Arduino
    _physicaloid.addReadListener(new ReadLisener() {

    String readStr;

    @override
    public void onRead(int size) {
    byte[] buf = new byte[size];
    _physicaloid.read(buf, size);

    try {
    readStr = new String(buf, "UTF-8");
    } catch (UnsupportedEncodingException e) {
    message = e.getMessage();
    return;
    }
    message = readStr;
    }
    });
    return true;
    }
    return false;
    }

    public static boolean close() {
    _physicaloid.clearReadListener();
    return _physicaloid.close();
    }

    public static boolean isOpen() {
    return _physicaloid.isOpened();
    }

    public static String getMessage() {
    return message;
    }

    public static void sendMessage(String message){

    if (_physicaloid.isOpened()) {
    if (message.length() > 0){
    byte[] buf = message.getBytes();
    _physicaloid.write(buf, buf.length);
    }
    }
    }
    }

    /* -------------------------------------------------------------------*/

    C# Unity to manage Arduino java plugin :
    Code (CSharp):
    1. // This is the script to manage the Arduino
    2.  
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6.  
    7. public class Arduino : MonoBehaviour {
    8.  
    9.     int baudRate = 9600;
    10.  
    11.     AndroidJavaClass unityPlayer;
    12.     AndroidJavaClass arduinoPort;
    13.     AndroidJavaObject context;
    14.  
    15.     static Arduino _instance;
    16.     public static Arduino instance { get { return _instance; } }
    17.  
    18.     bool _initialized = false;
    19.     public bool initialized { get { return _initialized; } }
    20.  
    21.     void Awake() {
    22.         _instance = this;
    23.     }
    24.  
    25.     public void Initialize()
    26.     {
    27.         // Get the activity context
    28.         unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    29.         context = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
    30.  
    31.         // Get the correct android plugin
    32.         arduinoPort = new AndroidJavaClass("com.anthonyferry.myplugin.SerialPortCommunicator");
    33.         arduinoPort.CallStatic("initialize", new object[2] { context, baudRate });
    34.     }
    35.  
    36.     public bool IsOpen { get { return arduinoPort.CallStatic<bool>("isOpen"); } }
    37.  
    38.     public bool Open() {
    39.         return arduinoPort.CallStatic<bool>("open");
    40.     }
    41.  
    42.     public bool Close() {
    43.         return arduinoPort.CallStatic<bool>("close");
    44.     }
    45.  
    46.     public void Write(string message) {
    47.         arduinoPort.CallStatic("sendMessage", message + '\r' + '\n');
    48.     }
    49.  
    50.     public string Read() {
    51.         return arduinoPort.CallStatic<string>("getMessage");
    52.     }
    53. }
    54.  
    /*-----------------------------------------------------------*/

    C# Unity to use with UI

    Code (CSharp):
    1. using System.Collections;
    2. using System.Threading;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.UI;
    6.  
    7. public class TestScript : MonoBehaviour {
    8.  
    9.     public class BoolMonitor
    10.     {
    11.         public delegate bool BoolGenerator();
    12.  
    13.         private string m_name = "";
    14.         private BoolGenerator m_generator;
    15.         private bool m_prevValue = false;
    16.         private bool m_currentValue = false;
    17.         private bool m_currentValueRecentlyChanged = false;
    18.         private float m_displayTimeout = 0.0f;
    19.         private float m_displayTimer = 0.0f;
    20.  
    21.         public string value
    22.         {
    23.             get
    24.             {
    25.                 string msg = m_name;
    26.  
    27.                 if (m_currentValue && m_currentValueRecentlyChanged)
    28.                     msg += ": *True*\n";
    29.                 else if (m_currentValue)
    30.                     msg += ":  True \n";
    31.                 else if (!m_currentValue && m_currentValueRecentlyChanged)
    32.                     msg += ":  False \n";
    33.                 else if (!m_currentValue)
    34.                     msg += ":  False \n";
    35.  
    36.                 return msg;
    37.             }
    38.         }
    39.  
    40.         public BoolMonitor(string name, BoolGenerator generator, float displayTimeout = 0.5f)
    41.         {
    42.             m_name = name;
    43.             m_generator = generator;
    44.             m_displayTimeout = displayTimeout;
    45.         }
    46.  
    47.         public void Update()
    48.         {
    49.             m_prevValue = m_currentValue;
    50.             m_currentValue = m_generator();
    51.  
    52.             if (m_currentValue != m_prevValue)
    53.             {
    54.                 m_currentValueRecentlyChanged = true;
    55.                 m_displayTimer = m_displayTimeout;
    56.             }
    57.  
    58.             if (m_displayTimer > 0.0f)
    59.             {
    60.                 m_displayTimer -= Time.deltaTime;
    61.  
    62.                 if (m_displayTimer <= 0.0f)
    63.                 {
    64.                     m_currentValueRecentlyChanged = false;
    65.                     m_displayTimer = 0.0f;
    66.                 }
    67.             }
    68.         }
    69.     }
    70.  
    71.     public Text debugText;
    72.     public Text answerText;
    73.     public string messageOn;
    74.     public string messageOff;
    75.     public string answer = "pong";
    76.  
    77.     bool isConnected;
    78.     public bool IsConnected
    79.     {
    80.         get
    81.         {
    82.             return isConnected;
    83.         }
    84.  
    85.         set
    86.         {
    87.             isConnected = value;
    88.         }
    89.     }
    90.  
    91.     bool isCoroutineRunning;
    92.     public bool IsCoroutineRunning
    93.     {
    94.         get
    95.         {
    96.             return isCoroutineRunning;
    97.         }
    98.  
    99.         set
    100.         {
    101.             isCoroutineRunning = value;
    102.         }
    103.     }
    104.    
    105.     List<BoolMonitor> monitors;
    106.  
    107.     // Buttons' functions
    108.     public void InitArduino() { Arduino.instance.Initialize(); }
    109.     public void OpenArduino() { Arduino.instance.Open(); }
    110.     public void CloseArduino() { Arduino.instance.Close(); }
    111.     public void ReadArduino() { answerText.text = Arduino.instance.Read() == null ? "no answers" : Arduino.instance.Read(); }
    112.     public void TurnOn() { Arduino.instance.Write(messageOn); }
    113.     public void TurnOff() { Arduino.instance.Write(messageOff); }
    114.  
    115.     void Start()
    116.     {
    117.         monitors = new List<BoolMonitor>()
    118.         {
    119.             new BoolMonitor("isOpen", () => Arduino.instance.IsOpen),
    120.             new BoolMonitor("isConnected", () => IsConnected),
    121.             new BoolMonitor("isCoroutineRunning", () => IsCoroutineRunning)
    122.         };
    123.  
    124.     }
    125.  
    126.     void Update()
    127.     {
    128.         string data = "";
    129.  
    130.         foreach (BoolMonitor monitor in monitors)
    131.         {
    132.             monitor.Update();
    133.             data += monitor.value;
    134.         }
    135.  
    136.         debugText.text = data;
    137.     }
    138. }

    The logic of this program is the following :

    I send a message to Arduino.
    The arduino turn on the LED.
    The arduino send back another message.
    [problem] Can't read the message properly
     
  2. AnthonyFerryDG

    AnthonyFerryDG

    Joined:
    Dec 20, 2016
    Posts:
    2
    Nobody can help me ? Please =) Or maybe this thread is not in the good forum ?
     
  3. Pierrein8

    Pierrein8

    Joined:
    Nov 7, 2016
    Posts:
    6
    Hello AnthonyFerryDG.
    Have you found a solution? I follow your step and same result... i have truncate response from arduino... I start looking in the buffer system of physicaloid, but i don't see what is going wrong...
    Thank you !
     
  4. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    For my Arduino communications, I generally use WiFi instead of Serial. No cable needed!
     
  5. Pierrein8

    Pierrein8

    Joined:
    Nov 7, 2016
    Posts:
    6
    JeffDUnity3d, thank you, but i have a spécial case where (for some people) setting up a wifi is more difficult than plug a usb cable :)
     
  6. Pierrein8

    Pierrein8

    Joined:
    Nov 7, 2016
    Posts:
    6
    So i try to change the buffer size or the thread pause time of 50 ms but all my try where worst than default settings...
    I have to look for offset, because some time it's ok, but 5 time latter, the message is randomly troncated, like o wrong offset...
     
  7. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    What Arduino device are you using? How is serial working out for you? :) One note, all USB cables are not created equal, you might try a different cable.
     
  8. Pierrein8

    Pierrein8

    Joined:
    Nov 7, 2016
    Posts:
    6
    ok my setup is, one samsung galaxy tab A 7" or one Archos 70 Oxygen, for arduino i test with one DUE or one UNO.
    Unity with the above script, arduino with the above script, and two jar files as unity plugin ( the java script above and the physicaloid library).
    With the samsung or the archos tablet same result, with the arduino DUE or UNO same result,
    The DUE working with UartCdcAcm driver and the UNO work with the UartCH340 driver. So i keep the DUE for testing and only look at the UartCdcAcm driver.
    From my log the problem is from mConnection.bulkTransfer(mEndpointIn, rbuf, rbuf.length, 50); in UartCdcAcm.java file.
    In this reading loop i already have truncated message.
    i have to understand bulkTransfer...and the RingBuffer
     
  9. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    As mentioned, don't forget to test different cables (although I doubt it is the issue)
     
  10. Pierrein8

    Pierrein8

    Joined:
    Nov 7, 2016
    Posts:
    6
    so, i test in c# in unity to trim the message + i put a starting and ending character from arduino (to keep the message from start to end). I manage to get the string in the right order and all is good !
     
  11. Axel78

    Axel78

    Joined:
    Dec 13, 2013
    Posts:
    1
    Hello there,

    I did some Andoird apps with the PhysicaloidLibrary. And all works fine.

    I want to do the same as you. But I have no luck.
    I use the Android Studio to create a plugin for Unity.
    Everything is well and I can access the library.
    But I get no connection to the USB.

    In your Android.cs, the line 33 seems not to work at me. Maybe a version modification.
    Code (CSharp):
    1. arduinoPort.CallStatic("initialize", new object[2] { context, baudRate });
    I have to write it so:
    Code (CSharp):
    1. arduinoPort.CallStatic("initialize", context, baudRate);
    I use the same code that you posted above.

    How did you make your plugin?
    Do you have a tutorial about your work?
     
    Last edited: Feb 24, 2019
  12. WhosTheBoss

    WhosTheBoss

    Joined:
    Jan 8, 2013
    Posts:
    64
    Hello,

    I'm getting Gradle build errors in Unity when i try to build an App in Unity.


    CommandInvokationFailure: Gradle build failed.
    /Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/bin/java -classpath "/Applications/Unity/PlaybackEngines/AndroidPlayer/Tools/gradle/lib/gradle-launcher-4.2.1.jar" org.gradle.launcher.GradleMain "-Dorg.gradle.jvmargs=-Xmx4096m" "assembleRelease"

    stderr[
    /Users/UgoOdukwe/Desktop files/some ish/ArduinoTest/Temp/gradleOut/src/main/java/com/anthonyferry/myplugin/SerialPortCommunicator.java:4: error: package com.physicaloid.lib does not exist
    import com.physicaloid.lib.Physicaloid;
    ^
    /Users/UgoOdukwe/Desktop files/some ish/ArduinoTest/Temp/gradleOut/src/main/java/com/anthonyferry/myplugin/SerialPortCommunicator.java:5: error: package com.physicaloid.lib.usb.driver.uart does not exist
    import com.physicaloid.lib.usb.driver.uart.ReadLisener;
    ^
    /Users/UgoOdukwe/Desktop files/some ish/ArduinoTest/Temp/gradleOut/src/main/java/com/anthonyferry/myplugin/SerialPortCommunicator.java:10: error: cannot find symbol
    static Physicaloid _physicaloid;
    ^
    symbol: class Physicaloid
    location: class SerialPortCommunicator
    /Users/UgoOdukwe/Desktop files/some ish/ArduinoTest/Temp/gradleOut/src/main/java/com/anthonyferry/myplugin/SerialPortCommunicator.java:16: error: cannot find symbol
    _physicaloid = new Physicaloid(context);
    ^
    symbol: class Physicaloid
    location: class SerialPortCommunicator
    /Users/UgoOdukwe/Desktop files/some ish/ArduinoTest/Temp/gradleOut/src/main/java/com/anthonyferry/myplugin/SerialPortCommunicator.java:24: error: cannot find symbol
    _physicaloid.addReadListener(new ReadLisener() {
    ^
    symbol: class ReadLisener
    location: class SerialPortCommunicator
    5 errors

    FAILURE: Build failed with an exception.

    * What went wrong:
    Execution failed for task ':compileReleaseJavaWithJavac'.
    > Compilation failed; see the compiler error output for details.

    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

    * Get more help at https://help.gradle.org

    BUILD FAILED in 2s
    ]
    stdout[
    :preBuild UP-TO-DATE
    :preReleaseBuild UP-TO-DATE
    :compileReleaseAidl UP-TO-DATE
    :compileReleaseRenderscript UP-TO-DATE
    :checkReleaseManifest UP-TO-DATE
    :generateReleaseBuildConfig UP-TO-DATE
    :prepareLintJar UP-TO-DATE
    :generateReleaseResValues UP-TO-DATE
    :generateReleaseResources UP-TO-DATE
    :mergeReleaseResources UP-TO-DATE
    :createReleaseCompatibleScreenManifests UP-TO-DATE
    :processReleaseManifest
    :splitsDiscoveryTaskRelease UP-TO-DATE
    :processReleaseResources
    :generateReleaseSources
    :javaPreCompileRelease UP-TO-DATE
    :compileReleaseJavaWithJavac FAILED
    14 actionable tasks: 3 executed, 11 up-to-date
    ]
    exit code: 1
    UnityEditor.Android.Command.WaitForProgramToRun (UnityEditor.Utils.Program p, UnityEditor.Android.WaitingForProcessToExit waitingForProcessToExit, System.String errorMsg)
    UnityEditor.Android.Command.Run (System.Diagnostics.ProcessStartInfo psi, UnityEditor.Android.WaitingForProcessToExit waitingForProcessToExit, System.String errorMsg)
    UnityEditor.Android.AndroidJavaTools.RunJava (System.String args, System.String workingdir, System.Action`1 progress, System.String error)
    UnityEditor.Android.GradleWrapper.Run (UnityEditor.Android.AndroidJavaTools javaTools, System.String workingdir, System.String task, System.Action`1 progress)
    Rethrow as GradleInvokationException: Gradle build failed
    UnityEditor.Android.GradleWrapper.Run (UnityEditor.Android.AndroidJavaTools javaTools, System.String workingdir, System.String task, System.Action`1 progress)
    UnityEditor.Android.PostProcessor.Tasks.BuildGradleProject.Execute (UnityEditor.Android.PostProcessor.PostProcessorContext context)
    UnityEditor.Android.PostProcessor.PostProcessRunner.RunAllTasks (UnityEditor.Android.PostProcessor.PostProcessorContext context)
    UnityEngine.GUIUtility:processEvent(Int32, IntPtr)
     
  13. LeoLamolda

    LeoLamolda

    Joined:
    Apr 4, 2017
    Posts:
    2