Controlling LED RGB Strips with Unity and Arduino

Recently I was asked to create a LED lighting controller that would be part of a bigger interactive experience controlled by Unity. More specifically, a lighting system behind a transparent OLED. There were 4 channels of lighting that needed to be independently faded on or off.

There are a lot of tutorials out there on connecting Unity to Arduino, and driving LEDs with Arduino, but none that I could find that put everything together nicely. So I’ll share my experience here for anyone that is tasked with the same thing. This tutorial is based on PC and uses .NET, so it will require adaptation for other platforms.

Arduinos/PC communications are usually accomplished via COM ports. I used the SerialPort class in Unity. This is not typically included in the .NET subset, so be sure to go to player settings and set the API compatibility to .NET 2.0.

  1. Go on Edit | Player Settings to open the PlayerSettings in the inspector;
  2. From Optimization, look for Api Compatibility Level and select .NET 2.0.

Unity2

Now I created a scene with some buttons for integration testing.

Unity

Since I made my TurnOnLight and TurnOffLight functions public, it’s easy to connect my buttons with the correct parameters.

BottonConnect

And here is my c# code:


using UnityEngine;
using System.Collections;
using System.IO.Ports;
public class MenuScript : MonoBehaviour {

public string MyComPort = "COM2";//This should be accessible from a config file

public SerialPort serial;
void Start() {

serial = new SerialPort(MyComPort, 9600);
}

// Use this for initialization
public void TurnOnLight (int LightNum) {
if (serial.IsOpen == false)
serial.Open();
if (LightNum == 1) serial.Write("A");
if (LightNum == 2) serial.Write("B");
if (LightNum == 3) serial.Write("C");
if (LightNum == 4) serial.Write("D");
}

// Update is called once per frame
public void TurnOffLight (int LightNum) {
  if (serial.IsOpen == false)
  serial.Open();
  if (LightNum == 1) serial.Write("a");
  if (LightNum == 2) serial.Write("b");
  if (LightNum == 3) serial.Write("c");
  if (LightNum == 4) serial.Write("d");
  }
}

As you can see, I’m just writing A/B/C/D and a/b/c/d to the COM port to message the Arduino.

Note that the baud rate is 9600 and Com port is 2. This is set by the OS. There are ways to autodetect which com port the arduino is plugged in to, but you will have to write a call and response between Unity and the Arduino, and force unity to try all available COM ports when it initializes. For now I just have a look at the device manager or the arduino editor to see what COM port the OS assigned the Arduino and make sure it’s correct here.

Now to my Arduino sketch:

The Arduino will fade the LEDs in and out using PWM (Pulse Width modulation). This is basically turning on and off the LED (Pulsing) to achieve the desired brightness, and with a linear face effect, the Pulsing speeds up or slows down. Note I created some integer variables to store the value of the brightness of each of my LEDs in memory.


int led1 = 5;          // the PWM pin the LED is attached to
int led2 = 9;
int led3 = 10;
int led4 = 11;

int currentval_Led1 =0;
int currentval_Led2 =0;
int currentval_Led3 =0;
int currentval_Led4 =0;

int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by
unsigned long StartTime;
unsigned long ElapsedTime;
unsigned long CurrentTime;
int data;
// the setup routine runs once when you press reset:
void setup() {
Serial.begin (9600);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
}
void loop() {
if (Serial.available())
{
data = Serial.read();
if(data == 'A')   { fademyled (led1,1); fademyled (led2,1);}
if(data == 'a') { fademyled (led1,0); fademyled (led2,0);}
// and so on.. B/C/D
}
}

void fademyled (int targetled, int onoff){
Serial.println("FadeLedStart");
StartTime = millis();

Serial.print("LED Values =");

if (targetled==led1) brightness=currentval_Led1;
if (targetled==led2) brightness=currentval_Led2;

if (onoff ==1){
while (brightness <= 255)
{
analogWrite(targetled, brightness);
brightness = brightness + fadeAmount;
delay(60);
}
brightness =255; //(just in case if goes under from changing fade variables above)
}
if (onoff ==0){
while (brightness >= 0)
{
analogWrite(targetled, brightness);
brightness = brightness - fadeAmount;
delay(30);
}
brightness =0; //(just in case if goes under from changing fade variables above)
}
//Read stored values
if (targetled==led1) {currentval_Led1 = brightness;}
if (targetled==led2) {currentval_Led2 = brightness;}
if (targetled==led3) {currentval_Led3 = brightness;}
if (targetled==led4) {currentval_Led4 = brightness;}

CurrentTime = millis();
ElapsedTime=CurrentTime-StartTime;
Serial.println(ElapsedTime);

Serial.println("Done. Led Values should be: ");
Serial.println(currentval_Led1);
Serial.println(currentval_Led2);

}

You can use any pins on your Arduino to do this, as long as they are designated as PWM. However you cannot drive a high powered LED strip with an adruino plugged into a USB port. I used this 30A MOSFET to drive the LED strips. A MOSFET is a fancy transistor package that allows you to drive a large load with a small control signal, which is what we are sending from the Arduino.

TO_220_3_t

I was driving four strips of high brightness LED strips (not RGB), and the power supply I was using could not fade in and out smoothly. After I upgraded to a industrial grade 10A supply,  It worked beautifully. Here is the circuit that I used, thanks to Adafruit!

rgb-led-strips-mosfets