Uduino is another Open Source plugin for Unity, which allow to communicate between a Arduino board with Unity.
This project was created after too much frustration on how to properly connected Unity & Arduino. During past past experiences I was facing some problems: difficulties to detect a specific Arduino board when several are connected, freeze and crash when communicating with serial ports, and many more...
All existing projects mixing Arduino and Unity where either not cross-platform, too complex and complicated (using Firmata to control a LED !? Hell no! ), not compatible with all the libraries or simply not stable enough. What we really need is a simple Arduino file and simple c# functions to read analog pin or write instructions.
Uduino aims to be a comprehensive and easy to setup solution for your Arduino/Unity projects. It features simple declaration both on Unity and Arduino side.
You give a unique name to your arduino board, and declare which variable is readable. For example I want to access mySensor
on the arduino board named myArduinoName
. On Unity, this value is accessible by using UduinoManager.Instance.Read("myArduinoName", "mySensor");
. Uduino is handling the detection of the boards and the serial connection between the software and the hardware !
1 . Import uduino.unitypackage in your project
2 . Add the library Uduino
from the Arduino
folder to your local Arduino libraries
folder.
3 . On your Arduino project, add on the top of your code :
#include<Uduino.h>
Uduino uduino("myArduinoName"); // "myArduinoName" is your object's name !
4 . On your main Unity script, initialize Uduino:
using Uduino; // adding the NameSpace
public class ExampleScript : MonoBehaviour
{
UduinoManager u; // your Instance is initialized here !
void Start() ... // continue your code
}
5 . Add the reading/writing methods, and you're good to go !
using Uduino;
public class ExampleScript : MonoBehaviour
{
int ledPin = 11;
void Start() {
UduinoManager.Instance.InitPin(ledPin, PinMode.PWM);
}
void Update() {
UduinoManager.Instance.Write(ledPin, Time.time);
}
}
Download uduino.unitypackage and import it in your current project or open this repository with Unity Editor.
The Arduino
folder in this repo contains Uduino
library and examples for Arduino. Merge it with your local Arduino folder.
Uduino is partially based on SerialCommand by Steven Cogswell, released under GPL License. However this library is not needed to run Uduino.
This new version has two new features, the custom editor panel and a custom Logger.
The debug panel is automatically attached to UduinoManager.cs
. It displays all connected boards, with their name, last messages received and sent.
Uduino now works also in editor mode, you can detect the connected boards and send custom messages to try your arduino code.
With the custom logger you can chose how much messages you want to be displayed on the console. Feature helpful for debugging, the settings can be changed in the custom inspector.
Examples can be found under Assets\Uduino\Examples
. Their respective arduino code are on the library folders (Arduino IDE\Examples\Uduino
). It might be the easiest solution to understand Uduino !
Here is the steps to have Uduino working.
- Add
#include<Uduino.h>
as dependency - Instantiate Uduino and define the name of your board :
Uduino uduino("sensorArduino");
- Add new commands in Setup()
- Update Uduino in the loop.
if (Serial.available() > 0) uduino.readSerial();
- Add he namespace
using Uduino
at the to of your script - Declare
UduinoManager u;
as new variable (note: The Instance is created the First time you call Uduino.Instance . It's recommended to declare it as variable to find you connected boards on start.)
Read the value of a sensor connected to the pin A0 of the board.
#include<Uduino.h>
Uduino uduino("myArduinoName"); // Declare and name your object
void setup()
{
Serial.begin(9600);
uduino.addCommand("mySensor", GetVariable); // Link your sensor reading (called "mySensor") to a function
}
void GetVariable() {
Serial.println(analogRead(A0));
}
void loop()
{
if (Serial.available() > 0) // verify if the serial is available...
uduino.readSerial(); // ...then process Uduino. /!\ This part is mandatory
}
using UnityEngine;
using System.Collections;
using Uduino;
public class ReadSensor : MonoBehaviour {
UduinoManager u;
void Awake ()
{
UduinoManager.Instance.OnValueReceived += OnValueReceived; //Create the Delegate
}
void Update ()
{
UduinoManager.Instance.Read("myArduinoName", "mySensor"); // Read every frame the value of the "mySensor" function on our board.
}
void OnValueReceived(string data, string device)
{
Debug.Log(int.Parse(data)); // Use the data as you want !
}
}
Note : To retrieve the data on Unity without creating any freeze of your application, you need to create a new delegate function.
Send a PWM value from unity to arduino, to light set the light intensity of a LED.
#include<Uduino.h>
Uduino uduino("ledIntensity");
void setup()
{
Serial.begin(9600);
pinMode(11,OUTPUT);
uduino.addCommand("SetLight", SetLightValue); // The function to be executed when we receive the value from Unity
}
void SetLightValue() {
char *arg;
arg = uduino.next(); // The arg char buffer is read and stored
analogWrite(11,uduino.charToInt(arg)); // The function uduino.charToInt(); converts a char* to a int
}
void loop()
{
if (Serial.available() > 0)
uduino.readSerial();
delay(50);
}
using UnityEngine;
using System.Collections;
using Uduino;
public class SendLedIntensity : MonoBehaviour {
[Range(0, 255)]
public int intensity = 0;
void Update ()
{
UduinoManager.Instance.Write("ledIntensity", "SetLight", intensity);
}
}
Uduino works with multiple boards connected to the computer. Be sure to set a different board name for each Arduino board.
using UnityEngine;
using System.Collections;
using Uduino;
public class MultipleArduino: MonoBehaviour
{
UduinoManager u;
int sensorOne = 0;
int sensorTwo = 0;
void Start()
{
UduinoManager.Instance.OnValueReceived += OnValuesReceived;
}
void Update ()
{
UduinoManager.Instance.Read("myArduinoBoard", "mySensor");
UduinoManager.Instance.Read("myOtherArduino", "myOtherSensor");
}
void OnValuesReceived(string data, string device)
{
if (device == "myArduinoBoard") sensorOne = int.Parse(data);
else if (device == "myOtherArduino") sensorTwo = int.Parse(data);
}
}
Unlike other Unity/Arduino plugins, Uduino is compatible with any other Arduino libraries ! Example below with Arduino's Servo
library.
####Servo.ino (Arduino)
#include<Uduino.h>
Uduino uduino("servoBoard");
#include <Servo.h>
Servo myservo;
void setup()
{
Serial.begin(9600);
myservo.attach(9);
uduino.addCommand("R", rotate);
}
void rotate() {
char *arg;
arg = uduino.next();
myservo.write(uduino.charToInt(arg));
}
void loop()
{
uduino.readSerial();
}
using UnityEngine;
using System.Collections;
using Uduino;
public class Servo : MonoBehaviour {
[Range(0, 180)]
public int servoAngle = 0;
private int prevServoAngle = 0;
void Update()
{
OptimizedWrite();
}
void OptimizedWrite()
{
if (servoAngle != prevServoAngle) // Condition to not send data each frame
{
UduinoManager.Instance.Write("servoBoard", "R", servoAngle);
prevServoAngle = servoAngle;
}
}
}
Rather than declaring a delegate function (mainly for prototyping), the c#
language allows to declare on-the-fly actions. It can reduce the reading code to a simple line :
// ...
public int sensorOne = 0;
void Update ()
{
UduinoManager.Instance.Read("myArduinoBoard", "mySensor", action:((string data) => sensorOne = int.Parse(data)));
}
}
A function trying to read the of a Serial port pauses its execution until the reading is complete. If the reading never happens... the software crash ! Because Unity is mono-thread, opening a new thread to do some other calculations might not be safe. However, Uduino has a thread safe function to read and write on the serial port. The values retrieved are transmitted from the side thread to the main, and we use delegates to do that. You can then use safely UduinoManager.Instance.Read(..)
in your script.
Name | Description |
---|---|
readSerial() |
Process Uduino every clock turn. Required in the loop() function. |
addCommand(string, void) |
Attach a command to a specific function. The function will be triggerd when the event is called by Unity |
charToInt(args) |
Convet chars* to int |
clearBuffer() |
Clear Serial buffer |
Send a read command to a specific Arduino board. A Read() command will be returned on the OnValueReceived() delegate function.
Name | Description |
---|---|
target |
System.String Target device name. Not defined means read everything |
variable |
System.String Variable watched, if defined |
timeout |
System.Integer Read Timeout, if defined |
action |
System.Action Action callback |
Write a command on an Arduino
Name | Description |
---|---|
target |
System.String Target device name. Not defined means read everything |
message |
System.String Message to send to the Arduino board |
Write a command on an Arduino with a specific value
Name | Description |
---|---|
target |
System.String Target device name. Not defined means read everything |
message |
System.String Message to send to the Arduino board |
value |
System.Integer Value associated with the message |
Send multiple messages with different values.
Name | Description |
---|---|
target |
System.String Target device name. Not defined means read everything |
message |
System.String[] Messages to send to the Arduino board |
values |
System.Integer[] List of values to be sent. Value #is associated with message # |
Debug.Log() the status of all connected Serial Ports devices.
Close all opened serial ports.
To simplify the debug of serial communication, a custom Logger is available.
Custom logger with priorities. The level can be set on the inspector or at runtime with Log.SetPriority(level)
Name | Description |
---|---|
message |
System.String Message to debug |
Define the logger priority.
Name | Description |
---|---|
level |
*Uduino.Level {INFO, WARNING, ERROR, NONE} * Level of prioriy. |
- Delete
Assets\Uduino
in your Unity project and replace it with the last version. - Replace
libraries\Uduino
folder in your localArduino
folder by the new one on this repo.
I experience the error : The type or namespace name Ports' does not exist in the namespace
System.IO'
Be sure to set the API Compatibility level to .NET 2.0 (and not .NEt 2.0 Subset). This setting is located under Edit\Project settings\Player
.
Be sure that Uduino custom debug levels, is set not set to "NONE". If so, Uduino will hide all the messages in the console, including some important messages ("Arduino found", etc ).
It's not mandatory. If the script is not attached to any game object of your scene, the first call of UduinoManager.Instance
will create a new game object.
You can explain your problem on a new issue.
Uduino is an OPEN Open Source Project. This means that:
Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.
This is an experiment and feedback is welcome. I'll be very happy to have your contribution on this library. If you create something interesting with uduino, add it to the examples folder, submit a pull-request, and we'll take a look.
- Unity: Arduino: Create a "simple" Sketch
- Unity: Write(string target, string[] message, int[] value) could take a 2D array as parameter ?
- Arduino: Introduce a custom delay, to avoid blocking situations ?
- Documentation: Explain Arduino uduino_hardwareonly mode
Current Version: 1.1
Last stable update: Nov 30 2016