{"id":306,"date":"2017-02-16T03:16:01","date_gmt":"2017-02-16T03:16:01","guid":{"rendered":"http:\/\/kiphaynes.com\/?p=306"},"modified":"2025-08-28T15:34:14","modified_gmt":"2025-08-28T15:34:14","slug":"controlling-led-rgb-strips-with-unity-and-arduino","status":"publish","type":"post","link":"https:\/\/kiphaynes.com\/?p=306","title":{"rendered":"Controlling LED RGB Strips with Unity and Arduino"},"content":{"rendered":"<p>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.<\/p>\n<p>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&#8217;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.<\/p>\n<p>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.<\/p>\n<ol>\n<li>Go on <strong>Edit<\/strong> | <strong>Player Settings<\/strong> to open the <strong>PlayerSettings<\/strong> in the inspector;<\/li>\n<li>From <strong>Optimization<\/strong>, look for <strong>Api Compatibility Level<\/strong> and select <strong>.NET 2.0<\/strong>.<\/li>\n<\/ol>\n<p><a href=\"https:\/\/kiphaynes.com\/wpress\/wp-content\/uploads\/2017\/02\/Unity2.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-312\" src=\"https:\/\/kiphaynes.com\/wpress\/wp-content\/uploads\/2017\/02\/Unity2.jpg\" alt=\"Unity2\" width=\"390\" height=\"285\" srcset=\"https:\/\/kiphaynes.com\/wp-content\/uploads\/2017\/02\/Unity2.jpg 390w, https:\/\/kiphaynes.com\/wp-content\/uploads\/2017\/02\/Unity2-300x219.jpg 300w\" sizes=\"auto, (max-width: 390px) 100vw, 390px\" \/><\/a><\/p>\n<p>Now I created a scene with some buttons for integration testing.<\/p>\n<p><a href=\"https:\/\/kiphaynes.com\/wpress\/wp-content\/uploads\/2017\/02\/Unity.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-311\" src=\"https:\/\/kiphaynes.com\/wpress\/wp-content\/uploads\/2017\/02\/Unity-1024x625.png\" alt=\"Unity\" width=\"1024\" height=\"625\" srcset=\"https:\/\/kiphaynes.com\/wp-content\/uploads\/2017\/02\/Unity-1024x625.png 1024w, https:\/\/kiphaynes.com\/wp-content\/uploads\/2017\/02\/Unity-300x183.png 300w, https:\/\/kiphaynes.com\/wp-content\/uploads\/2017\/02\/Unity-768x469.png 768w, https:\/\/kiphaynes.com\/wp-content\/uploads\/2017\/02\/Unity.png 1324w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<p>Since I made my TurnOnLight and TurnOffLight functions public, it&#8217;s easy to connect my buttons with the correct parameters.<\/p>\n<p><a href=\"https:\/\/kiphaynes.com\/wpress\/wp-content\/uploads\/2017\/02\/BottonConnect.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-314\" src=\"https:\/\/kiphaynes.com\/wpress\/wp-content\/uploads\/2017\/02\/BottonConnect.png\" alt=\"BottonConnect\" width=\"764\" height=\"296\" srcset=\"https:\/\/kiphaynes.com\/wp-content\/uploads\/2017\/02\/BottonConnect.png 764w, https:\/\/kiphaynes.com\/wp-content\/uploads\/2017\/02\/BottonConnect-300x116.png 300w\" sizes=\"auto, (max-width: 764px) 100vw, 764px\" \/><\/a><\/p>\n<p>And here is my c# code:<\/p>\n<pre><code>\nusing UnityEngine;\nusing System.Collections;\nusing System.IO.Ports;\npublic class MenuScript : MonoBehaviour {\n\npublic string MyComPort = \"COM2\";\/\/This should be accessible from a config file\n\npublic SerialPort serial;\nvoid Start() {\n\nserial = new SerialPort(MyComPort, 9600);\n}\n\n\/\/ Use this for initialization\npublic void TurnOnLight (int LightNum) {\nif (serial.IsOpen == false)\nserial.Open();\nif (LightNum == 1) serial.Write(\"A\");\nif (LightNum == 2) serial.Write(\"B\");\nif (LightNum == 3) serial.Write(\"C\");\nif (LightNum == 4) serial.Write(\"D\");\n}\n\n\/\/ Update is called once per frame\npublic void TurnOffLight (int LightNum) {\n  if (serial.IsOpen == false)\n  serial.Open();\n  if (LightNum == 1) serial.Write(\"a\");\n  if (LightNum == 2) serial.Write(\"b\");\n  if (LightNum == 3) serial.Write(\"c\");\n  if (LightNum == 4) serial.Write(\"d\");\n  }\n}\n\n<\/code><\/pre>\n<p>As you can see, I&#8217;m just writing A\/B\/C\/D and a\/b\/c\/d to the COM port to message the Arduino.<\/p>\n<p>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&#8217;s correct here.<\/p>\n<p>Now to my Arduino sketch:<\/p>\n<p>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.<\/p>\n<pre><code>\nint led1 = 5;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ the PWM pin the LED is attached to\nint led2 = 9;\nint led3 = 10;\nint led4 = 11;<\/code>\n\nint currentval_Led1 =0;\nint currentval_Led2 =0;\nint currentval_Led3 =0;\nint currentval_Led4 =0;\n\nint brightness = 0;\u00a0\u00a0\u00a0 \/\/ how bright the LED is\nint fadeAmount = 5;\u00a0\u00a0\u00a0 \/\/ how many points to fade the LED by\nunsigned long StartTime;\nunsigned long ElapsedTime;\nunsigned long CurrentTime;\nint data;\n\/\/ the setup routine runs once when you press reset:\nvoid setup() {\nSerial.begin (9600);\npinMode(led1, OUTPUT);\npinMode(led2, OUTPUT);\npinMode(led3, OUTPUT);\npinMode(led4, OUTPUT);\n}\nvoid loop() {\nif (Serial.available())\n{\ndata = Serial.read();\nif(data == 'A')\u00a0\u00a0 { fademyled (led1,1); fademyled (led2,1);}\nif(data == 'a') { fademyled (led1,0); fademyled (led2,0);}\n\/\/ and so on.. B\/C\/D\n}\n}\n\nvoid fademyled (int targetled, int onoff){\nSerial.println(\"FadeLedStart\");\nStartTime = millis();\n\nSerial.print(\"LED Values =\");\n\nif (targetled==led1) brightness=currentval_Led1;\nif (targetled==led2) brightness=currentval_Led2;\n\nif (onoff ==1){\nwhile (brightness &lt;= 255)\n{\nanalogWrite(targetled, brightness);\nbrightness = brightness + fadeAmount;\ndelay(60);\n}\nbrightness =255; \/\/(just in case if goes under from changing fade variables above)\n}\nif (onoff ==0){\nwhile (brightness &gt;= 0)\n{\nanalogWrite(targetled, brightness);\nbrightness = brightness - fadeAmount;\ndelay(30);\n}\nbrightness =0; \/\/(just in case if goes under from changing fade variables above)\n}\n\/\/Read stored values\nif (targetled==led1) {currentval_Led1 = brightness;}\nif (targetled==led2) {currentval_Led2 = brightness;}\nif (targetled==led3) {currentval_Led3 = brightness;}\nif (targetled==led4) {currentval_Led4 = brightness;}\n\nCurrentTime = millis();\nElapsedTime=CurrentTime-StartTime;\nSerial.println(ElapsedTime);\n\nSerial.println(\"Done. Led Values should be: \");\nSerial.println(currentval_Led1);\nSerial.println(currentval_Led2);\n\n}\n<\/pre>\n<p>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<a href=\"http:\/\/www.mouser.com\/search\/ProductDetail.aspx?r=942-IRLB8721PBF\"> this 30A MOSFET<\/a> 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.<\/p>\n<p><a href=\"https:\/\/kiphaynes.com\/wpress\/wp-content\/uploads\/2017\/02\/TO_220_3_t.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-310\" src=\"https:\/\/kiphaynes.com\/wpress\/wp-content\/uploads\/2017\/02\/TO_220_3_t.jpg\" alt=\"TO_220_3_t\" width=\"150\" height=\"181\" \/><\/a><\/p>\n<p>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,\u00a0 It worked beautifully. Here is the circuit that I used, thanks to <a href=\"https:\/\/learn.adafruit.com\/rgb-led-strips\/usage\">Adafruit!<\/a><\/p>\n<p><a href=\"https:\/\/kiphaynes.com\/wpress\/wp-content\/uploads\/2017\/02\/rgb-led-strips-mosfets.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-309\" src=\"https:\/\/kiphaynes.com\/wpress\/wp-content\/uploads\/2017\/02\/rgb-led-strips-mosfets-1024x763.png\" alt=\"rgb-led-strips-mosfets\" width=\"1024\" height=\"763\" srcset=\"https:\/\/kiphaynes.com\/wp-content\/uploads\/2017\/02\/rgb-led-strips-mosfets-1024x763.png 1024w, https:\/\/kiphaynes.com\/wp-content\/uploads\/2017\/02\/rgb-led-strips-mosfets-300x223.png 300w, https:\/\/kiphaynes.com\/wp-content\/uploads\/2017\/02\/rgb-led-strips-mosfets-768x572.png 768w, https:\/\/kiphaynes.com\/wp-content\/uploads\/2017\/02\/rgb-led-strips-mosfets.png 1647w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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<\/p>\n<p><span class=\"xf__dots\">&#8230;<\/span><a class=\"xf__more xf__button\" href=\"https:\/\/kiphaynes.com\/?p=306\">Read More<\/a><\/p>\n","protected":false},"author":2,"featured_media":308,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,4,2],"tags":[],"class_list":["post-306","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-fun","category-learn","category-technology","xf__entry"],"_links":{"self":[{"href":"https:\/\/kiphaynes.com\/index.php?rest_route=\/wp\/v2\/posts\/306","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kiphaynes.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kiphaynes.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kiphaynes.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/kiphaynes.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=306"}],"version-history":[{"count":4,"href":"https:\/\/kiphaynes.com\/index.php?rest_route=\/wp\/v2\/posts\/306\/revisions"}],"predecessor-version":[{"id":626,"href":"https:\/\/kiphaynes.com\/index.php?rest_route=\/wp\/v2\/posts\/306\/revisions\/626"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kiphaynes.com\/index.php?rest_route=\/wp\/v2\/media\/308"}],"wp:attachment":[{"href":"https:\/\/kiphaynes.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=306"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kiphaynes.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=306"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kiphaynes.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=306"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}