LED strips are pretty great. They are very cheap; you can buy them through Amazon in 16 ft spools. You can stick them anywhere you want, and they are good for ambient lighting or for adding some excitement to a room. Using the physical remote that most come with may be acceptable, but making them WiFi connected seems much more fun.

The end result will be a fully WiFi controllable LED strip that you can set to any color.

Here’s a video demonstration.

What You Need

The LED strips I used are SMD 5050 LEDs. They are made out of flexible circuit board material with surface-mounted RGB LEDs. They usually come in a spool and you can cut them along predetermined sections. You can find them on Amazon with a simple search. Here’s a link to the ones I have (there are many different ones). On the strip there are four pads: 12V, R, G, and B. You control the LEDs by supplying a positive 12V to the 12V pin and then grounding any of the other pins completing the circuit, causing the corresponding color to light up. For example, if you ground the R pin then they will light up full red.

LED Strip

Below is a schematic for the internals of the strip if you are curious.

LED Strip Internal Schematic

Most strips already come with a controller that has a remote. However, to make them WiFi connected we are going to make a new controller. To control these strips we need a microcontroller, some transistors or MOSFETs, and WiFi capabilities. We could use an Arduino board for this but those can get expensive, especially after you add in the cost of an ethernet or WiFi shield. We can do better and use a relatively new microcontroller: the ESP8266.

This board is insane. It’s extremely cheap, like $5 cheap, and has full WiFi capabilities with easy to use libraries available for things like a HTTP server and sending and parsing UDP packets. And using some open-source software, we can program it just like an Arduino, with the Arduino IDE and everything! It also already has a bunch of digital input/output pins with 3.3V logic and it supports PWM (pulse width modulation) – more on this later – so we won’t need anything else to control the LED strip.

I recommend getting Adafruit’s ESP8266 HUZZAH breakout board. It has a voltage regulator and other things built-in that make it a lot easier to use. For the rest of this article I’ll assume this what you are using.

The Circuit

To make the circuit to control the LEDs you need a power supply. The LEDs need +12V although you can power them with as little as 9V and they will still work. The ESP8266 needs a regulated +3.3V but if you have the HUZZAH breakout board, which has a voltage regulator built-in, then you can power it with up to 16V.

I used a 12V regulated power supply to power both the ESP8266 breakout board and LED strip. The LEDs draw about 0.6 amps per meter, according to Adafruit, so plan accordingly.

Now it’s time to make the actual circuit. We need to hook up the +12V from the power supply to the V+ pin on the ESP8266 breakout board and to the +12V on the LED strip. Also, wire the GND pin on the ESP8266 to the GND from the power supply. This is very important because we need a common ground for all of this to function properly. We use transistors or MOSFETs to control the LEDs. We need three transistors, one for each r, g, and b. Hook up three of the output pins on the ESP8266 to each gate pin on the transistors. Then wire the source pin on each transistor to ground. And finally wire each drain pin to the corresponding pad on the LED strip. Here is the schematic:

Schematic Breadboard

  • A lot of transistors and MOSFETs have different pin orders so don’t use this as a reference. Look it up. I used N-channel MOSFETs.
  • Make sure you know which pin controls which color.

When we sent any of the three pins on the ESP8266 to HIGH, it switches the transistor, completing the circuit and lighting up the corresponding color. LEDs can only be set to full on or full off, so you might be wondering how we dim them or set them to custom color using just R, G, and B. Well to do this we can use something called pulse width modulation (PWM). PWM is essentially when you switch something on and off hundreds of times a second and vary the width of the on or off signal to control the intensity. So if the majority of the time it is on, then LEDs will appear brighter and vice-versa. You don’t really need to know the details of this but you can look it up if you are interested. All you need to know is you can use the analogWrite Arduino function to control the intensity or brightness.

The Code

In my opinion, the easiest way to program the ESP8266 is to use the Arduino IDE. There is some set up and installation you need to do that I won’t cover here. There are plenty of tutorials on this elsewhere. I’ll assume you already have everything set up.

Here is all of my code that runs on the ESP8266. It is not well written by any means, but it works. Feel free to copy and paste this for your own use.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char* ssid      = "ssid";
const char* password  = "password";

unsigned int port = 2390;

char packetBuffer[255];
char ReplyBuffer[] = "acknowledged";

WiFiUDP Udp;

const int REDPIN = 12;
const int GREENPIN = 16;
const int BLUEPIN = 13;

void setup()
{
  // set pin modes
  pinMode(REDPIN, OUTPUT);
  pinMode(GREENPIN, OUTPUT);
  pinMode(BLUEPIN, OUTPUT);
  pinMode(ledPin, OUTPUT);

  digitalWrite(REDPIN, HIGH);
  delay(300);
  digitalWrite(REDPIN, LOW);
  digitalWrite(GREENPIN, HIGH);
  delay(300);
  digitalWrite(GREENPIN, LOW);
  digitalWrite(BLUEPIN, HIGH);
  delay(300);
  digitalWrite(BLUEPIN, LOW);

  // begin serial and connect to WiFi
  Serial.begin(115200);
  delay(100);

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  Udp.begin(port);

}



int value = 0;

void loop()
{
  int packetSize = Udp.parsePacket();
  if(packetSize) {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remoteIp = Udp.remoteIP();
    Serial.print(remoteIp);
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    int len = Udp.read(packetBuffer, 255);
    if (len > 0) {
      packetBuffer[len] = 0;
    }    
    Serial.println("Contents:");
    Serial.println(packetBuffer);
    Serial.write(packetBuffer);
    Serial.println();

    // TEMP parse data from packet
    char * temp;
    Serial.print("Splitting string \"");
    Serial.print(packetBuffer);
    Serial.println("\"");

    int r = 0;
    int b = 0;
    int g = 0;

    temp = strtok (packetBuffer,":");
    Serial.println(temp);
    r = atoi(temp);

    if(temp != NULL){
      temp = strtok (NULL,":");
      Serial.println(temp);
      g = atoi(temp);
    }

    if(temp != NULL){
      temp = strtok (NULL,":");
      Serial.println(temp);
      b = atoi(temp);
    }

    Serial.println();
    Serial.println(r);
    Serial.println(g);
    Serial.println(b);

    analogWrite(REDPIN, r);
    analogWrite(GREENPIN, g);
    analogWrite(BLUEPIN, b);

    // send a reply, to the IP address and port
    // that sent us the packet we received
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();

  }


}
  • Make sure you replace “ssid” and “password” with your network information. Don’t rename the variables just replace what is in the quotes.
  • Set the variables REDPIN, GREENPIN, and BLUEPIN at the top to the pins that control the corresponding color.
  • The port variable is what port it will listen for packets on.

This code basically works by connecting to the network then opening a port and listening for UDP packets. When a packet is received it parses it, sets the LEDs to the color specified, and sends a reply that says "acknowledged". The packet it receives must be in the form red:green:blue with three integers between 0 and 1023. 0 is off and 1023 is full brightness. So if you wanted to, for example, make the LEDs purple you would set red and blue to full brightness and green to 0. The packet would look like this, 1023:0:1023.

Feedback on this code is welcome as I am not very experienced in C++ or C and a lot of is from copying and pasting.

Controller / Client

With everything we have done so far, we should now be able to control the LED strip over WiFi. First we need to find the IP address of the ESP8266. You can find it by using the serial monitor with it plugged into the computer. It will output information as it connects.

Using a packet-sender tool such as Packet Sender we can send a packet with UDP to the IP address we just found over the port specified in the code (2390 is the default). Make sure the packet is a string with format red:green:blue (red, green, blue being integers between 0 and 1023). If everything is working correctly the LEDs should light up based on the numbers sent.

This is not very convenient to do. Every time we want to change the color we need to use this tool and manually type in the color brightness for r, g, b. Something more useful would be a simple app on a phone or computer.

I made an Android app for this reason. You can view the code and download it from this GitHub repository. With this app you can control the LED strip from you phone. The interface is very crude and simple. It consists of three sliders, one for each red, green, and blue. You move the sliders to change the color of the lights. I was going to implement a color picker except the LEDs are not well color-balanced so the color you pick on the screen would not look the same as the color displayed on the lights.

This app will automatically broadcast UDP packets and will try to discover a LED strip on the local network. Currently it only has support for one LED controller per network. How to develop an app like this is outside of the scope of this article but I will describe how it works on a high-level. You can check out the GitHub repository if you want to learn more about it.

When the app starts (actually every time the MainActivity starts) it will repeatedly send out packets to the network broadcast address, so all devices on the network will receive them, with the contents 0:0:0 and listens for a response. It keeps doing this until it receives a response packet with the contents acknowledged. Because the controller is programmed to respond to every packet with the string acknowledged we know that this is our LED controller. The app then takes the IP of the LED controller it just discovered and stores it in memory. While all of this is going on a progress dialog is shown on the screen, after it is done it goes away.

After the app finds the IP of the controller it shows three sliders (SeekBar in Android speak) for red, green, and blue. When any of the sliders’ positions are changed, a packet is sent to the LED controller telling it to change colors. It sends out a packet even while a slider is being dragged, so the result is a smooth and continuous color change.

  • Note: this app assumes the the LED controller uses port 2390 for communication

App Screenshot App Screenshot

Conclusion

If you have followed (maybe struggled) along you should now have a functioning wifi controllable LED strip. Let me know what you think of this project. Feedback is very much appreciated as this is my first post like this.

More

The end result is a somewhat primitive way to control a LED strip with your phone. There are many ways to improve this. You could:

  • Make a better Android app with more features, such as scenes, timers, etc.
  • Design a better protocol for communication with the LED controller. Mine is very basic, you cannot get the current state of the lights and every time the Android app searches for LED controllers the lights get turned off. A much better protocol could be implemented with these features and more while creating and parsing packets on a bit level. Look at LIFX’s LAN protocol for inspiration.
  • Design and print a PCB instead of using a breadboard or perfboard.
  • Make an app for other systems, such as an iOS or web app.