Adding Smarts and Color to an IKEA Lamp

WLED helped me turn a basic, inexpensive owl lamp into something fun. Owl show you how.

Posted May 20, 2021 (Revised May 21, 2021) Home AutomationHardwareLED LightingDIY

When it comes to the smart home, my number one priority is functionality. When I'm deciding what devices to buy and what projects to tackle, I tend to prioritize the ones that will legitimately make life easier.

That being said, there is definitely room for fun in the smart home as well, and one of the best ways to easily add a little fun to your home is with some multicolored LED lighting. The open-source WLED software has made these types of projects accessible to a lot more people, both in terms of price point and work effort. At the start of the pandemic last year, the first big project I tackled was converting a plain white LED owl lamp from IKEA into a multicolored light show for my daughter's room. Read on, and I'll show you how it's done.

Materials

You will need the following items:

All prices are as of the publication date of this post and are subject to change. Amazon links from this page may go through the Amazon affiliate program, which helps me to earn a small commission on purchases made through the link to help support the site. Purchasing through the affiliate link does not change the price on your end.

  • A lamp to retrofit. I used the IKEA SOLBO ($16.99 - click here), but anything similar will work. Pick something you think will look nice for your particular project.
  • An ESP8266 board ($16.99 - click here): I suggest the four-pack, as it is a bit more economical. If you get the DIY bug and want to tackle more projects after this one, it's good to have more of these versatile little boards. In addition to LED lighting, they can also be used for sensors of a variety of types, and countless other projects. I'll also say that since they are so cheap, it's good to have extra on hand off the bat in case you mess up and accidentally "brick" a board, rendering it unusable.
  • Individually addressable LED strips ($16.99 - click here): I recommend these WS2812B's, but there are a lot of different options out there. If you really want to get into the weeds, The Hook Up has an excellent video comparing the different types of addressable LED strips and their features. In a nutshell, though, an individually addressable LED strip is a strip of LED lights where each light can be set to a different color, allowing for all sorts of fun effects.
  • Soldering iron ($16.99 - click here): This is great for the price. You'll need it to connect the LED's to the board.
  • Jumper wires ($5.99 - click here): This is optional but recommended for testing your project before soldering it together, especially if it's your first project. This will get you an assortment of connection types for a great price, and like the four-pack of ESP8266 boards, they are great to have on hand for future projects.
  • Alligator clips ($6.19 - click here): As with the jumper wires, these are optional, but very useful for testing purposes.
  • Power supply: For a bigger project, a dedicated external power supply is recommended. I've got some outdoor lighting I've done that uses a more complicated power supply setup, and that blog will be coming in a few weeks. For a small project like this, though, you can get by with a micro-USB cable and a standard phone charger brick. Just make sure the power brick is 5V and 2.4A.

Installing WLED

Before we start connecting anything together, we'll start by flashing our ESP8266 board with the WLED firmware. This is what will tell the board how to control the lighting, and it will also set up a small web server on the board that will allow us to communicate with it using the WLED mobile app, Home Assistant, and many other integrations.

First, you'll want to download NodeMCU-PyFlasher from here. Install the appropriate version for your operating system. This will allow your computer to communicate with the board and upload the firmware.

Next, grab the latest WLED firmware from here. Since we are using an ESP8266, not an ESP32, the filename ending in ESP8266.bin is the appropriate one.

The ESP32 is just a similar development board that is slightly more powerful and slightly more expensive. In more complex WLED setups, it can be useful, but the ESP8266 is suitable for this project.

Ignore the ones ending in 1M and 2M, as those are for specific boards that have memory limitations. As of the publication date of this tutorial, WLED_0.12.0_ESP8266.bin is the name of the file you want.

Now, use your micro-USB cable to connect your ESP8266 board to a USB port on your computer. If you run into issues at this point, try swapping cables, as you will need a USB cable that supports both power and data cables. Most do, but some do not, so for these steps, that would be the first thing to try if you encounter trouble.

Open the NodeMCU-PyFlasher software you installed. You should see something similar to this:

NodeMCU PyFlasher

Select the port your board is plugged into in the Serial Port dropdown (usually, the auto-detect will get it right, but if the flashing doesn't work the first try, try a different port - it won't hurt anything if you have the wrong port the first time). Then, click browse and select the WLED firmware file you downloaded, and select "Flash NodeMCU." In a minute or so, the flash process should complete, and the screen should give you a success message. Again, the first things to try if you run into issues with this step would be to try a different USB cable and switch the port in the flasher software.

If flashing is successful, go ahead and disconnect the ESP8266 board so we can start wiring it up.

Light it up

This is where the fun begins

Now we're getting to the good stuff. We'll be connecting the three wires on our addressable LED strip to the board and powering it all up. As I mentioned in the materials section, we'll power everything with a micro-USB cable to the ESP8266 board, which will output power to the lights on the VIN pin. In a bigger project, an external power supply would output power to both the lights and the board, and the VIN pin would be a power input rather than an output (and the micro-USB would not be used). If you want to go with anything more than about 100 lights, you'll want an external power supply, which I will elaborate on in my next WLED project walkthrough. For now, I've got 91 LED's in this owl lamp and micro-USB has served me well on it for about a year. The lights don't quite go to full brightness, especially for bright white, but this is only an accent light and gets plenty bright for my needs. The added complexity of an external power supply wasn't worth the hassle to squeeze out a little extra brightness.

Back to the rest of the wiring. The red wire on your addressable LEDs should be the power wire, especially if you bought the LEDs I recommended above. Meanwhile, back should be ground and green should be data. That being said, the color coding on these is not always consistent. I recommend double-checking the labeling on the strip itself and matching it to the wire colors. In the example below, +5V is your power, Di is data in, and G is ground.

In addition to checking the labeling of the strip, you should also check the direction. Data can only flow one way, so if you connect to the wrong side, your lights won't light up. In the picture below, you can see that there are arrows on the strips. Those indicate the direction the data flows, so make sure you are using the wires at the start of the strip in relation to the direction of the arrows when connecting to the board.

LED Strip

Power goes to the VIN pin on your ESP8266 board, ground goes to GND, and data goes to D4 ("You sunk my battleship!"). For most strips, there will be three wires bundled together with a connector, plus an extra red and white wire. The red and white wire are for power injection, which is only needed when connecting multiple wires together. There may be extra pre-stripped wire and a connector included; if so, go ahead and connect that now, and then connect the pre-stripped wires to the ESP8266 board using alligator clips or jumper wires. If there is no additional wire included, you can strip the ends yourself.

At this point, you can go ahead and plug your ESP8266 into the charging brick and start to set it up. It will create its own WiFi network called WLED-AP, which you can connect to with the password wled1234. You should be taken to a captive portal after connecting from your phone or computer, and you use that portal to do the initial setup to get your lights on your WiFi network. After setup is done, the lights will reboot, and then you can either find them by going to the IP address of the lights on your computer, or by using the WLED mobile app (download for Android here and iPhone here). For the remainder of the article, I'll be referencing the app for simplicity's sake, but assume that the same workflow applies in the web interface.

Configuring and Testing

WLED App

I'll briefly run through some of the key setup options, but you can also click here to view more details from the main WLED wiki. Access these through the Config menu in the WLED app.

  • WiFi Setup: Pretty self explanatory. If you need to move your lights to a new WiFi network, this is where you'd do it.
  • LED Preferences: For effects to run properly, you'll need to tell WLED how many individual lights you have connected. The strip I recommended previously is 120 LEDs, so you can put that in for now. However, these also can be cut at the connection between any two lights, so if you need to cut it down to size to fit your project, you would come back here at the end to specify the final count of LEDs. WLED makes a recommendation for the proper power supply to get the maximum bright white level out of your lights. In our case, since we're just using the phone charger, we'll want to enable the automatic brightness limited, and I recommend setting the maximum current to 850mA to stay well below your charger's amperage limit (especially since it is powering both the board and lights). The other thing you may need to adjust on this menu is the color order; if you are adjusting the light color in the app and things don't match up, your lights likely have a different color order than the default.
  • Security & Updates: This is the only other section I'd worry about for now. I recommend locking wireless (OTA) software updates for security purposes, so that nobody on your WiFi network can flash malicious firmware to the device. While the risk is relatively low, it's a good and easy step to take to protect yourself.

At this point, I'd recommend putting your lights through their paces a bit, both to familiarize yourself with the interface and to see if there are any issues encountered as you try out different brightness levels, colors, and effects. It will definitely take some time to learn about all the different effects and various options, but a good place to start is the palettes and effects list.

Putting it Together

Lamp in Progress

Once you're satisfied with the performance of the lights, it's time to assemble your creation. These steps will vary depending on the specific light you purchased, but at a high level, you'll need to do the following:

  1. Remove any existing wiring and bulbs from the existing light, without damaging the outside of it. For ours, I was able to just unscrew the bulb holder and wiring from the base.
  2. Mount the LED strips inside the lamp and cut any excess. There are a number of ways to do this. The easiest way would be to take something like a wooden rod and affix it to the center of the light, then wrap the LEDs around it. In my case, since the lamp was somewhat cone-shaped, I unraveled the center of toilet paper rolls and actually put them together to make a smaller cone inside the light (such a 2020 thing to do). This allowed all of the lights to be roughly the same distance from the outside of the fixture, so there wouldn't be too much trouble with some lights looking different because they were closer or further from the surface. I'd recommend measuring and confirming the length of lights you're going to put inside the fixture, then cut them to length and affix them. In most cases, the adhesive on the strips themselves should be enough to hold them, but you could add a little hot glue if you really want to be sure.
  3. Mount the ESP8266 inside the case and connect the wires. I put in screws on the bottom plate of the light to create standoffs to mount the board on with nuts. If you're not too concerned about the fixture being moved at all, you might be able to get away with jumper wires to connect the lights to the board, but I'd recommend soldering if you're comfortable with it.
  4. Connect the micro-USB cable to the board and route it out of the fixture in some fashion. If you're lucky, there may be an existing hole for a power cord that the cable fits through. Otherwise, you may need to drill a hole.
  5. Close up the fixture, plug the cable in, and enjoy! If you made any cuts to the strip during the assembly steps, be sure to go back in and adjust the number of LEDs in the WLED app.

Connecting to Home Assistant

There's a lot of fun you can have with your finished creation, just by using the app. However, if we truly want to make it smart, app control is not enough. Fortunately, WLED provides a robust set of APIs to allow just about anything to integrate with it. In my case, since I'm a Home Assistant fan, I'll briefly go over how to integrate with Home Assistant.

Add Integration

First, go to Settings -> Integrations. It's likely the lamp will be auto-discovered by Home Assistant. If not, you can still click "Add Integration" and find WLED there to add manually by IP address.

Giving your WLED device a DHCP reservation on your router is highly recommended to make sure that Home Assistant can always find it if you add it by IP.

You'll now have ability to control the device in the Home Assistant interface, but to automate, you can utilize the wled.effect or wled.preset service calls.

  • wled.effect: This allows you to apply any of the 100+ effects to your light.
  • wled.preset: In the WLED app, you can save up to 250 preset configurations that can be applied later. I contributed this service call to Home Assistant last year, and it allows you to apply any of those saved presets by preset number in Home Assistant. I'd suggest reading more on presets in the WLED wiki.

You can, of course, also use the light.turn_on service call to apply any normal lighting settings like color/brightness/color temperature, but I think the best way is to create your presets in the App and then apply them in Home Assistant.

What I currently am doing with this owl lamp is running an AppDaemon script to pick from a pre-defined list of "daytime" presets every 5 minutes during daytime hours, and then to set it to a more mellow preset at night so that my daughter can use it as a nightlight. It also brightens and changes to gradually more exciting effects in the morning hours to help let our daughter know it's time to wake up (not easy, since she's a night owl and not a morning person, just like her parents). Finally, it turns off when we're not home, as well.

AppDaemon is a Python-based library for writing Home Assistant automations. I choose to use it instead of the default Home Assistant automation engine because I prefer to write Python code, but you could create these automations just as easily with the built-in interface, or with Node-RED.

Here's the current code I use. There are some best practices that would make it more re-usable, such as allowing the entity_id to be specified as an argument in apps.yaml, but hopefully this can at least provide some inspiration.

class OwlLamp(hass.Hass):
  #owl LED lamp rotating effect
  def initialize(self):
    self.ps = 0
    self.timer = None

    if (self.noone_home() and self.get_state("input_boolean.guest_mode") == "off"):
      self.turn_off("light.owl_lamp")
    elif self.get_state("input_boolean.white_noise") == "on":
      if self.now_is_between("08:30:00", "09:00:00"):
        self.call_wled(2)
      elif self.now_is_between("09:00:00", "09:30:00"):
        self.call_wled(3)
      else:
        self.call_wled(1)
    else:
      self.call_wled(0)
    self.listen_state(self.wn_toggle, "input_boolean.white_noise")
    self.listen_state(self.trigger_change, "group.all_devices")

    runtime = datetime.time(8, 30, 0)
    self.run_daily(self.scheduled_update, runtime, mode=2)
    runtime = datetime.time(9, 0, 0)
    self.run_daily(self.scheduled_update, runtime, mode=3)
    runtime = datetime.time(9, 30, 0)
    self.run_daily(self.scheduled_update, runtime, mode=4)

  def wn_toggle(self, entity, attribute, old, new, kwargs):
        self.cancel_timer(self.timer)
        if new == "on":
            self.call_wled(1)
        else:
            self.call_wled(0)

  def trigger_change(self, entity, attribute, old, new, kwargs):
    if self.timer != None:
      self.cancel_timer(self.timer)
    if new == "not_home" and self.get_state("input_boolean.guest_mode" == "off"):
      self.turn_off("light.owl_lamp") #turn off, not home
    elif self.get_state("input_boolean.white_noise") == "on":
      self.call_wled(1) #turn on, nighttime
    else:
      self.call_wled(0) #turn on, daytime

  def preset_rotate(self, kwargs):
    self.call_wled(0)

  def scheduled_update(self, kwargs):
    if self.get_state("input_boolean.white_noise") == "on":
      if kwargs["mode"] == 4:
        self.turn_off("input_boolean.white_noise")
      else:
        self.call_wled(kwargs["mode"])

  def override(self, entity, attribute, old, new, kwargs):
    if new == "on":
      self.cancel_timer(self.timer)
    else:
      self.call_wled(0)

  def call_wled(self, mode):
    if mode == 0:
      new_ps = randint(1,16)
      while new_ps == self.ps:
        new_ps = randint(1,16)
      self.ps = new_ps
      self.call_service("wled/preset", entity_id="light.owl_lamp", preset=self.ps)
            self.timer = self.run_in(self.preset_rotate, 60*5)

    elif mode == 1: #during night or nap
      self.call_service("wled/preset", entity_id="light.owl_lamp", preset=17) #applies nighttime preset (17)
    elif mode == 2: #8:30 to 9 am
      self.call_service("wled/preset", entity_id="light.owl_lamp", preset=18) #applies morning preset (18)
    else: #9 to 9:30am
      self.call_service("wled/preset", entity_id="light.owl_lamp", preset=19) #applies morning preset (19)  	

After saving the above as owl.py, the app requires the following setup in apps.yaml:

owl_lamp:
  module: owl
  class: OwlLamp

If you have any questions about the code, feel free to comment below.

More Resources

Hopefully this helps to get you started. If you run into any trouble, feel free to chime in with a comment below and I'll be glad to try and help you work through it. And if you create something with WLED as well using this guide, be sure to share it in the comments as well!

There are a lot of other great resources out there for getting started with WLED. You can check out their main wiki here. There's much more to learn about WLED there, as I cannot possibly cover everything in this one blog post. The issues section on their GitHub page is also very active, and a good place to either ask questions or see if someone else has had a similar question that's already been answered. They also have a Discord server and a subreddit.

Enjoyed this post? Consider buying me a coffee to fuel the creation of more content.